// Scripts that always start immediately at level load. void Map::ACS_StartOpenScript(acs_script_t *s) { CONS_Printf("Starting an opening ACS (script %d)\n", s->number); acs_t *script = new acs_t(s); script->delay = TICRATE; // Give a second for the Map to get spawned. AddThinker(script); }
VThinker* VLevel::SpawnThinker(VClass* AClass, const TVec& AOrigin, const TAVec& AAngles, mthing_t* mthing, bool AllowReplace) { guard(VLevel::SpawnThinker); VClass* Class = AllowReplace ? AClass->GetReplacement() : AClass; VThinker* Ret = (VThinker*)StaticSpawnObject(Class); AddThinker(Ret); if (IsForServer() && Class->IsChildOf(VEntity::StaticClass())) { ((VEntity*)Ret)->Origin = AOrigin; ((VEntity*)Ret)->Angles = AAngles; ((VEntity*)Ret)->eventOnMapSpawn(mthing); if (LevelInfo->LevelInfoFlags2 & VLevelInfo::LIF2_BegunPlay) { ((VEntity*)Ret)->eventBeginPlay(); } } return Ret; unguard; }
int Map::Unserialize(LArchive &a) { unsigned temp; short stemp; int i, n; if (!a.Marker(MARK_MAP)) return -1; a.active_map = this; // so the Thinkers can be extracted OK // first we load and setup the map, but without spawning any Thinkers if possible a << lumpname; // TODO load map md5 checksum, make sure the correct map is loaded Setup(0, false); // remove all the current thinkers (could be done more elegantly by not spawning them // in the first place, but... well, at least the Actors are not spawned.) Thinker *th, *next; for (th = thinkercap.next; th != &thinkercap; th = next) { next = th->next; delete th; } InitThinkers(); a << starttic << maptic; a << kills << items << secrets; line_t *li; side_t *si; byte diff, diff2; // load changes in geometry while (1) { a << temp; if (temp == MARK_END) break; i = temp; // sector number a << diff; if (diff & SD_DIFF2) a << diff2; else diff2 = 0; char picname[8]; if (diff & SD_FLOORHT ) a << sectors[i].floorheight; if (diff & SD_CEILHT ) a << sectors[i].ceilingheight; if (diff & SD_FLOORPIC) { a.Read((byte *)picname, 8); sectors[i].floorpic = materials.Get8char(picname, TEX_floor); } if (diff & SD_CEILPIC) { a.Read((byte *)picname, 8); sectors[i].ceilingpic = materials.Get8char(picname, TEX_floor); } if (diff & SD_LIGHT) a << sectors[i].lightlevel; if (diff & SD_SPECIAL) a << sectors[i].special; if (diff & SD_TAG) a << sectors[i].tag; if (diff2 & SD_FXOFFS) a << sectors[i].floor_xoffs; if (diff2 & SD_FYOFFS) a << sectors[i].floor_yoffs; if (diff2 & SD_CXOFFS) a << sectors[i].ceiling_xoffs; if (diff2 & SD_CYOFFS) a << sectors[i].ceiling_yoffs; if (diff2 & SD_STAIRLOCK) a << sectors[i].stairlock; else sectors[i].stairlock = 0; if (diff2 & SD_NEXTSEC) a << sectors[i].nextsec; else sectors[i].nextsec = -1; if (diff2 & SD_PREVSEC) a << sectors[i].prevsec; else sectors[i].prevsec = -1; if (diff2 & SD_SEQTYPE) a << sectors[i].seqType; } while (1) { a << temp; // line number if (temp == MARK_END) break; li = &lines[temp]; a << diff; if (diff & LD_DIFF2) a << diff2; else diff2 = 0; if (diff & LD_FLAG) a << li->flags; if (diff & LD_SPECIAL) a << li->special; if (diff & LD_ARGS) for (i=0; i<5; i++) a << li->args[i]; si = li->sideptr[0]; if (diff & LD_S1TEXOFF) a << si->textureoffset; if (diff & LD_S1TOPTEX) a << si->toptexture; if (diff & LD_S1BOTTEX) a << si->bottomtexture; if (diff & LD_S1MIDTEX) a << si->midtexture; si = li->sideptr[1]; if (diff2 & LD_S2TEXOFF) a << si->textureoffset; if (diff2 & LD_S2TOPTEX) a << si->toptexture; if (diff2 & LD_S2BOTTEX) a << si->bottomtexture; if (diff2 & LD_S2MIDTEX) a << si->midtexture; } //---------------------------------------------- if (!a.Marker(MARK_POLYOBJ)) return -2; for (i = 0; i < NumPolyobjs; i++) { a << n; if (n != polyobjs[i].id) I_Error("Invalid polyobj tag!\n"); angle_t ang; a << ang; polyobjs[i].Rotate(ang); fixed_t x, y; a << x << y; polyobjs[i].Move(x - polyobjs[i].origin.x, y - polyobjs[i].origin.y); } //---------------------------------------------- // scripts if (!a.Marker(MARK_SCRIPT)) return -3; for (acs_script_iter_t i = ACS_scripts.begin(); i != ACS_scripts.end(); i++) { acs_script_t &s = i->second; a << (int &)s.state; //a << n; ACSInfo[i].state = acs_state_t(n); a << s.wait_data; } a.Read((byte *)ACS_map_vars, sizeof(ACS_map_vars)); // FS: restore levelscript FS_levelscript->Unserialize(a); // restore runningscripts // remove all runningscripts first: levelscript may have started them FS_ClearRunningScripts(); a << n; for (i=0; i<n; i++) { // create a new runningscript runningscript_t *rs = new runningscript_t(); int scriptnum; a << scriptnum; // levelscript? if (scriptnum == -1) rs->script = FS_levelscript; else rs->script = FS_levelscript->children[scriptnum]; a << n; // read out offset from save rs->savepoint = rs->script->data + n; a << n; rs->wait_type = fs_wait_e(n); a << rs->wait_data; rs->trigger = (Actor *)Thinker::Unserialize(a); // read out the variables now (fun!) // start with basic script slots/labels for (i=0; i<VARIABLESLOTS; i++) rs->variables[i] = rs->script->variables[i]; // get number of variables a << n; for (i=0; i<n; i++) { svariable_t *sv = (svariable_t*)Z_Malloc(sizeof(svariable_t), PU_LEVEL, 0); sv->Unserialize(a); // link in the new variable int hashkey = script_t::variable_hash(sv->name); sv->next = rs->variables[hashkey]; rs->variables[hashkey] = sv; } // hook into chain FS_AddRunningScript(rs); } // TODO Unarchive the script camera //---------------------------------------------- // Thinkers if (!a.Marker(MARK_THINK)) return -4; a << n; for (i=0; i<n; i++) { Thinker *th = Thinker::Unserialize(a); AddThinker(th); } if (!a.Marker(MARK_MISC)) return -5; //---------------------------------------------- // respawnqueue a << n; for (i=0; i<n; i++) { a << temp; itemrespawnqueue.push_back(&mapthings[temp]); a << temp; itemrespawntime.push_back(temp); } //---------------------------------------------- // the rest TID_map.clear(); a << n; for (i=0; i<n; i++) { Actor *p = NULL; a << stemp << temp; if (a.GetPtr((int &)temp, (void * &)p)) TID_map.insert(pair<const short, Actor*>(stemp, p)); else I_Error("Crap in TIDmap!\n"); } return 0; }