Bug 2517: Vertraute ohne eigene Zauber reparieren

Trennung von caster und mage in spells.c
This commit is contained in:
Enno Rehling 2018-11-17 21:24:59 +01:00
parent b181618b53
commit d2389fa87b
10 changed files with 424 additions and 353 deletions

View file

@ -96,7 +96,6 @@ function test_follow_ship()
local f = faction.create("human", "test@example.com", "de")
local u1 = unit.create(f, r1, 1)
local u2 = unit.create(f, r1, 1)
u2.name = 'Xolgrim'
u1:add_item("money", 100)
u2:add_item("money", 100)
u1.ship = ship.create(r1, "boat")

View file

@ -117,7 +117,6 @@ function test_familiar_cast()
u:add_spell("earn_silver#gwyrrd")
u:add_order('ARBEITE')
local uf = unit.create(f, r)
uf.magic = "gwyrrd"
uf.race = "lynx"
uf:set_skill("magic", 5)
uf:add_order('ZAUBER STUFE 1 Viehheilung')
@ -141,13 +140,10 @@ function test_familiar_mage_actions()
u:add_spell("earn_silver#gwyrrd")
u:add_order('ZAUBER STUFE 1 Viehheilung')
local uf = unit.create(f, r)
uf.magic = "gwyrrd"
uf.race = "lynx"
uf:set_skill("magic", 5)
uf:add_order('ZAUBER STUFE 1 Viehheilung')
u.familiar = uf
u.name = 'Xolgrim'
uf.name = 'Zonk'
process_orders()
assert_equal(50, u:get_item('money'))
assert_equal(50, uf:get_item('money'))
@ -199,3 +195,55 @@ function test_bug_2480()
process_orders()
assert_equal(0, u1.number);
end
function test_bug_2517()
local r = region.create(0, 0, "plain")
local f = faction.create("elf")
local um = unit.create(f, r, 1)
local uf = nil
eressea.settings.set("magic.familiar.race", "lynx")
f.magic = 'gwyrrd'
um.name = 'Xolgrim'
um.magic = 'gwyrrd'
um.race = 'elf'
um:set_skill('magic', 10)
um:add_spell('summon_familiar')
um:add_spell('earn_silver#gwyrrd')
um:add_order('ZAUBERE Vertrauten~rufen')
um.aura = 200
process_orders()
uf = um.familiar
assert_not_nil(uf)
assert_equal('lynx', uf.race)
assert_nil(uf.magic)
uf:add_order('LERNE Magie')
um:clear_orders()
um:add_order('ARBEITEN')
process_orders()
assert_nil(uf.magic)
uf:add_order('ZAUBERE STUFE 1 Viehheilung')
process_orders()
assert_equal(50, uf:get_item('money'))
end
function test_familiar_school()
local r = region.create(0, 0, "plain")
r:set_resource("money", 350)
r:set_resource("peasant", 0)
local f = faction.create("human")
local u = unit.create(f, r)
u.magic = "draig"
u:set_skill("magic", 10)
u.aura = 200
u:add_spell("fireball")
local uf = unit.create(f, r)
uf.race = "lynx"
u.familiar = uf
assert_nil(uf.magic)
uf:set_skill("magic", 5)
assert_nil(uf.magic)
uf.aura = 10
assert_equal(0, uf.aura)
assert_nil(uf.magic)
end

View file

@ -607,7 +607,7 @@ struct spellbook * faction_get_spellbook(struct faction *f)
if (f->magiegebiet != M_GRAY) {
return get_spellbook(magic_school[f->magiegebiet]);
}
return 0;
return NULL;
}
static int allied_skillcount(const faction * f, skill_t sk)

View file

@ -39,8 +39,9 @@
#define FIXATKEYS_VERSION 361 /* remove global.attribs, fix at_keys */
#define FACTION_UID_VERSION 362 /* f->uid contains a database id */
#define CRYPT_VERSION 363 /* passwords are encrypted */
#define FAMILIAR_FIXMAGE_VERSION 364 /* familiar links are fixed */
#define RELEASE_VERSION CRYPT_VERSION /* current datafile */
#define RELEASE_VERSION FAMILIAR_FIXMAGE_VERSION /* current datafile */
#define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */

View file

