1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-27 07:52:25 +01:00

More fixes

Split relink into mx/ox versions that can be called on single mons/objs, to cover cases where we may need to fix up pointers that weren't done during restore (eg, mon_traits). At the moment, this isn't needed -- only ESUM needs any fixups at all, and the only way to reach montraits is for the mon to die, which quite intentionally severs the connection between mon and summoner. But this may be needed for future features! Futureproofing, yay!

Save youmonst, so we can use &youmonst->summonpwr and not have it reset to 0 over save/restore.

Revived petrified statues of summons crumble into dust (instead of creating a summon unlinked from its summoner and with no desummoning timer).
This commit is contained in:
NeroOneTrueKing 2021-01-16 18:18:23 -06:00
parent 93e2e0f3d9
commit a76396c29c
11 changed files with 92 additions and 45 deletions

View file

@ -132,6 +132,8 @@ struct esum {
struct monst * summoner; /* monster responsible for this mon/obj -- can be null */
unsigned sm_id; /* m_id of summoner */
int summonstr; /* tax on summoner, who may maintain up to its own HD of summons at a time. */
Bitfield(staleptr, 1); /* denotes if `summoner` is a stale pointer and needs to be updated */
Bitfield(unused,7);
};

View file

@ -1316,6 +1316,7 @@ E void * FDECL(bundle_mextra, (struct monst *, long *));
E void FDECL(unbundle_mextra, (struct monst *, void *));
E void FDECL(save_mextra, (struct monst *, int, int));
E void FDECL(rest_mextra, (struct monst *, int, boolean));
E void FDECL(relink_mx, (struct monst *));
/* out of order, but it makes sense to directly follow mextra */
/* ### oextra.c ### */
@ -1332,6 +1333,7 @@ E void * FDECL(bundle_oextra, (struct obj *, long *));
E void FDECL(unbundle_oextra, (struct obj *, void *));
E void FDECL(save_oextra, (struct obj *, int, int));
E void FDECL(rest_oextra, (struct obj *, int, boolean));
E void FDECL(relink_ox, (struct obj *));
/* ### minion.c ### */

View file

@ -230,8 +230,13 @@ long * len_p;
for (i = 0; i < NUM_MX; i++) {
if (!(towrite & (1 << i)))
continue;
/* special handling when we need to mark something as having a stale pointer */
if (i == MX_ESUM) mtmp->mextra_p->esum_p->staleptr = 1;
/* copy memory */
memcpy(output_ptr,mtmp->mextra_p->eindex[i],siz_mx(mtmp, i));
/* and remove markers after saving */
if (i == MX_ESUM) mtmp->mextra_p->esum_p->staleptr = 0;
/* increment output_ptr (char is 1 byte) */
output_ptr = ((char *)output_ptr) + siz_mx(mtmp, i);
}
@ -377,8 +382,29 @@ boolean ghostly;
assign_level(&(mtmp->mextra_p->epri_p->shrlevel), &u.uz);
}
}
/* cannot handle esum here -- it needs all monsters to have been restored first -- done in relink_mx() below */
}
return;
}
/* relinks mx. If called with a specific mtmp, only does so for that one, otherwise does all on fmon */
void
relink_mx(specific_mtmp)
struct monst * specific_mtmp;
{
unsigned nid;
struct monst * mtmp = (specific_mtmp ? specific_mtmp : fmon);
/* only checking fmon because MX_ESUM cannot be on migratingmons */
for (; mtmp && (mtmp == specific_mtmp || !specific_mtmp); mtmp = mtmp->nmon) {
if (get_mx(mtmp, MX_ESUM)) {
if (mtmp->mextra_p->esum_p->staleptr) {
mtmp->mextra_p->esum_p->staleptr = 0;
/* restore stale pointer -- id==0 is assumed to be player */
nid = mtmp->mextra_p->esum_p->sm_id;
mtmp->mextra_p->esum_p->summoner = (genericptr_t) (nid ? find_mid(nid, FM_FMON) : &youmonst);
if (!mtmp->mextra_p->esum_p->summoner) panic("cant find m_id %d", nid);
}
}
}
}
/*mextra.c*/

View file

