// // P_UnArchiveThinkers // void P_UnArchiveThinkers (void) { byte tclass; thinker_t* currentthinker; thinker_t* next; mobj_t* mobj; // remove all the current thinkers currentthinker = thinkercap.next; while (currentthinker != &thinkercap) { next = currentthinker->next; if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) P_RemoveMobj ((mobj_t *)currentthinker); else Z_Free (currentthinker); currentthinker = next; } P_InitThinkers (); // read in saved thinkers while (1) { tclass = saveg_read8(); switch (tclass) { case tc_end: return; // end of list case tc_mobj: saveg_read_pad(); mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); saveg_read_mobj_t(mobj); mobj->target = NULL; mobj->tracer = NULL; P_SetThingPosition (mobj); mobj->info = &mobjinfo[mobj->type]; mobj->floorz = mobj->subsector->sector->floorheight; mobj->ceilingz = mobj->subsector->sector->ceilingheight; mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; P_AddThinker (&mobj->thinker); break; default: I_Error ("Unknown tclass %i in savegame",tclass); } } }
void P_UnArchiveMobjs(void) { mobj_t* current; mobj_t* next; mobj_t* mobj; int i; // remove all the current thinkers current = mobjhead.next; while(current != &mobjhead) { next = current->next; P_RemoveMobj(current); current = next; } saveg_setup_mobjread(); mobjhead.next = mobjhead.prev = &mobjhead; for(i = 0; i < savegmobjnum; i++) { mobj = savegmobj[i].mobj; saveg_read_pad(); saveg_read_mobj_t(mobj); if(!saveg_read_marker(SAVEGAME_MOBJ)) I_Error("P_UnArchiveMobjs: Mobj read is inconsistent\nfile offset: %i\nmobj count: %i", save_offset, savegmobjnum); P_SetThingPosition(mobj); P_LinkMobj(mobj); mobj->info = &mobjinfo[mobj->type]; } saveg_read_pad(); }
// // P_UnArchiveThinkers // void P_UnArchiveThinkers(void) { thinker_t *currentthinker = thinkers[th_all].next; // remove all the current thinkers while (currentthinker != &thinkers[th_all]) { thinker_t *next = currentthinker->next; if (currentthinker->function == P_MobjThinker || currentthinker->function == MusInfoThinker) { P_RemoveMobj((mobj_t *)currentthinker); P_RemoveThinkerDelayed(currentthinker); } else Z_Free(currentthinker); currentthinker = next; } P_InitThinkers(); // remove all bloodsplats for (int i = 0; i < numsectors; i++) { bloodsplat_t *splat = sectors[i].splatlist; while (splat) { bloodsplat_t *next = splat->snext; P_UnsetBloodSplatPosition(splat); splat = next; } } r_bloodsplats_total = 0; thingindex = 0; // read in saved thinkers while (true) { byte tclass = saveg_read8(); switch (tclass) { case tc_end: return; // end of list case tc_mobj: { mobj_t *mobj = Z_Calloc(1, sizeof(*mobj), PU_LEVEL, NULL); saveg_read_pad(); saveg_read_mobj_t(mobj); mobj->info = &mobjinfo[mobj->type]; P_SetThingPosition(mobj); mobj->thinker.function = (mobj->type == MT_MUSICSOURCE ? MusInfoThinker : P_MobjThinker); P_AddThinker(&mobj->thinker); mobj->colfunc = mobj->info->colfunc; mobj->altcolfunc = mobj->info->altcolfunc; P_SetShadowColumnFunction(mobj); thingindex = MIN(thingindex + 1, TARGETLIMIT - 1); break; } case tc_bloodsplat: { bloodsplat_t *splat = calloc(1, sizeof(*splat)); saveg_read_pad(); saveg_read_bloodsplat_t(splat); if (r_bloodsplats_total < r_bloodsplats_max) { splat->width = spritewidth[splat->patch]; splat->sector = R_PointInSubsector(splat->x, splat->y)->sector; P_SetBloodSplatPosition(splat); splat->colfunc = (splat->blood == FUZZYBLOOD ? fuzzcolfunc : bloodsplatcolfunc); r_bloodsplats_total++; } break; } default: I_Error("This savegame is invalid."); } } }
// // P_UnArchiveThinkers // void P_UnArchiveThinkers (void) { byte tclass; thinker_t* currentthinker; thinker_t* next; mobj_t* mobj; // remove all the current thinkers currentthinker = thinkercap.next; while (currentthinker != &thinkercap) { next = currentthinker->next; if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) P_RemoveMobj ((mobj_t *)currentthinker); else Z_Free (currentthinker); currentthinker = next; } P_InitThinkers (); // read in saved thinkers while (1) { tclass = saveg_read8(); switch (tclass) { case tc_end: return; // end of list case tc_mobj: saveg_read_pad(); mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); saveg_read_mobj_t(mobj); // haleyjd 09/29/10: Strife sets the targets of non-allied creatures // who had a non-NULL target at save time to players[0].mo so that // they won't fall back asleep. // // BUG: As the player may not have been spawned yet, we could be // setting monsters' targets to the mobj which was spawned by // P_SetupLevel and then removed just above. Due to a subtle glitch // in the DOOM engine whereby all things removed in this function // are leaked until the next time P_SetupLevel is called, this is a // safe operation - the call to P_InitThinkers above stops any of // the objects removed, including the player's previous body, from // being passed to Z_Free. One glitch relying on another! if(mobj->target != NULL && (mobj->flags & MF_ALLY) != MF_ALLY) mobj->target = players[0].mo; else mobj->target = NULL; // WARNING! Strife does not seem to set tracer! I am leaving it be // for now because so far no crashes have been observed, and failing // to set this here will almost certainly crash Choco. mobj->tracer = NULL; P_SetThingPosition (mobj); mobj->info = &mobjinfo[mobj->type]; // [STRIFE]: doesn't set these //mobj->floorz = mobj->subsector->sector->floorheight; //mobj->ceilingz = mobj->subsector->sector->ceilingheight; mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; P_AddThinker (&mobj->thinker); break; default: I_Error ("Unknown tclass %i in savegame",tclass); } } }