forked from github/server
finalize spell cost bugfix. fix familiar spellcost calculation tests. remove debug names from tests.
This commit is contained in:
parent
c8e975333b
commit
250c098bf6
|
@ -136,11 +136,9 @@ function test_fleeing_units_can_be_transported()
|
|||
u1.number = 100
|
||||
u1:add_order("ATTACKIEREN " .. itoa36(u2.id))
|
||||
u2.number = 100
|
||||
u2.name = 'Passagier'
|
||||
u2:add_order("FAHREN " .. itoa36(u3.id))
|
||||
u2:add_order("KAEMPFE FLIEHE")
|
||||
u3.number = 100
|
||||
u3.name = 'Transporter'
|
||||
u3:add_order("KAEMPFE FLIEHE")
|
||||
u3:add_order("TRANSPORT " .. itoa36(u2.id))
|
||||
u3:add_order("NACH O ")
|
||||
|
@ -642,7 +640,6 @@ function test_laen2()
|
|||
u1:set_skill("mining", 15)
|
||||
u1:clear_orders()
|
||||
u1:add_order("MACHEN Laen")
|
||||
u1.name = "Laenmeister"
|
||||
|
||||
local b = building.create(r, "mine")
|
||||
b.size = 10
|
||||
|
|
|
@ -115,7 +115,6 @@ function test_dwarf_bonus()
|
|||
local u = unit.create(faction.create("dwarf"), r)
|
||||
assert_equal("dwarf", u.faction.race)
|
||||
assert_equal("dwarf", u.race)
|
||||
u.faction.name = "Zwerge"
|
||||
u.number = 10
|
||||
u:set_skill("mining", 1)
|
||||
u:add_order("MACHE EISEN")
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
local tcname = 'tests.e2.familiars'
|
||||
local lunit = require('lunit')
|
||||
if _VERSION >= 'Lua 5.2' then
|
||||
_ENV = module(tcname, 'seeall')
|
||||
else
|
||||
module(tcname, lunit.testcase, package.seeall)
|
||||
end
|
||||
|
||||
function setup()
|
||||
eressea.game.reset()
|
||||
eressea.settings.set("nmr.removenewbie", "0")
|
||||
eressea.settings.set("nmr.timeout", "0")
|
||||
eressea.settings.set("NewbieImmunity", "0")
|
||||
eressea.settings.set("rules.food.flags", "4")
|
||||
eressea.settings.set("rules.peasants.growth.factor", "0")
|
||||
eressea.settings.set("magic.resist.enable", "0")
|
||||
eressea.settings.set("magic.fumble.enable", "0")
|
||||
eressea.settings.set("magic.regeneration.enable", "0")
|
||||
end
|
||||
|
||||
local function setup_familiars(f, r)
|
||||
f.magic = 'gwyrrd'
|
||||
local uf = unit.create(f, r)
|
||||
uf.magic = 'gray'
|
||||
local u = unit.create(f, r)
|
||||
u.magic = 'gwyrrd'
|
||||
u:set_skill('magic', 9)
|
||||
u.familiar = uf
|
||||
return u, uf
|
||||
end
|
||||
|
||||
function test_moneyspell()
|
||||
local r = region.create(0, 0, "plain")
|
||||
local f = faction.create('human')
|
||||
local um, uf = setup_familiars(f, r)
|
||||
um.aura = 9
|
||||
um:add_order('ZAUBERE STUFE 9 Viehheilung')
|
||||
process_orders()
|
||||
assert_equal(0, um.aura)
|
||||
assert_equal(450, um:get_item('money'))
|
||||
end
|
||||
|
||||
function test_moneyspell_through_familiar()
|
||||
-- casting magician's spell with the familiar: double cost
|
||||
local r = region.create(0, 0, "plain")
|
||||
local f = faction.create('human')
|
||||
local um, uf = setup_familiars(f, r)
|
||||
um.aura = 12
|
||||
uf:add_order('ZAUBERE STUFE 3 Viehheilung')
|
||||
process_orders()
|
||||
assert_equal(0, uf:get_skill('magic'))
|
||||
assert_equal(12, um.aura) -- cannot cast, familiar needs magic skill
|
||||
assert_equal(0, uf:get_item('money'))
|
||||
assert_equal(0, um:get_item('money'))
|
||||
|
||||
uf:set_skill('magic', 2) -- can cast no higher than level 2
|
||||
process_orders()
|
||||
assert_equal(8, um.aura) -- double the cost
|
||||
assert_equal(100, uf:get_item('money'))
|
||||
assert_equal(0, um:get_item('money'))
|
||||
|
||||
um:set_skill('magic', 4) -- use at most half of skill
|
||||
uf:set_skill('magic', 1) -- too low for level 2 spell, cast at level 1
|
||||
process_orders()
|
||||
assert_equal(6, um.aura) -- double cost of level 1
|
||||
assert_equal(150, uf:get_item('money'))
|
||||
assert_equal(0, um:get_item('money'))
|
||||
end
|
||||
|
||||
function test_moneyspell_as_familiar()
|
||||
-- familiar has the spell and has magic skills: regular spellcasting rules apply
|
||||
local r = region.create(0, 0, "plain")
|
||||
local f = faction.create('human')
|
||||
local um, uf = setup_familiars(f, r)
|
||||
um.aura = 9
|
||||
uf.aura = 20
|
||||
uf:set_skill('magic', 10)
|
||||
uf:add_spell('earn_silver#gwyrrd')
|
||||
uf:add_order('ZAUBERE STUFE 10 Viehheilung')
|
||||
process_orders()
|
||||
assert_equal(500, uf:get_item('money'))
|
||||
assert_equal(10, uf.aura)
|
||||
assert_equal(9, um.aura)
|
||||
end
|
|
@ -22,7 +22,6 @@ function test_ship_requires_skill()
|
|||
assert_not_nil(r2)
|
||||
local f = faction.create("human", "fake@eressea.de", "de")
|
||||
local u1 = unit.create(f, r1, 1)
|
||||
u1.name = "fake"
|
||||
u1.ship = ship.create(r1, "longboat")
|
||||
u1:clear_orders()
|
||||
u1:add_order("NACH O")
|
||||
|
|
|
@ -45,7 +45,6 @@ function test_stealth_faction_on()
|
|||
end
|
||||
|
||||
function test_stealth_faction_other()
|
||||
u.name = "Enno"
|
||||
u:clear_orders()
|
||||
u:add_order("TARNEN PARTEI NUMMER " .. itoa36(f.id))
|
||||
|
||||
|
|
|
@ -256,7 +256,6 @@ function test_promote_after_recruit()
|
|||
local r1 = region.create(0, 0, 'plain')
|
||||
local r2 = region.create(1, 0, 'plain')
|
||||
local u1 = unit.create(f, r1, 1)
|
||||
u1.name = 'Xolgrim'
|
||||
local u2 = unit.create(f, r2, 55)
|
||||
u2:add_order('REKRUTIERE 1')
|
||||
u1:add_order('BEFOERDERE')
|
||||
|
|
167
src/magic.c
167
src/magic.c
|
@ -267,16 +267,12 @@ bool FactionSpells(void)
|
|||
return rule != 0;
|
||||
}
|
||||
|
||||
int mage_get_spell_level(const sc_mage *mage, const spell *sp) {
|
||||
spellbook *book = mage_get_spellbook(mage);
|
||||
spellbook_entry *sbe = spellbook_get(book, sp);
|
||||
return sbe ? sbe->level : 0;
|
||||
}
|
||||
|
||||
int get_spell_level_mage(const spell * sp, void * cbdata)
|
||||
{
|
||||
sc_mage *mage = (sc_mage *)cbdata;
|
||||
return mage_get_spell_level(mage, sp);
|
||||
spellbook *book = mage_get_spellbook(mage);
|
||||
spellbook_entry *sbe = spellbook_get(book, sp);
|
||||
return sbe ? sbe->level : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -502,12 +498,21 @@ sc_mage *create_mage(unit * u, magic_t mtyp)
|
|||
/* ------------------------------------------------------------- */
|
||||
/* Funktionen fuer die Bearbeitung der List-of-known-spells */
|
||||
|
||||
int unit_spell_level(const unit *u, const struct spell *sp)
|
||||
{
|
||||
spellbook *book = unit_get_spellbook(u);
|
||||
spellbook_entry *sbe = book ? spellbook_get(book, sp) : NULL;
|
||||
if (sbe) {
|
||||
return sbe->level;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool u_hasspell(const unit *u, const struct spell *sp)
|
||||
{
|
||||
spellbook * book = unit_get_spellbook(u);
|
||||
spellbook_entry * sbe = book ? spellbook_get(book, sp) : NULL;
|
||||
if (sbe) {
|
||||
return sbe->level <= effskill(u, SK_MAGIC, NULL);
|
||||
int level = unit_spell_level(u, sp);
|
||||
if (level > 0) {
|
||||
return level <= effskill(u, SK_MAGIC, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -826,10 +831,9 @@ void pay_spell(unit * mage, const unit *caster, const spell * sp, int cast_level
|
|||
*/
|
||||
bool knowsspell(const region * r, const unit * u, const spell * sp)
|
||||
{
|
||||
UNUSED_ARG(r);
|
||||
assert(sp);
|
||||
int level = unit_spell_level(u, sp);
|
||||
/* steht der Spruch in der Spruchliste? */
|
||||
return u_hasspell(u, sp);
|
||||
return level > 0;
|
||||
}
|
||||
|
||||
/* Um einen Spruch zu beherrschen, muss der Magier die Stufe des
|
||||
|
@ -2479,16 +2483,16 @@ static bool is_moving_ship(ship * sh)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int default_spell_level(const sc_mage *mage, const spell *sp) {
|
||||
static int default_spell_level(const unit *u, const spell *sp) {
|
||||
if (sp && sp->components) {
|
||||
const struct spell_component *spc;
|
||||
for (spc = sp->components; spc->type; ++spc) {
|
||||
if (spc->cost != SPC_FIX) {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mage_get_spell_level(mage, sp);
|
||||
return unit_spell_level(u, sp);
|
||||
}
|
||||
|
||||
#define MAX_PARAMETERS 48
|
||||
|
@ -2503,7 +2507,7 @@ static castorder *cast_cmd(unit * u, order * ord)
|
|||
spell *sp = NULL;
|
||||
plane *pl;
|
||||
spellparameter *args = NULL;
|
||||
unit * mage = u;
|
||||
unit * mage = NULL;
|
||||
param_t param;
|
||||
|
||||
if (LongHunger(u)) {
|
||||
|
@ -2553,40 +2557,50 @@ static castorder *cast_cmd(unit * u, order * ord)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* skill = der maximale durch das Magietalent erlaubte Level.
|
||||
* Entspricht dem Talent des Zaubernden, oder im Falle, dass ein
|
||||
* Vertrauter einen Spruch seines Magiers zaubert, dessen halbes Talent.
|
||||
*/
|
||||
skill = effskill(u, SK_MAGIC, NULL);
|
||||
sp = unit_getspell(u, s, u->faction->locale);
|
||||
/* Vertraute koennen auch Zauber sprechen, die sie selbst nicht
|
||||
* koennen. unit_getspell findet aber nur jene Sprueche, die
|
||||
* die Einheit beherrscht. */
|
||||
if (!sp && is_familiar(u)) {
|
||||
|
||||
/*
|
||||
* u = Die Einheit, die den Befehl gegeben hat.
|
||||
* mage = Die Einheit, deren Spruchliste und Aura benutzt wird.
|
||||
*
|
||||
* Vertraute koennen auch Zauber sprechen, die sie selbst nicht
|
||||
* koennen. `unit_getspell` findet aber nur jene Sprueche, die
|
||||
* die Einheit beherrscht. In diesem Fall ist `familiar` der Vertraute.
|
||||
*/
|
||||
if (sp) {
|
||||
/* wir zaubern selbst */
|
||||
mage = u;
|
||||
}
|
||||
else if (skill > 0) {
|
||||
/* als Vertrauter suchen wir einen Spender-Magier mit dem Spruch */
|
||||
mage = get_familiar_mage(u);
|
||||
if (mage) {
|
||||
familiar = u;
|
||||
int limit = effskill(mage, SK_MAGIC, NULL) / 2;
|
||||
if (limit < skill) {
|
||||
skill = limit;
|
||||
}
|
||||
sp = unit_getspell(mage, s, mage->faction->locale);
|
||||
}
|
||||
else {
|
||||
/* somehow, this familiar has no mage! */
|
||||
log_error("cast_cmd: familiar %s is without a mage?\n", unitname(u));
|
||||
mage = u;
|
||||
if (sp->sptyp & NOTFAMILIARCAST) {
|
||||
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
|
||||
cmistake(u, ord, 177, MSG_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
familiar = u;
|
||||
}
|
||||
}
|
||||
|
||||
/* OBS: hier kein else! */
|
||||
if (!sp) {
|
||||
/* Fehler 'Spell not found' */
|
||||
cmistake(u, ord, 173, MSG_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* um testen auf spruchnamen zu unterbinden sollte vor allen
|
||||
* fehlermeldungen die anzeigen das der magier diesen Spruch
|
||||
* nur in diese Situation nicht anwenden kann, noch eine
|
||||
* einfache Sicherheitspruefung kommen */
|
||||
if (!knowsspell(r, u, sp)) {
|
||||
/* vorsicht! u kann der familiar sein */
|
||||
if (!familiar) {
|
||||
cmistake(u, ord, 173, MSG_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (sp->sptyp & ISCOMBATSPELL) {
|
||||
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
|
||||
cmistake(u, ord, 174, MSG_MAGIC);
|
||||
|
@ -2627,19 +2641,45 @@ static castorder *cast_cmd(unit * u, order * ord)
|
|||
cmistake(u, ord, 176, MSG_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */
|
||||
if (familiar) {
|
||||
/* Magier zaubert durch Vertrauten: keine Fernzauber erlaubt */
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast",
|
||||
"mage", mage));
|
||||
return 0;
|
||||
}
|
||||
if (range > 1024) {
|
||||
/* (2^10) weiter als 10 Regionen entfernt */
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "spellfail::nocontact",
|
||||
"target", target_r));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (familiar) {
|
||||
/*
|
||||
* Magier zaubert durch Vertrauten: Doppelte Kosten.
|
||||
*
|
||||
* Das hier über range zu machen ist ein Hack, deshalb passiert es erst
|
||||
* nach allen anderen Range-Checks.
|
||||
*/
|
||||
range *= 2;
|
||||
}
|
||||
|
||||
skill = effskill(mage, SK_MAGIC, NULL);
|
||||
/**
|
||||
* level = Die Stufe, auf der gezaubert werden soll.
|
||||
* Kann nicht höher sein als das Talent des Zaubernden, oder im
|
||||
* Falle, dass ein Vertrauter einen Spruch seines Magiers zaubert,
|
||||
* nicht höher als dessen halbes Talent.
|
||||
*/
|
||||
if (level < 0) {
|
||||
level = default_spell_level(get_mage(mage), sp);
|
||||
if (level < 0) {
|
||||
level = default_spell_level(mage, sp);
|
||||
if (level <= 0) {
|
||||
level = skill;
|
||||
}
|
||||
if (level > skill) {
|
||||
/* die Einheit ist nicht erfahren genug fuer diesen Zauber */
|
||||
cmistake(u, ord, 169, MSG_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!(sp->sptyp & SPELLLEVEL)) {
|
||||
/* Stufenangabe bei nicht Stufenvariierbaren Spruechen abfangen */
|
||||
|
@ -2649,45 +2689,12 @@ static castorder *cast_cmd(unit * u, order * ord)
|
|||
"mage region command", u, u->region, ord));
|
||||
}
|
||||
}
|
||||
|
||||
if (level > skill) {
|
||||
/* die Einheit ist nicht erfahren genug fuer diesen Zauber */
|
||||
cmistake(u, ord, 169, MSG_MAGIC);
|
||||
return 0;
|
||||
/* STUFE kann nicht mehr als das erlaubte Maximum sein */
|
||||
level = skill;
|
||||
}
|
||||
|
||||
/* Vertrautenmagie */
|
||||
/* Kennt der Vertraute den Spruch, so zaubert er ganz normal.
|
||||
* Ansonsten zaubert der Magier durch seinen Vertrauten, dh
|
||||
* zahlt Komponenten und Aura. Dabei ist die maximale Stufe
|
||||
* die des Vertrauten!
|
||||
* Der Spruch wirkt dann auf die Region des Vertrauten und
|
||||
* gilt nicht als Farcasting. */
|
||||
if (familiar) {
|
||||
if ((sp->sptyp & NOTFAMILIARCAST)) {
|
||||
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
|
||||
cmistake(u, ord, 177, MSG_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
if (mage != familiar) { /* Magier zaubert durch Vertrauten */
|
||||
int sk;
|
||||
if (range > 1) { /* Fehler! Versucht zu Farcasten */
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast",
|
||||
"mage", mage));
|
||||
return 0;
|
||||
}
|
||||
sk = effskill(mage, SK_MAGIC, NULL);
|
||||
if (distance(mage->region, r) > sk) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar",
|
||||
"mage", mage));
|
||||
return 0;
|
||||
}
|
||||
/* mage auf magier setzen, level anpassen, range fuer Erhoehung
|
||||
* der Spruchkosten nutzen */
|
||||
range *= 2;
|
||||
sk /= 2;
|
||||
if (level > sk) level = sk;
|
||||
}
|
||||
}
|
||||
/* Weitere Argumente zusammenbasteln */
|
||||
if (sp->parameter) {
|
||||
char *params[MAX_PARAMETERS];
|
||||
|
|
|
@ -192,7 +192,6 @@ extern "C" {
|
|||
enum magic_t mage_get_type(const struct sc_mage *mage);
|
||||
const struct spell *mage_get_combatspell(const struct sc_mage *mage, int nr, int *level);
|
||||
struct spellbook * mage_get_spellbook(const struct sc_mage * mage);
|
||||
int mage_get_spell_level(const struct sc_mage *mage, const struct spell *sp);
|
||||
int mage_get_spellpoints(const struct sc_mage *m);
|
||||
void mage_set_spellpoints(struct sc_mage *m, int aura);
|
||||
int mage_change_spellpoints(struct sc_mage *m, int delta);
|
||||
|
@ -201,6 +200,7 @@ extern "C" {
|
|||
void unit_set_magic(struct unit *u, enum magic_t mtype);
|
||||
struct spellbook * unit_get_spellbook(const struct unit * u);
|
||||
void unit_add_spell(struct unit * u, struct spell * sp, int level);
|
||||
int unit_spell_level(const struct unit *u, const struct spell *sp);
|
||||
|
||||
bool is_mage(const struct unit *u);
|
||||
/* gibt true, wenn u->mage gesetzt. */
|
||||
|
@ -222,7 +222,9 @@ extern "C" {
|
|||
bool u_hasspell(const struct unit *u, const struct spell *sp);
|
||||
/* prueft, ob der Spruch in der Spruchliste der Einheit steht. */
|
||||
void pick_random_spells(struct faction *f, int level, struct spellbook * book, int num_spells);
|
||||
bool knowsspell(const struct region *r, const struct unit *u,
|
||||
bool knowsspell(
|
||||
const struct region *r,
|
||||
const struct unit *u,
|
||||
const struct spell * sp);
|
||||
/* prueft, ob die Einheit diesen Spruch gerade beherrscht, dh
|
||||
* mindestens die erforderliche Stufe hat. Hier koennen auch Abfragen
|
||||
|
|
Loading…
Reference in New Issue