@ -2552,6 +2552,8 @@ boolean copyof;
if (mnew->mextra_p) {
void * mextra_bundle = mtmp+1;
unbundle_mextra(mnew, mextra_bundle);
/* relink any stale pointers */
relink_mx(mnew);
}
}
else {

View file

@ -230,6 +230,7 @@ STATIC_VAR int cham_to_pm[] = {
is_reviver((mon)->data) || \
((mon)->mfaction) || \
(templated(mon)) || \
(get_mx((mon), MX_ESUM)) || \
((mon)->ispolyp) || \
((mon)->zombify) || \
((mon)->mtyp == PM_UNDEAD_KNIGHT) || \

View file

@ -226,8 +226,13 @@ long * len_p;
for (i = 0; i < NUM_OX; i++) {
if (!(towrite & (1 << i)))
continue;
/* special handling when we need to mark something as having a stale pointer */
if (i == OX_ESUM) otmp->oextra_p->esum_p->staleptr = 1;
/* copy memory */
memcpy(output_ptr,otmp->oextra_p->eindex[i],siz_ox(otmp, i));
/* and remove markers after saving */
if (i == OX_ESUM) otmp->oextra_p->esum_p->staleptr = 0;
/* increment output_ptr (char is 1 byte) */
output_ptr = ((char *)output_ptr) + siz_ox(otmp, i);
}
@ -355,4 +360,32 @@ boolean ghostly;
return;
}
/* relinks ox. If called with a specific otmp, only does so for that one, otherwise does all */
void
relink_ox(specific_otmp)
struct obj * specific_otmp;
{
unsigned nid;
int owhere = ((1 << OBJ_FLOOR) |
(1 << OBJ_INVENT) |
(1 << OBJ_MINVENT) |
(1 << OBJ_MIGRATING) |
(1 << OBJ_BURIED) |
(1 << OBJ_CONTAINED) |
(1 << OBJ_MAGIC_CHEST) |
(1 << OBJ_INTRAP));
struct obj * otmp = specific_otmp ? specific_otmp : start_all_items(&owhere);
for (; otmp && (otmp == specific_otmp || !specific_otmp); otmp = (specific_otmp ? (struct obj *)0 : next_all_items(&owhere))) {
if (get_ox(otmp, OX_ESUM)) {
if (otmp->oextra_p->esum_p->staleptr) {
otmp->oextra_p->esum_p->staleptr = 0;
/* restore stale pointer -- id==0 is assumed to be player */
nid = otmp->oextra_p->esum_p->sm_id;
otmp->oextra_p->esum_p->summoner = (genericptr_t) (nid ? find_mid(nid, FM_FMON) : &youmonst);
if (!otmp->oextra_p->esum_p->summoner) panic("cant find m_id %d", nid);
}
}
}
}
/*oextra.c*/

View file

@ -30,7 +30,6 @@ STATIC_DCL boolean FDECL(restgamestate, (int, unsigned int *, unsigned int *));
STATIC_DCL void FDECL(restlevelstate, (unsigned int, unsigned int));
STATIC_DCL int FDECL(restlevelfile, (int,int));
STATIC_DCL void FDECL(reset_oattached_mids, (BOOLEAN_P));
STATIC_DCL void NDECL(relink);
/*
* Save a mapping of IDs from ghost levels to the current level. This
@ -432,6 +431,7 @@ unsigned int *stuckid, *steedid; /* STEED */
amii_setpens(amii_numcolors); /* use colors from save file */
#endif
mread(fd, (genericptr_t) &u, sizeof(struct you));
mread(fd, (genericptr_t) &youmonst, sizeof(struct monst));
mread(fd, (genericptr_t) &god_list, sizeof(struct god_details)*MAX_GOD);
init_uasmon();
#ifdef CLIPPING
@ -544,7 +544,8 @@ unsigned int *stuckid, *steedid; /* STEED */
sizeof realtime_data.realtime);
#endif
/* must come after all mons & objs are restored */
relink();
relink_mx((struct monst *)0);
relink_ox((struct obj *)0);
#ifdef WHEREIS_FILE
touch_whereis();
#endif
@ -1013,7 +1014,8 @@ boolean ghostly;
}
/* must come after all mons & objs are restored */
relink();
relink_mx((struct monst *)0);
relink_ox((struct obj *)0);
reset_oattached_mids(ghostly);
/* regenerate animals while on another level */
@ -1129,44 +1131,6 @@ boolean ghostly;
}
}
/* relink (o/m)extras as needed */
void
relink()
{
unsigned nid;
/* objects first */
struct obj * otmp;
int owhere = ((1 << OBJ_FLOOR) |
(1 << OBJ_INVENT) |
(1 << OBJ_MINVENT) |
(1 << OBJ_MIGRATING) |
(1 << OBJ_BURIED) |
(1 << OBJ_CONTAINED) |
(1 << OBJ_MAGIC_CHEST) |
(1 << OBJ_INTRAP));
for (otmp = start_all_items(&owhere); otmp; otmp = next_all_items(&owhere)) {
if (get_ox(otmp, OX_ESUM)) {
nid = otmp->oextra_p->esum_p->sm_id;
if (nid) {
otmp->oextra_p->esum_p->summoner = (genericptr_t) find_mid(nid, FM_FMON);
if (!otmp->oextra_p->esum_p->summoner) panic("cant find m_id %d", nid);
}
}
}
/* then monsters -- only checking fmon because MX_ESUM cannot be on migratingmons */
struct monst * mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (get_mx(mtmp, MX_ESUM)) {
nid = mtmp->mextra_p->esum_p->sm_id;
if (nid) {
mtmp->mextra_p->esum_p->summoner = (genericptr_t) find_mid(nid, FM_FMON);
if (!mtmp->mextra_p->esum_p->summoner) panic("cant find m_id %d", nid);
}
}
}
}
#ifdef ZEROCOMP
#define RLESC '\0' /* Leading character for run of RLESC's */

