try fixing familars without a mage.

This commit is contained in:
Enno Rehling 2017-08-31 21:19:25 +02:00
parent 0b6f5aa064
commit a8bfa5e095
5 changed files with 78 additions and 31 deletions

View File

@ -663,8 +663,8 @@ static int forget_cmd(unit * u, order * ord)
sk = get_skill(s, u->faction->locale); sk = get_skill(s, u->faction->locale);
if (sk != NOSKILL) { if (sk != NOSKILL) {
if (sk == SK_MAGIC && (u_race(u)->flags & RCF_FAMILIAR)) { if (sk == SK_MAGIC && is_familiar(u)) {
/* some races cannot forget their innate magical abilities */ /* some units cannot forget their innate magical abilities */
return 0; return 0;
} }
ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk));

View File

@ -29,6 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "faction.h" #include "faction.h"
#include "group.h" #include "group.h"
#include "item.h" #include "item.h"
#include "magic.h"
#include "messages.h" #include "messages.h"
#include "move.h" #include "move.h"
#include "objtypes.h" #include "objtypes.h"
@ -51,6 +52,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <attributes/attributes.h> #include <attributes/attributes.h>
#include <attributes/key.h> #include <attributes/key.h>
#include <triggers/timeout.h> #include <triggers/timeout.h>
#include <triggers/shock.h>
/* util includes */ /* util includes */
#include <util/assert.h> #include <util/assert.h>
@ -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; int p, nread;
faction *f, **fp; faction *f, **fp;
region *r; region *r;
@ -1783,6 +1837,11 @@ int read_game(gamedata *data) {
} }
} }
} }
if (data->version < FAMILIAR_FIX_VERSION) {
fix_familiars();
}
if (loadplane || maxregions >= 0) { if (loadplane || maxregions >= 0) {
remove_empty_factions(); remove_empty_factions();
} }

View File

@ -2140,16 +2140,6 @@ void free_castorders(castorder * co)
return; return;
} }
/* ------------------------------------------------------------- */
/***
** at_familiarmage
**/
typedef struct familiar_data {
unit *mage;
unit *familiar;
} famililar_data;
bool is_familiar(const unit * u) bool is_familiar(const unit * u)
{ {
attrib *a = a_find(u->attribs, &at_familiarmage); 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 */ /* if the skill modifier for the mage does not yet exist, add it */
attrib *a = a_find(mage->attribs, &at_skillmod); attrib *a = a_find(mage->attribs, &at_skillmod);
@ -2384,7 +2374,6 @@ static int read_clone(attrib * a, void *owner, struct gamedata *data)
} }
/* mages */ /* mages */
static int resolve_mage(variant data, void *addr) static int resolve_mage(variant data, void *addr)
{ {
unit *mage; unit *mage;

View File

@ -38,6 +38,10 @@ extern "C" {
#define IRONGOLEM_CRUMBLE 15 /* monatlich Chance zu zerfallen */ #define IRONGOLEM_CRUMBLE 15 /* monatlich Chance zu zerfallen */
#define STONEGOLEM_CRUMBLE 10 /* 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 /* Spruchparameter
* Wir suchen beim Parsen des Befehls erstmal nach lokalen Objekten, * Wir suchen beim Parsen des Befehls erstmal nach lokalen Objekten,
@ -82,11 +86,6 @@ extern "C" {
#define TARGET_RESISTS (1<<0) #define TARGET_RESISTS (1<<0)
#define TARGET_NOTFOUND (1<<1) #define TARGET_NOTFOUND (1<<1)
/* ------------------------------------------------------------- */
/* Magierichtungen */
extern const char *magic_school[MAXMAGIETYP];
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Magier: /* Magier:
* - Magierichtung * - Magierichtung
@ -324,16 +323,15 @@ extern "C" {
/* Sprüche in der struct region */ /* Sprüche in der struct region */
/* (sind in curse) */ /* (sind in curse) */
extern struct unit *get_familiar(const struct unit *u); void set_familiar(struct unit * mage, struct unit * familiar);
extern struct unit *get_familiar_mage(const struct unit *u); struct unit *get_familiar(const struct unit *u);
extern struct unit *get_clone(const struct unit *u); struct unit *get_familiar_mage(const struct unit *u);
extern struct unit *get_clone_mage(const struct unit *u); struct unit *get_clone(const struct unit *u);
extern struct attrib_type at_familiar; struct unit *get_clone_mage(const struct unit *u);
extern struct attrib_type at_familiarmage; void remove_familiar(struct unit *mage);
extern void remove_familiar(struct unit *mage); bool create_newfamiliar(struct unit *mage, struct unit *familiar);
extern bool create_newfamiliar(struct unit *mage, struct unit *familiar); void create_newclone(struct unit *mage, struct unit *familiar);
extern void create_newclone(struct unit *mage, struct unit *familiar); struct unit *has_clone(struct unit *mage);
extern struct unit *has_clone(struct unit *mage);
const char *spell_info(const struct spell *sp, const char *spell_info(const struct spell *sp,
const struct locale *lang); const struct locale *lang);

View File

@ -36,10 +36,11 @@
#define NOLANDITEM_VERSION 356 /* land_region has no items */ #define NOLANDITEM_VERSION 356 /* land_region has no items */
#define NORCSPELL_VERSION 357 /* data contains no RC_SPELL units */ #define NORCSPELL_VERSION 357 /* data contains no RC_SPELL units */
#define SORTKEYS_VERSION 358 /* at_keys is sorted */ #define SORTKEYS_VERSION 358 /* at_keys is sorted */
#define FAMILIAR_FIX_VERSION 359 /* at_keys is sorted */
/* unfinished: */ /* unfinished: */
#define CRYPT_VERSION 400 /* passwords are encrypted */ #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 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 */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */