void P_UnArchiveThinkers (void) { thinker_t *th; mobj_t **mobj_p; // killough 2/14/98: Translation table size_t size; // killough 2/14/98: size of or index into table totallive = 0; // killough 3/26/98: Load boss brain state memcpy(&brain, save_p, sizeof brain); save_p += sizeof brain; // remove all the current thinkers for (th = thinkercap.next; th != &thinkercap; ) { thinker_t *next = th->next; if (th->function == P_MobjThinker) { P_RemoveMobj ((mobj_t *) th); P_RemoveThinkerDelayed(th); // fix mobj leak } else Z_Free (th); th = next; } P_InitThinkers (); // killough 2/14/98: count number of thinkers by skipping through them { byte *sp = save_p; // save pointer and skip header for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98 { // skip all entries, adding up count PADSAVEP(); save_p += sizeof(mobj_t);//e6y } if (*--save_p != tc_end) I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p); // first table entry special: 0 maps to NULL *(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers save_p = sp; // restore save pointer } // read in saved thinkers for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98 { mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL); // killough 2/14/98 -- insert pointers to thinkers into table, in order: mobj_p[size] = mobj; PADSAVEP(); memcpy (mobj, save_p, sizeof(mobj_t)); save_p += sizeof(mobj_t); mobj->state = states + (int) mobj->state; if (mobj->player) (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj; P_SetThingPosition (mobj); mobj->info = &mobjinfo[mobj->type]; // killough 2/28/98: // Fix for falling down into a wall after savegame loaded: // mobj->floorz = mobj->subsector->sector->floorheight; // mobj->ceilingz = mobj->subsector->sector->ceilingheight; mobj->thinker.function = P_MobjThinker; P_AddThinker (&mobj->thinker); if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE))) totallive++; } // killough 2/14/98: adjust target and tracer fields, plus // lastenemy field, to correctly point to mobj thinkers. // NULL entries automatically handled by first table entry. // // killough 11/98: use P_SetNewTarget() to set fields for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { P_SetNewTarget(&((mobj_t *) th)->target, mobj_p[P_GetMobj(((mobj_t *)th)->target,size)]); P_SetNewTarget(&((mobj_t *) th)->tracer, mobj_p[P_GetMobj(((mobj_t *)th)->tracer,size)]); P_SetNewTarget(&((mobj_t *) th)->lastenemy, mobj_p[P_GetMobj(((mobj_t *)th)->lastenemy,size)]); } { // killough 9/14/98: restore soundtargets int i; for (i = 0; i < numsectors; i++) { mobj_t *target; memcpy(&target, save_p, sizeof target); save_p += sizeof target; // Must verify soundtarget. See P_ArchiveThinkers. P_SetNewTarget(§ors[i].soundtarget, mobj_p[P_GetMobj(target,size)]); } } free(mobj_p); // free translation table // killough 3/26/98: Spawn icon landings: if (gamemode == commercial) { // P_SpawnBrainTargets overwrites brain.targeton and brain.easy with zero. struct brain_s brain_tmp = brain; // saving P_SpawnBrainTargets(); // old demos with save/load tics should not be affected by this fix if (!prboom_comp[PC_RESET_MONSTERSPAWNER_PARAMS_AFTER_LOADING].state) { brain = brain_tmp; // restoring } } }
void P_UnArchiveThinkers (void) { thinker_t *th; mobj_t **mobj_p; // killough 2/14/98: Translation table size_t size; // killough 2/14/98: size of or index into table totallive = 0; // killough 3/26/98: Load boss brain state memcpy(&brain, save_p, sizeof brain); save_p += sizeof brain; // remove all the current thinkers for (th = thinkercap.next; th != &thinkercap; ) { thinker_t *next = th->next; if (th->function == P_MobjThinker) { P_RemoveMobj ((mobj_t *) th); P_RemoveThinkerDelayed(th); // fix mobj leak } else Z_Free (th); th = next; } P_InitThinkers (); // killough 2/14/98: count number of thinkers by skipping through them { byte *sp = save_p; // save pointer and skip header for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98 { // skip all entries, adding up count PADSAVEP(); /* cph 2006/07/30 - see comment below for change in layout of mobj_t */ save_p += sizeof(mobj_t)+3*sizeof(void*)-4*sizeof(fixed_t); } if (*--save_p != tc_end) I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p); // first table entry special: 0 maps to NULL *(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers save_p = sp; // restore save pointer } // read in saved thinkers for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98 { mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL); // killough 2/14/98 -- insert pointers to thinkers into table, in order: mobj_p[size] = mobj; PADSAVEP(); /* cph 2006/07/30 - * The end of mobj_t changed from * boolean invisible; * mobj_t* lastenemy; * mobj_t* above_monster; * mobj_t* below_monster; * void* touching_sectorlist; * to * mobj_t* lastenemy; * void* touching_sectorlist; * fixed_t PrevX, PrevY, PrevZ; * at prboom 2.4.4. There is code here to preserve the savegame format. * * touching_sectorlist is reconstructed anyway, so we now read in all * but the last 5 words from the savegame (filling all but the last 2 * fields of our current mobj_t. We then pull lastenemy from the 2nd of * the 5 leftover words, and skip the others. */ memcpy (mobj, save_p, sizeof(mobj_t)-2*sizeof(void*)-4*sizeof(fixed_t)); save_p += sizeof(mobj_t)-sizeof(void*)-4*sizeof(fixed_t); memcpy (&(mobj->lastenemy), save_p, sizeof(void*)); save_p += 4*sizeof(void*); mobj->state = states + (int) mobj->state; if (mobj->player) (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj; P_SetThingPosition (mobj); mobj->info = &mobjinfo[mobj->type]; // killough 2/28/98: // Fix for falling down into a wall after savegame loaded: // mobj->floorz = mobj->subsector->sector->floorheight; // mobj->ceilingz = mobj->subsector->sector->ceilingheight; mobj->thinker.function = P_MobjThinker; P_AddThinker (&mobj->thinker); if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE))) totallive++; } // killough 2/14/98: adjust target and tracer fields, plus // lastenemy field, to correctly point to mobj thinkers. // NULL entries automatically handled by first table entry. // // killough 11/98: use P_SetNewTarget() to set fields for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { P_SetNewTarget(&((mobj_t *) th)->target, mobj_p[P_GetMobj(((mobj_t *)th)->target,size)]); P_SetNewTarget(&((mobj_t *) th)->tracer, mobj_p[P_GetMobj(((mobj_t *)th)->tracer,size)]); P_SetNewTarget(&((mobj_t *) th)->lastenemy, mobj_p[P_GetMobj(((mobj_t *)th)->lastenemy,size)]); } { // killough 9/14/98: restore soundtargets int i; for (i = 0; i < numsectors; i++) { mobj_t *target; memcpy(&target, save_p, sizeof target); save_p += sizeof target; // Must verify soundtarget. See P_ArchiveThinkers. P_SetNewTarget(§ors[i].soundtarget, mobj_p[P_GetMobj(target,size)]); } } free(mobj_p); // free translation table // killough 3/26/98: Spawn icon landings: if (gamemode == commercial) P_SpawnBrainTargets(); }