View file

@ -305,6 +305,7 @@ register int fd, mode;
flags.end_around = has_loaded_bones;
bwrite(fd, (genericptr_t) &flags, sizeof(struct flag));
bwrite(fd, (genericptr_t) &u, sizeof(struct you));
bwrite(fd, (genericptr_t) &youmonst, sizeof(struct monst));
bwrite(fd, (genericptr_t) &god_list, sizeof(struct god_details)*MAX_GOD);
/* save random monsters*/

View file

@ -2455,6 +2455,8 @@ long timeout;
struct monst * mon = (struct monst *)arg;
if (get_mx(mon, MX_ESUM) && mon->mextra_p->esum_p->summoner) {
mon->mextra_p->esum_p->summoner->summonpwr -= mon->mextra_p->esum_p->summonstr;
mon->mextra_p->esum_p->summoner = (struct monst *)0;
mon->mextra_p->esum_p->sm_id = 0;
}
/* special case for vexing orbs -- awful */
@ -2478,8 +2480,11 @@ genericptr_t arg;
long timeout;
{
struct monst * mon = (struct monst *)arg;
if (get_mx(mon, MX_ESUM) && mon->mextra_p->esum_p->summoner) {
/* if we are stopping the timer because mon died or vanished, reduce tax on summoner */
if (get_mx(mon, MX_ESUM) && DEADMONSTER(mon) && mon->mextra_p->esum_p->summoner) {
mon->mextra_p->esum_p->summoner->summonpwr -= mon->mextra_p->esum_p->summonstr;
mon->mextra_p->esum_p->summoner = (struct monst *)0;
mon->mextra_p->esum_p->sm_id = 0;
}
}
void

View file

@ -633,7 +633,11 @@ int *fail_reason;
/* mimic statue becomes seen mimic; other hiders won't be hidden */
if (mon->m_ap_type) seemimic(mon);
else mon->mundetected = FALSE;
if ((x == u.ux && y == u.uy) || cause == ANIMATE_SPELL) {
if (get_mx(mon, MX_ESUM)) {
if (cansee(x,y))
pline_The("statue crumbles to dust.");
}
else if ((x == u.ux && y == u.uy) || cause == ANIMATE_SPELL) {
const char *comes_to_life = nonliving(mon->data) ?
"moves" : "comes to life";
if (cause == ANIMATE_SPELL){

View file

@ -2098,8 +2098,8 @@ struct obj *obj, *otmp;
obj = poly_obj(obj, MEATBALL);
goto smell;
}
if (!animate_statue(obj, oox, ooy,
ANIMATE_SPELL, (int *)0)) {
struct monst * mtmp;
if (!(mtmp = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *)0))) {
struct obj *item;
makecorpse: if (mons[obj->corpsenm].geno &
(G_NOCORPSE|G_UNIQ)) {
@ -2117,6 +2117,13 @@ makecorpse: if (mons[obj->corpsenm].geno &
obj = poly_obj(obj, CORPSE);
break;
}
else {
/* creature was created */
if (get_mx(mtmp, MX_ESUM)) {
/* vanish it */
monvanished(mtmp);
}
}
} else if (obj->otyp == FOSSIL) {
int corpsetype = obj->corpsenm;
xchar oox, ooy;