@ -1293,50 +1293,63 @@ ship *read_ship(gamedata *data)
return sh;
}
static void fix_fam_mage(unit *u) {
sc_mage *m = get_mage(u);
if (m && m->magietyp != M_GRAY) {
/* unit should be a familiar that has aura and a spell-list */
if (!m->spellbook) {
m->magietyp = M_GRAY;
}
}
}
static void fix_familiars(void) {
static void fix_fam_triggers(unit *u) {
attrib * a = a_find(u->attribs, &at_mage);
attrib * am = a_find(u->attribs, &at_familiarmage);
if (!am && a) {
/* not a familiar, but magical */
attrib * ae = a_find(u->attribs, &at_eventhandler);
if (ae) {
trigger **tlist;
tlist = get_triggers(ae, "destroy");
if (tlist) {
trigger *t;
unit *um = NULL;
for (t = *tlist; t; t = t->next) {
if (t->type == &tt_shock) {
um = (unit *)t->data.v;
break;
}
}
if (um) {
attrib *af = a_find(um->attribs, &at_familiar);
log_error("%s seems to be a broken familiar of %s.",
unitname(u), unitname(um));
if (af) {
unit * uf = (unit *)af->data.v;
log_error("%s already has a familiar: %s.",
unitname(um), unitname(uf));
}
else {
set_familiar(um, u);
}
}
else {
log_error("%s seems to be a broken familiar with no trigger.", unitname(u));
}
}
}
}
}
static void fix_familiars(void (*callback)(unit *)) {
region *r;
for (r = regions; r; r = r->next) {
unit * u;
for (u = r->units; u; u = u->next) {
if (u->_race != u->faction->race && (u->_race->flags & RCF_FAMILIAR)) {
/* unit is potentially a familiar */
attrib * a = a_find(u->attribs, &at_mage);
attrib * am = a_find(u->attribs, &at_familiarmage);
if (!am && a) {
/* not a familiar, but magical */
attrib * ae = a_find(u->attribs, &at_eventhandler);
if (ae) {
trigger **tlist;
tlist = get_triggers(ae, "destroy");
if (tlist) {
trigger *t;
unit *um = NULL;
for (t = *tlist; t; t = t->next) {
if (t->type == &tt_shock) {
um = (unit *)t->data.v;
break;
}
}
if (um) {
attrib *af = a_find(um->attribs, &at_familiar);
log_error("%s seems to be a broken familiar of %s.",
unitname(u), unitname(um));
if (af) {
unit * uf = (unit *)af->data.v;
log_error("%s already has a familiar: %s.",
unitname(um), unitname(uf));
}
else {
set_familiar(um, u);
}
}
else {
log_error("%s seems to be a broken familiar with no trigger.", unitname(u));
}
}
}
}
callback(u);
}
}
}
@ -1524,7 +1537,10 @@ int read_game(gamedata *data)
}
if (data->version < FAMILIAR_FIX_VERSION) {
fix_familiars();
fix_familiars(fix_fam_triggers);
}
if (data->version < FAMILIAR_FIXMAGE_VERSION) {
fix_familiars(fix_fam_mage);
}
log_debug("Done loading turn %d.", turn);

View file

@ -1671,7 +1671,7 @@ struct spellbook * unit_get_spellbook(const struct unit * u)
return faction_get_spellbook(u->faction);
}
}
return 0;
return NULL;
}
int effskill(const unit * u, skill_t sk, const region *r)

View file

@ -904,6 +904,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz);
if (itemhave < itemanz) {
resource *res = malloc(sizeof(resource));
assert(res);
res->number = itemanz - itemhave;
res->type = rtype;
res->next = reslist;
@ -2874,7 +2875,7 @@ spell *unit_getspell(struct unit *u, const char *name, const struct locale * lan
sb = unit_get_spellbook(u);
if (sb) {
void * tokens = 0;
void * tokens = NULL;
select_spellbook(&tokens, sb, lang);
if (tokens) {
variant token;
@ -2885,7 +2886,7 @@ spell *unit_getspell(struct unit *u, const char *name, const struct locale * lan
freetokens(tokens);
}
}
return 0;
return NULL;
}
int cast_spell(struct castorder *co)

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@ int sp_flying_ship(castorder * co)
ship *sh;
unit *u;
region *r;
unit *mage;
unit *caster;
int cast_level;
double power;
spellparameter *pa;
@ -47,7 +47,7 @@ int sp_flying_ship(castorder * co)
assert(co);
r = co_get_region(co);
mage = co_get_magician(co);
caster = co_get_caster(co);
cast_level = co->level;
power = co->force;
pa = co->par;
@ -57,22 +57,22 @@ int sp_flying_ship(castorder * co)
return 0;
sh = pa->param[0]->data.sh;
if (sh->type->construction->maxsize > 50) {
ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order,
ADDMSG(&caster->faction->msgs, msg_feedback(caster, co->order,
"error_flying_ship_too_big", "ship", sh));
return 0;
}
/* Duration = 1, nur diese Runde */
cno = levitate_ship(sh, mage, power, 1);
cno = levitate_ship(sh, caster, power, 1);
if (cno == 0) {
if (is_cursed(sh->attribs, &ct_flyingship)) {
/* Auf dem Schiff befindet liegt bereits so ein Zauber. */
cmistake(mage, co->order, 211, MSG_MAGIC);
cmistake(caster, co->order, 211, MSG_MAGIC);
}
else if (is_cursed(sh->attribs, &ct_shipspeedup)) {
/* Es ist zu gefaehrlich, ein sturmgepeitschtes Schiff fliegen zu lassen. */
cmistake(mage, co->order, 210, MSG_MAGIC);
cmistake(caster, co->order, 210, MSG_MAGIC);
}
return 0;
}
@ -86,7 +86,7 @@ int sp_flying_ship(castorder * co)
if (!(u->faction->flags & FFL_SELECT)) {
u->faction->flags |= FFL_SELECT;
if (!m) {
m = msg_message("flying_ship_result", "mage ship", mage, sh);
m = msg_message("flying_ship_result", "mage ship", caster, sh);
}
add_message(&u->faction->msgs, m);
}

View file

@ -784,13 +784,7 @@ int study_cmd(unit * u, order * ord)
show_potions(f, skill);
}
}
else if (sk == SK_MAGIC) {
sc_mage *mage = get_mage_depr(u);
if (!mage) {
mage = create_mage(u, u->faction->magiegebiet);
}
}
init_order_depr(NULL);
init_order(NULL, NULL);
return 0;
}