bool Level::LoadState(Stream *pstm) { // Do version handling byte nVer = pstm->ReadByte(); if (nVer != knVerLevelState) return false; // Get level name char szLevel[kcbFilename]; pstm->ReadString(szLevel, sizeof(szLevel)); // Load level constants if (!Init(szLevel, true)) { return false; } // Check to see if the save game has a different mission revision number than the mission // itself. If so, error. This is the case if a game is saved, then the level is revised // in M and reloaded. dword dwRevision = pstm->ReadDword(); if (dwRevision != m_dwRevision) { HtMessageBox(kfMbWhiteBorder | kfMbClearDib, "Error", "This saved game is based on an older version of this mission!"); return false; } // Load gobm state if (!ggobm.LoadState(pstm)) return false; // Load fog and galaxite state if (!m_pfogm->LoadState(pstm)) { return false; } if (!m_ptrmap->LoadState(pstm)) { return false; } // Load gobs int cGobs = pstm->ReadWord(); while (cGobs-- != 0) { // Get gob type GobType gt = pstm->ReadByte(); Gob *pgob = CreateGob(gt); if (pgob == NULL) { return false; } if (!pgob->LoadState(pstm)) { return false; } } // Load triggers if (!m_tgrm.LoadState(pstm)) { return false; } // Load UnitGroups if (!m_ugm.LoadState(pstm)) { return false; } return pstm->IsSuccess(); }
bool Level::LoadLevelConstants(const char *pszLevelName, IniReader *pini) { if (!LoadLevelInfo(pszLevelName, pini)) return false; // m_fInitialized is to distinguish between just having the level parameters // read and having been initialized enough to require some cleanup. m_fInitialized = true; // Load map Status("Load Tile Map..."); char szT[kcbFilename]; if (!pini->GetPropertyValue("General", "TileMap", szT, sizeof(szT))) { Assert(false); return false; } Size sizPlayfield; ggame.GetPlayfieldSize(&sizPlayfield); m_ptmap = LoadTileMap(szT, &sizPlayfield); Assert(m_ptmap != NULL); if (m_ptmap == NULL) { Assert(false); return false; } // Init GobMgr Size sizMap; m_ptmap->GetMapSize(&sizMap); Size sizTile; m_ptmap->GetTileSize(&sizTile); if (!ggobm.Init(sizMap.cx / sizTile.cx, sizMap.cy / sizTile.cy, kcpgobMax)) { Assert(false); return false; } // Load terrain map Status("Load Terrain Map..."); if (!pini->GetPropertyValue("General", "TerrainMap", szT, sizeof(szT))) { Assert(false); return false; } m_ptrmap = new TerrainMap; if (m_ptrmap == NULL) { Assert(false); return false; } if (!m_ptrmap->Init(szT)) { Assert(false); return false; } // Create fog map. Status("Create Fog Map..."); m_pfogm = new FogMap; if (m_pfogm == NULL) { Assert(false); return false; } if (!m_pfogm->Init(&sizTile, &sizMap)) { Assert(false); return false; } // Load palette if (!pini->GetPropertyValue("General", "Palette", szT, sizeof(szT))) { Assert(false); return false; } m_ppal = (Palette *)gpakr.MapFile(szT, &m_fmapPalette); if (m_ppal == NULL) { Assert(false); return false; } strcat(szT, ".shadowmap"); m_mpiclriclrShadow = (byte *)gpakr.MapFile(szT, &m_fmapShadowMap); // Instantiate an OvermindGob for each Computer Player Player *pplr = gplrm.GetNextPlayer(NULL); for (; pplr != NULL; pplr = gplrm.GetNextPlayer(pplr)) { #ifdef STRESS // Instantiate an Overmind for the human player if we're running stress if (gfStress) { if ((pplr->GetFlags() & (kfPlrComputer | kfPlrComputerOvermind)) == kfPlrComputer) continue; } else { if (!(pplr->GetFlags() & kfPlrComputerOvermind)) continue; } #else if (!(pplr->GetFlags() & kfPlrComputerOvermind)) continue; #endif // Instantiate and initialize an OvermindGob OvermindGob *pgobOvermind = (OvermindGob *)CreateGob(kgtOvermind); if (pgobOvermind == NULL) { Assert(false); delete pini; return false; } if (!pgobOvermind->Init(NULL)) { Assert(false); delete pgobOvermind; delete pini; return false; } // Who's your daddy? pgobOvermind->SetOwner(pplr); } // Load the Triggers Status("Load Triggers..."); if (!m_tgrm.Init(pini)) { Assert(false); return false; } // Load the UnitGroups Status("Load UnitGroups..."); if (!m_ugm.Init(pini)) { Assert(false); return false; } return true; }
bool Level::LoadLevelVariables(IniReader *pini) { // Load areas Status("Load Areas..."); if (!ggobm.LoadAreas(pini)) { return false; } // Enumerate all Gob descriptions and instantiate in-memory versions Status("Load Gobs..."); char szName[kcbFilename]; FindProp find; while (pini->FindNextProperty(&find, "GameObjects", szName, sizeof(szName))) { GobType gt; pini->GetPropertyValue(&find, "%d,", >); Gob *pgob = CreateGob(gt); if (pgob == NULL) { Assert(false); return false; } // Don't waste space on Gobs that don't need names char *pszName; if (strcmp("nil", szName) == 0) pszName = NULL; else pszName = szName; if (!pgob->Init(pini, &find, pszName)) { Assert(false); delete pgob; return false; } #ifdef STRESS if (gfStress) { // Make player's units invulnerable if (pgob->GetOwner() == gpplrLocal) { if (pgob->GetFlags() & kfGobUnit) { UnitGob *punt = (UnitGob *)pgob; punt->SetUnitFlags(punt->GetUnitFlags() | kfUnitInvulnerable); } } } #endif } // Enumerate all Galaxite positions and add them to the Fog/Galaxite map Status("Load Galaxite..."); FindProp find2; while (pini->FindNextProperty(&find2, "Galaxite", szName, sizeof(szName))) { int nGx, tx, ty; pini->GetPropertyValue(&find2, "%d,%d,%d", &nGx, &tx, &ty); m_pfogm->SetGalaxite(nGx, tx, ty); } // In terrain for the moment (forever?) #if 0 // Enumerate all Wall positions and add them to the Fog/Galaxite/Wall map Status("Load walls..."); FindProp find3; while (pini->FindNextProperty(&find3, "Walls", szName, sizeof(szName))) { int nHealth, tx, ty; pini->GetPropertyValue(&find3, "%d,%d,%d", &nHealth, &tx, &ty); m_pfogm->SetWallHealth(nHealth, tx, ty); } #endif // Instantiate the "CreateAtLevelLoad" UnitGroups m_ugm.CreateAtLevelLoadGroups(); return true; }
int ReplicatorGob::ProcessStateMachineMessage(State st, Message *pmsg) { BeginStateMachine OnMsg(kmidPlaySfx) gsndm.PlaySfx((Sfx)pmsg->PlaySfx.sfx); State(kstIdle) OnUpdate // If a mobile unit is at either output, ask it to move on TPoint tpt; GetTilePosition(&tpt); Gid gid; // Clear left and right output bays Player *pplrNeedCredits = NULL; bool fJammed = ClearOutputBay(tpt.tx + kdtxReplicatorOutput1, tpt.ty + kdtyReplicatorOutput1, tpt.tx + kdtxReplicatorOutput1 - 1, tpt.ty + kdtyReplicatorOutput1 + 1); fJammed = ClearOutputBay(tpt.tx + kdtxReplicatorOutput2, tpt.ty + kdtyReplicatorOutput2, tpt.tx + kdtxReplicatorOutput2 + 1, tpt.ty + kdtyReplicatorOutput2 + 1) || fJammed; // If there's nothing clogging the outputs we can consider the input if (m_fEnabled && !fJammed) { // loop through all the gobs on this tile to find the mobile unit and ignore ourself, or // shots flying by for (gid = ggobm.GetFirstGid(tpt.tx + kdtxReplicatorInput, tpt.ty + kdtyReplicatorInput); gid != kgidNull; gid = ggobm.GetNextGid(gid)) { MobileUnitGob *pmunt = (MobileUnitGob *)ggobm.GetGob(gid); if (pmunt == NULL) continue; if (!(pmunt->GetFlags() & kfGobMobileUnit)) continue; // Something there! If it's ready, clone it. if (!(pmunt->GetMobileUnitFlags() & kfMuntAtReplicatorInput)) continue; // At the limit? // TUNE: #define kctIntervalLimitNotify 600 if (!ggobm.IsBelowLimit(knLimitMobileUnit, pmunt->GetOwner())) { if (pmunt->GetOwner() == gpplrLocal) { static long s_tLastNotify; long tCurrent = gtimm.GetTickCount(); if (abs((int)(s_tLastNotify - tCurrent)) >= kctIntervalLimitNotify) { s_tLastNotify = tCurrent; ShowAlert(kidsUnitLimitReached); } } continue; } // Does the player have enough credits to perform the replication? MobileUnitConsts *pmuntc = (MobileUnitConsts *)pmunt->GetConsts(); Player *pplr = pmunt->GetOwner(); int cCredits = pplr->GetCredits(); int nCost = pmuntc->GetCost(); int cReplicationCost = GetReplicationCost(nCost); if (cCredits < cReplicationCost) { pplrNeedCredits = pplr; break; } // Take the money! pplr->SetCredits(cCredits - cReplicationCost, true); // Remove highlight pmunt->Hilight(false); // Start the replicating animation m_fReplicating = true; m_ifrmLights = -1; MobileUnitGob *pmuntClone = (MobileUnitGob *)CreateGob(pmunt->GetType()); if (pmuntClone != NULL) { pmuntClone->Init(WcFromTc(tpt.tx + kdtxReplicatorOutput2), WcFromTc(tpt.ty + kdtyReplicatorOutput2), pmunt->GetOwner(), pmunt->GetHealth(), 0, NULL); // Clone acquires the selection state of the original if (pmunt->GetFlags() & kfGobSelected) pmuntClone->Select(true); // Replicated GalaxMiners lose their load of Galaxite // UNDONE: if there is more of this special casing go with virtual UnitGob::Replicate() if (pmunt->GetType() == kgtGalaxMiner) ((MinerGob *)pmunt)->SetGalaxiteAmount(0); // If this unit is a member of a group add its clone to the group too UnitGroup *pug = gsim.GetLevel()->GetUnitGroupMgr()->GetUnitGroup(pmunt->GetId()); if (pug != NULL) pug->AddUnit(pmuntClone, true); } // Warp the original Unit to the left output port TerrainMap *ptrmap = gsim.GetLevel()->GetTerrainMap(); ptrmap->ClearFlags(tpt.tx + kdtxReplicatorInput, tpt.ty + kdtyReplicatorInput, 1, 1, kbfMobileUnit); ptrmap->SetFlags(tpt.tx + kdtxReplicatorOutput1, tpt.ty + kdtyReplicatorOutput1, 1, 1, kbfMobileUnit); pmunt->SetPosition(WcFromTc(tpt.tx + kdtxReplicatorOutput1) + kwcTileHalf, WcFromTc(tpt.ty + kdtyReplicatorOutput1) + kwcTileHalf); // Clear the bit pmunt->SetMobileUnitFlags(pmunt->GetMobileUnitFlags() & ~kfMuntAtReplicatorInput); // Let player know the replication process has happened // play cool replication sound effect gsndm.PlaySfx(ksfxReplicatorBuild); // wait a quarter second and let the new unit announce itself Sfx sfx = SfxFromCategory(pmuntc->sfxcSelect); Message msgT; memset(&msgT, 0, sizeof(msgT)); msgT.mid = kmidPlaySfx; msgT.smidSender = m_gid; msgT.smidReceiver = m_gid; msgT.PlaySfx.sfx = sfx; gsmm.SendDelayedMsg(&msgT, 24); // Play it again in another quarter of a second to sound cool memset(&msgT, 0, sizeof(msgT)); msgT.mid = kmidPlaySfx; msgT.smidSender = m_gid; msgT.smidReceiver = m_gid; msgT.PlaySfx.sfx = sfx; gsmm.SendDelayedMsg(&msgT, 48); break; } } if (m_fReplicating) { m_ifrmLights++; int nStrip = m_pmuntc->panid->GetStripIndex("l 0"); if (m_ifrmLights / 2 >= m_pmuntc->panid->GetFrameCount(nStrip)) { m_ifrmLights = -1; m_fReplicating = false; } MarkRedraw(); } WaitingForCredits(pplrNeedCredits != NULL, false, pplrNeedCredits); m_unvl.MinSkip(); DefUpdate(); #if 0 EndStateMachineInherit(StructGob) #else return knHandled; }