From a8bfa5e0954790113b2e84c8d9ed700d88c363ae Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 31 Aug 2017 21:19:25 +0200 Subject: [PATCH] try fixing familars without a mage. --- src/economy.c | 4 +-- src/kernel/save.c | 61 ++++++++++++++++++++++++++++++++++++++++++++- src/magic.c | 13 +--------- src/magic.h | 28 ++++++++++----------- src/util/gamedata.h | 3 ++- 5 files changed, 78 insertions(+), 31 deletions(-) diff --git a/src/economy.c b/src/economy.c index 546f7876e..74595a335 100644 --- a/src/economy.c +++ b/src/economy.c @@ -663,8 +663,8 @@ static int forget_cmd(unit * u, order * ord) sk = get_skill(s, u->faction->locale); if (sk != NOSKILL) { - if (sk == SK_MAGIC && (u_race(u)->flags & RCF_FAMILIAR)) { - /* some races cannot forget their innate magical abilities */ + if (sk == SK_MAGIC && is_familiar(u)) { + /* some units cannot forget their innate magical abilities */ return 0; } ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); diff --git a/src/kernel/save.c b/src/kernel/save.c index a3fc7e5af..39fab86af 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -29,6 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "faction.h" #include "group.h" #include "item.h" +#include "magic.h" #include "messages.h" #include "move.h" #include "objtypes.h" @@ -51,6 +52,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* util includes */ #include @@ -1607,7 +1609,59 @@ ship *read_ship(struct gamedata *data) } -int read_game(gamedata *data) { +static void fix_familiars(void) { + 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); + if (a) { + /* unit is magical */ + attrib * am = a_find(u->attribs, &at_familiarmage); + if (!am) { + /* but it is not a familiar? */ + 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)); + } + } + } + } + } + } + } + } +} + +int read_game(gamedata *data) +{ int p, nread; faction *f, **fp; region *r; @@ -1783,6 +1837,11 @@ int read_game(gamedata *data) { } } } + + if (data->version < FAMILIAR_FIX_VERSION) { + fix_familiars(); + } + if (loadplane || maxregions >= 0) { remove_empty_factions(); } diff --git a/src/magic.c b/src/magic.c index 7d33a28e1..f5e7810b4 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2140,16 +2140,6 @@ void free_castorders(castorder * co) return; } -/* ------------------------------------------------------------- */ -/*** - ** at_familiarmage - **/ - -typedef struct familiar_data { - unit *mage; - unit *familiar; -} famililar_data; - bool is_familiar(const unit * u) { attrib *a = a_find(u->attribs, &at_familiarmage); @@ -2182,7 +2172,7 @@ static int sm_familiar(const unit * u, const region * r, skill_t sk, int value) } } -static void set_familiar(unit * mage, unit * familiar) +void set_familiar(unit * mage, unit * familiar) { /* if the skill modifier for the mage does not yet exist, add it */ attrib *a = a_find(mage->attribs, &at_skillmod); @@ -2384,7 +2374,6 @@ static int read_clone(attrib * a, void *owner, struct gamedata *data) } /* mages */ - static int resolve_mage(variant data, void *addr) { unit *mage; diff --git a/src/magic.h b/src/magic.h index 6c905ea68..f5d2ff0f4 100644 --- a/src/magic.h +++ b/src/magic.h @@ -38,6 +38,10 @@ extern "C" { #define IRONGOLEM_CRUMBLE 15 /* monatlich Chance zu zerfallen */ #define STONEGOLEM_CRUMBLE 10 /* monatlich Chance zu zerfallen */ + extern const char *magic_school[MAXMAGIETYP]; + extern struct attrib_type at_familiar; + extern struct attrib_type at_familiarmage; + /* ------------------------------------------------------------- */ /* Spruchparameter * Wir suchen beim Parsen des Befehls erstmal nach lokalen Objekten, @@ -82,11 +86,6 @@ extern "C" { #define TARGET_RESISTS (1<<0) #define TARGET_NOTFOUND (1<<1) - /* ------------------------------------------------------------- */ - /* Magierichtungen */ - - extern const char *magic_school[MAXMAGIETYP]; - /* ------------------------------------------------------------- */ /* Magier: * - Magierichtung @@ -324,16 +323,15 @@ extern "C" { /* Sprüche in der struct region */ /* (sind in curse) */ - extern struct unit *get_familiar(const struct unit *u); - extern struct unit *get_familiar_mage(const struct unit *u); - extern struct unit *get_clone(const struct unit *u); - extern struct unit *get_clone_mage(const struct unit *u); - extern struct attrib_type at_familiar; - extern struct attrib_type at_familiarmage; - extern void remove_familiar(struct unit *mage); - extern bool create_newfamiliar(struct unit *mage, struct unit *familiar); - extern void create_newclone(struct unit *mage, struct unit *familiar); - extern struct unit *has_clone(struct unit *mage); + void set_familiar(struct unit * mage, struct unit * familiar); + struct unit *get_familiar(const struct unit *u); + struct unit *get_familiar_mage(const struct unit *u); + struct unit *get_clone(const struct unit *u); + struct unit *get_clone_mage(const struct unit *u); + void remove_familiar(struct unit *mage); + bool create_newfamiliar(struct unit *mage, struct unit *familiar); + void create_newclone(struct unit *mage, struct unit *familiar); + struct unit *has_clone(struct unit *mage); const char *spell_info(const struct spell *sp, const struct locale *lang); diff --git a/src/util/gamedata.h b/src/util/gamedata.h index 97f8416b3..058bc3f07 100644 --- a/src/util/gamedata.h +++ b/src/util/gamedata.h @@ -36,10 +36,11 @@ #define NOLANDITEM_VERSION 356 /* land_region has no items */ #define NORCSPELL_VERSION 357 /* data contains no RC_SPELL units */ #define SORTKEYS_VERSION 358 /* at_keys is sorted */ +#define FAMILIAR_FIX_VERSION 359 /* at_keys is sorted */ /* unfinished: */ #define CRYPT_VERSION 400 /* passwords are encrypted */ -#define RELEASE_VERSION SORTKEYS_VERSION /* current datafile */ +#define RELEASE_VERSION FAMILIAR_FIX_VERSION /* current datafile */ #define MIN_VERSION INTPAK_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 */