| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: /counterstrike/SAVELOAD.CPP 9 3/17/97 1:04a Steve_tall $ */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : SAVELOAD.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : August 23, 1994 *
- * *
- * Last Update : July 8, 1996 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * Code_All_Pointers -- Code all pointers. *
- * Decode_All_Pointers -- Decodes all pointers. *
- * Get_Savefile_Info -- gets description, scenario #, house *
- * Load_Game -- loads a saved game *
- * Load_MPlayer_Values -- Loads multiplayer-specific values *
- * Load_Misc_Values -- loads miscellaneous variables *
- * MPlayer_Save_Message -- pops up a "saving..." message *
- * Put_All -- Store all save game data to the pipe. *
- * Reconcile_Players -- Reconciles loaded data with the 'Players' vector *
- * Save_Game -- saves a game to disk *
- * Save_MPlayer_Values -- Saves multiplayer-specific values *
- * Save_Misc_Values -- saves miscellaneous variables *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "vortex.h"
- #ifdef WIN32
- #include "tcpip.h"
- #include "ccdde.h"
- //#include "WolDebug.h"
- extern bool DLLSave(Pipe &file);
- extern bool DLLLoad(Straw &file);
- extern bool SpawnedFromWChat;
- #endif
- //#define SAVE_BLOCK_SIZE 512
- #define SAVE_BLOCK_SIZE 4096
- //#define SAVE_BLOCK_SIZE 1024
- /*
- ********************************** Defines **********************************
- */
- #define SAVEGAME_VERSION (DESCRIP_MAX + \
- 0x01000006 + ( \
- sizeof(AircraftClass) + \
- sizeof(AircraftTypeClass) + \
- sizeof(AnimClass) + \
- sizeof(AnimTypeClass) + \
- sizeof(BaseClass) + \
- sizeof(BuildingClass) + \
- sizeof(BuildingTypeClass) + \
- sizeof(BulletClass) + \
- sizeof(BulletTypeClass) + \
- sizeof(CellClass) + \
- sizeof(FactoryClass) + \
- sizeof(HouseClass) + \
- sizeof(HouseTypeClass) + \
- sizeof(InfantryClass) + \
- sizeof(InfantryTypeClass) + \
- sizeof(LayerClass) + \
- sizeof(MouseClass) + \
- sizeof(OverlayClass) + \
- sizeof(OverlayTypeClass) + \
- sizeof(SmudgeClass) + \
- sizeof(SmudgeTypeClass) + \
- sizeof(TeamClass) + \
- sizeof(TeamTypeClass) + \
- sizeof(TemplateClass) + \
- sizeof(TemplateTypeClass) + \
- sizeof(TerrainClass) + \
- sizeof(TerrainTypeClass) + \
- sizeof(TriggerClass) + \
- sizeof(TriggerTypeClass) + \
- sizeof(UnitClass) + \
- sizeof(UnitTypeClass) + \
- sizeof(VesselClass) + \
- sizeof(ScenarioClass) + \
- sizeof(ChronalVortexClass)))
- // sizeof(Waypoint)))
- static int Reconcile_Players(void);
- extern bool Is_Mission_Counterstrike (char *file_name);
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- extern bool Is_Mission_Aftermath (char *file_name);
- #endif
- /***********************************************************************************************
- * Put_All -- Store all save game data to the pipe. *
- * *
- * This is the bulk processor of the game related save game data. All the game object *
- * and state data is stored to the pipe specified. *
- * *
- * INPUT: pipe -- Reference to the pipe that will receive the save game data. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 07/08/1996 JLB : Created. *
- *=============================================================================================*/
- static void Put_All(Pipe & pipe, int save_net)
- {
- /*
- ** Save the scenario global information.
- */
- pipe.Put(&Scen, sizeof(Scen));
- /*
- ** Save the map. The map must be saved first, since it saves the Theater.
- */
- if (!save_net) Call_Back();
- Map.Save(pipe);
- if (!save_net) Call_Back();
- /*
- ** Save all game objects. This code saves every object that's stored in a
- ** TFixedIHeap class.
- */
- Houses.Save(pipe);
- if (!save_net) Call_Back();
- TeamTypes.Save(pipe);
- if (!save_net) Call_Back();
- Teams.Save(pipe);
- if (!save_net) Call_Back();
- TriggerTypes.Save(pipe);
- if (!save_net) Call_Back();
- Triggers.Save(pipe);
- if (!save_net) Call_Back();
- Aircraft.Save(pipe);
- if (!save_net) Call_Back();
- Anims.Save(pipe);
- if (!save_net) Call_Back();
- Buildings.Save(pipe);
- if (!save_net) Call_Back();
- Bullets.Save(pipe);
- if (!save_net) Call_Back();
- Infantry.Save(pipe);
- if (!save_net) Call_Back();
- Overlays.Save(pipe);
- if (!save_net) Call_Back();
- Smudges.Save(pipe);
- if (!save_net) Call_Back();
- Templates.Save(pipe);
- if (!save_net) Call_Back();
- Terrains.Save(pipe);
- if (!save_net) Call_Back();
- Units.Save(pipe);
- if (!save_net) Call_Back();
- Factories.Save(pipe);
- if (!save_net) Call_Back();
- Vessels.Save(pipe);
- if (!save_net) Call_Back();
- /*
- ** Save the Logic & Map layers
- */
- Logic.Save(pipe);
- int count = MapTriggers.Count();
- pipe.Put(&count, sizeof(count));
- int index;
- for (int index = 0; index < MapTriggers.Count(); index++) {
- TARGET target = MapTriggers[index]->As_Target();
- pipe.Put(&target, sizeof(target));
- }
- if (!save_net) Call_Back();
- count = LogicTriggers.Count();
- pipe.Put(&count, sizeof(count));
- for (index = 0; index < LogicTriggers.Count(); index++) {
- TARGET target = LogicTriggers[index]->As_Target();
- pipe.Put(&target, sizeof(target));
- }
- if (!save_net) Call_Back();
- for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
- count = HouseTriggers[h].Count();
- pipe.Put(&count, sizeof(count));
- for (index = 0; index < HouseTriggers[h].Count(); index++) {
- TARGET target = HouseTriggers[h][index]->As_Target();
- pipe.Put(&target, sizeof(target));
- }
- }
- if (!save_net) Call_Back();
- for (int i = 0; i < LAYER_COUNT; i++) {
- Map.Layer[i].Save(pipe);
- }
- if (!save_net) Call_Back();
- /*
- ** Save the Score
- */
- pipe.Put(&Score, sizeof(Score));
- if (!save_net) Call_Back();
- /*
- ** Save the AI Base
- */
- Base.Save(pipe);
- if (!save_net) Call_Back();
- /*
- ** Save out the carry over list (if present). First see how
- ** many carry over objects are in the list.
- */
- int carry_count = 0;
- CarryoverClass const * cptr = Carryover;
- while (cptr != NULL) {
- carry_count++;
- cptr = (CarryoverClass const *)cptr->Get_Next();
- }
- if (!save_net) Call_Back();
- /*
- ** Save out the number of objects in the list.
- */
- pipe.Put(&carry_count, sizeof(carry_count));
- if (!save_net) Call_Back();
- /*
- ** Now write out the objects themselves.
- */
- CarryoverClass const * object_to_write = Carryover;
- while (object_to_write != NULL) {
- pipe.Put(object_to_write, sizeof(*object_to_write));
- object_to_write = (CarryoverClass const *)object_to_write->Get_Next();
- }
- if (!save_net) Call_Back();
- /*
- ** Save miscellaneous variables.
- */
- Save_Misc_Values(pipe);
- if (!save_net) Call_Back();
- /*
- ** Save multiplayer values
- */
- pipe.Put(&save_net, sizeof(save_net)); // Write out whether we saved the net values so we know if we have to load them again. ST - 10/22/2019 2:10PM
- if (save_net) {
- Save_MPlayer_Values(pipe);
- }
- pipe.Flush();
- }
- /***************************************************************************
- * Save_Game -- saves a game to disk *
- * *
- * Saving the Map: *
- * DisplayClass::Save() invokes CellClass's Write() for every cell *
- * that needs to be saved. A cell needs to be saved if it contains *
- * any special data at all, such as a TIcon, or an Occupier. *
- * The cell saves its own CellTrigger pointer, converted to a TARGET. *
- * *
- * Saving game objects: *
- * - Any object stored in an ArrayOf class needs to be saved. The ArrayOf*
- * Save() routine invokes each object's Write() routine, if that *
- * object's IsActive is set. *
- * *
- * Saving the layers: *
- * The Map's Layers (Ground, Air, etc) of things that are on the map, *
- * and the Logic's Layer of things to process both need to be saved. *
- * LayerClass::Save() writes the entire layer array to disk *
- * *
- * Saving the houses: *
- * Each house needs to be saved, to record its Credits, Power, etc. *
- * *
- * Saving miscellaneous data: *
- * There are a lot of miscellaneous variables to save, such as the *
- * map's dimensions, the player's house, etc. *
- * *
- * INPUT: *
- * id numerical ID, for the file extension *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/28/1994 BR : Created. *
- * 02/27/1996 JLB : Uses simpler game control value save operation. *
- *=========================================================================*/
- bool Save_Game(int id, char const * descr, bool )
- {
- char name[_MAX_FNAME+_MAX_EXT];
- /*
- ** Generate the filename to save. If 'id' is -1, it means save a
- ** network/modem game; otherwise, use 'id' as the file extension.
- */
- if (id==-1) {
- strcpy(name, NET_SAVE_FILE_NAME);
- //save_net = 1;
- } else {
- sprintf(name, "SAVEGAME.%03d", id);
- }
- return Save_Game(name, descr);
- }
- /*
- ** Version that takes file name. ST - 9/9/2019 11:10AM
- */
- bool NowSavingGame = false; // TEMP MBL: Need to discuss better solution with Steve
- bool Save_Game(const char *file_name, const char *descr)
- {
- NowSavingGame = true; // TEMP MBL: Need to discuss better solution with Steve
- int save_net = 0; // 1 = save network/modem game
-
- if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
- save_net = 1;
- }
-
- unsigned scenario;
- HousesType house;
- scenario = Scen.Scenario; // get current scenario #
- house = PlayerPtr->Class->House; // get current house
- /*
- ** Code everybody's pointers
- */
- Code_All_Pointers();
- /*
- ** Open the file
- */
- BufferIOFileClass file(file_name);
- FilePipe fpipe(&file);
- /*
- ** Save the DLLs variables first, so we can do a version check in the DLL when we begin the load
- */
- if (RunningAsDLL) {
- DLLSave(fpipe);
- }
- /*
- ** Save the description, scenario #, and house
- ** (scenario # & house are saved separately from the actual Scenario &
- ** PlayerPtr globals for convenience; we can quickly find out which
- ** house & scenario this save-game file is for by reading these values.
- ** Also, PlayerPtr is stored in a coded form in Save_Misc_Values(),
- ** which may or may not be a HousesType number; so, saving 'house'
- ** here ensures we can always pull out the house for this file.)
- */
- char descr_buf[DESCRIP_MAX];
- memset(descr_buf, '\0', sizeof(descr_buf));
- sprintf(descr_buf, "%s\r\n", descr); // put CR-LF after text
- //descr_buf[strlen(descr_buf) + 1] = 26; // put CTRL-Z after NULL
- fpipe.Put(descr_buf, DESCRIP_MAX);
- fpipe.Put(&scenario, sizeof(scenario));
- fpipe.Put(&house, sizeof(house));
- /*
- ** Save the save-game version, for loading verification
- */
- unsigned long version = SAVEGAME_VERSION;
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- version++;
- #endif
- fpipe.Put(&version, sizeof(version));
- int pos = file.Seek(0, SEEK_CUR);
- /*
- ** Store a dummy message digest.
- */
- char digest[20];
- fpipe.Put(digest, sizeof(digest));
- /*
- ** Dump the save game data to the file. The data is compressed
- ** and then encrypted. The message digest is calculated in the
- ** process by using the data just as it is written to disk.
- */
- SHAPipe sha;
- BlowPipe bpipe(BlowPipe::ENCRYPT);
- LZOPipe pipe(LZOPipe::COMPRESS, SAVE_BLOCK_SIZE);
- // LZWPipe pipe(LZWPipe::COMPRESS, SAVE_BLOCK_SIZE);
- // LCWPipe pipe(LCWPipe::COMPRESS, SAVE_BLOCK_SIZE);
- bpipe.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);
- sha.Put_To(fpipe);
- bpipe.Put_To(sha);
- pipe.Put_To(bpipe);
- Put_All(pipe, save_net);
- /*
- ** Output the real final message digest. This is the one that is of
- ** the data image as it exists on the disk.
- */
- pipe.Flush();
- file.Seek(pos, SEEK_SET);
- sha.Result(digest);
- fpipe.Put(digest, sizeof(digest));
- pipe.End();
- Decode_All_Pointers();
- NowSavingGame = false; // TEMP MBL: Need to discuss better solution with Steve
- return(true);
- }
- /***************************************************************************
- * Load_Game -- loads a saved game *
- * *
- * This routine loads the data in the same way it was saved out. *
- * *
- * Loading the Map: *
- * - DisplayClass::Load() invokes CellClass's Load() for every cell *
- * that was saved. *
- * - The cell loads its own CellTrigger pointer. *
- * *
- * Loading game objects: *
- * - IHeap's Load() routine loads the # of objects stored, and loads *
- * each object. *
- * - Triggers: Add themselves to the HouseTriggers if they're associated *
- * with a house *
- * *
- * Loading the layers: *
- * LayerClass::Load() reads the entire layer array to disk *
- * *
- * Loading the houses: *
- * Each house is loaded in its entirety. *
- * *
- * Loading miscellaneous data: *
- * There are a lot of miscellaneous variables to load, such as the *
- * map's dimensions, the player's house, etc. *
- * *
- * INPUT: *
- * id numerical ID, for the file extension *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * If this routine returns false, the entire game will be in an *
- * unknown state, so the scenario will have to be re-initialized. *
- * *
- * HISTORY: *
- * 12/28/1994 BR : Created. *
- * 1/20/97 V.Grippi Added expansion CD check *
- *=========================================================================*/
- bool Load_Game(int id)
- {
- char name[_MAX_FNAME+_MAX_EXT];
- /*
- ** Generate the filename to load. If 'id' is -1, it means save a
- ** network/modem game; otherwise, use 'id' as the file extension.
- */
- if (id == -1) {
- strcpy(name, NET_SAVE_FILE_NAME);
- //load_net = 1;
- } else {
- sprintf(name, "SAVEGAME.%03d", id);
- }
- return Load_Game(name);
- }
- /*
- ** Version that takes a file name instead. ST - 9/9/2019 11:13AM
- */
- bool Load_Game(const char *file_name)
- {
- int i;
- unsigned scenario;
- HousesType house;
- char descr_buf[DESCRIP_MAX];
- int load_net = 0; // 1 = save network/modem game
-
- /*
- ** Open the file
- */
- RawFileClass file(file_name);
- if (!file.Is_Available()) {
- return(false);
- }
- FileStraw fstraw(file);
- Call_Back();
- /*
- ** Load the DLLs variables first, in case we need to do something different based on version
- */
- if (RunningAsDLL) {
- DLLLoad(fstraw);
- }
- /*
- ** Read & discard the save-game's header info
- */
- if (fstraw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
- return(false);
- }
- if (fstraw.Get(&scenario, sizeof(scenario)) != sizeof(scenario)) {
- return(false);
- }
- if (fstraw.Get(&house, sizeof(house)) != sizeof(house)) {
- return(false);
- }
- /*
- ** Read in & verify the save-game ID code
- */
- unsigned long version;
- if (fstraw.Get(&version, sizeof(version)) != sizeof(version)) {
- return(false);
- }
- GameVersion = version;
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- if (version != SAVEGAME_VERSION && ((version-1) != SAVEGAME_VERSION) ) {
- return(false);
- }
- #else
- if (version != SAVEGAME_VERSION /*&& version != 0x0100616D*/){
- return(false);
- }
- #endif
- /*
- ** Get the message digest that is embedded in the file.
- */
- char digest[20];
- fstraw.Get(digest, sizeof(digest));
- /*
- ** Remember the file position since we must seek back here to
- ** perform the real saved game read.
- */
- long pos = file.Seek(0, SEEK_CUR);
- /*
- ** Pass the rest of the file through the hash straw so that
- ** the digest can be compaired to the one in the file.
- */
- SHAStraw sha;
- sha.Get_From(fstraw);
- for (;;) {
- if (sha.Get(_staging_buffer, sizeof(_staging_buffer)) != sizeof(_staging_buffer)) break;
- }
- char actual[20];
- sha.Result(actual);
- sha.Get_From(NULL);
- Call_Back();
- /*
- ** Compare the two digests. If they differ then return a failure condition
- ** before any damage could be done.
- */
- if (memcmp(actual, digest, sizeof(digest)) != 0) {
- return(false);
- }
- /*
- ** Set up the pipe so that the scenario data can be read.
- */
- file.Seek(pos, SEEK_SET);
- BlowStraw bstraw(BlowStraw::DECRYPT);
- LZOStraw straw(LZOStraw::DECOMPRESS, SAVE_BLOCK_SIZE);
- // LZWStraw straw(LZWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);
- // LCWStraw straw(LCWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);
- bstraw.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);
- bstraw.Get_From(fstraw);
- straw.Get_From(bstraw);
- /*
- ** Clear the scenario so we start fresh; this calls the Init_Clear() routine
- ** for the Map, and all object arrays. It has the following important
- ** effects:
- ** - Every cell is cleared to 0's, via MapClass::Init_Clear()
- ** - All heap elements' are cleared
- ** - The Houses are Initialized, which also clears their HouseTriggers
- ** array
- ** - The map's Layers & Logic Layer are cleared to empty
- ** - The list of currently-selected objects is cleared
- */
- Clear_Scenario();
- /*
- ** Load the scenario global information.
- */
- straw.Get(&Scen, sizeof(Scen));
- /*
- ** Fixup the Sessionclass scenario info so we can work out which
- ** CD to request later
- */
- if ( load_net ){
- CCFileClass scenario_file (Scen.ScenarioName);
- if ( !scenario_file.Is_Available() ){
- int cd = -1;
- if (Is_Mission_Counterstrike (Scen.ScenarioName)) {
- cd = 2;
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- if (Expansion_AM_Present()) {
- int current_drive = CCFileClass::Get_CD_Drive();
- int index = Get_CD_Index(current_drive, 1*60);
- if (index == 3) cd = 3;
- }
- #endif
- }
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- if (Is_Mission_Aftermath (Scen.ScenarioName)) {
- cd = 3;
- #ifdef BOGUSCD
- cd = -1;
- #endif
- }
- #endif
- RequiredCD = cd;
- if (!Force_CD_Available (RequiredCD)) {
- Emergency_Exit(EXIT_FAILURE);
- }
- /*
- ** Update the internal list of scenarios to include the counterstrike
- ** list.
- */
- Session.Read_Scenario_Descriptions();
- } else {
- /*
- ** The scenario is available so set RequiredCD to whatever is currently
- ** in the drive.
- */
- int current_drive = CCFileClass::Get_CD_Drive();
- RequiredCD = Get_CD_Index(current_drive, 1*60);
- }
- }
- /*
- ** Load the map. The map comes first, since it loads the Theater & init's
- ** mixfiles. The map calls all the type-class's Init routines, telling them
- ** what the Theater is; this must be done before any objects are created, so
- ** they'll be properly created.
- */
- Map.Load(straw);
- Call_Back();
- /*
- ** Load the object data.
- */
- Houses.Load(straw);
- TeamTypes.Load(straw);
- Teams.Load(straw);
- TriggerTypes.Load(straw);
- Triggers.Load(straw);
- Aircraft.Load(straw);
- Anims.Load(straw);
- Buildings.Load(straw);
- Bullets.Load(straw);
- Call_Back();
- Infantry.Load(straw);
- Overlays.Load(straw);
- Smudges.Load(straw);
- Templates.Load(straw);
- Terrains.Load(straw);
- Units.Load(straw);
- Factories.Load(straw);
- Vessels.Load(straw);
- /*
- ** Load the Logic & Map Layers
- */
- Logic.Load(straw);
- int count;
- straw.Get(&count, sizeof(count));
- MapTriggers.Clear();
- int index;
- for (index = 0; index < count; index++) {
- TARGET target;
- straw.Get(&target, sizeof(target));
- MapTriggers.Add(As_Trigger(target));
- }
- straw.Get(&count, sizeof(count));
- LogicTriggers.Clear();
- for (index = 0; index < count; index++) {
- TARGET target;
- straw.Get(&target, sizeof(target));
- LogicTriggers.Add(As_Trigger(target));
- }
- for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
- straw.Get(&count, sizeof(count));
- HouseTriggers[h].Clear();
- for (index = 0; index < count; index++) {
- TARGET target;
- straw.Get(&target, sizeof(target));
- HouseTriggers[h].Add(As_Trigger(target));
- }
- }
- for (i = 0; i < LAYER_COUNT; i++) {
- Map.Layer[i].Load(straw);
- }
- Call_Back();
- /*
- ** Load the Score
- */
- straw.Get(&Score, sizeof(Score));
- new(&Score) ScoreClass(NoInitClass());
- /*
- ** Load the AI Base
- */
- Base.Load(straw);
- /*
- ** Delete any carryover pseudo-saved game list.
- */
- while (Carryover != NULL) {
- CarryoverClass * cptr = (CarryoverClass *)Carryover->Get_Next();
- Carryover->Remove();
- delete Carryover;
- Carryover = cptr;
- }
- /*
- ** Load any carryover pseudo-saved game list.
- */
- int carry_count = 0;
- straw.Get(&carry_count, sizeof(carry_count));
- while (carry_count) {
- CarryoverClass * cptr = new CarryoverClass;
- assert(cptr != NULL);
- straw.Get(cptr, sizeof(CarryoverClass));
- new (cptr) CarryoverClass(NoInitClass());
- cptr->Zap();
- if (!Carryover) {
- Carryover = cptr;
- } else {
- cptr->Add_Tail(*Carryover);
- }
- carry_count--;
- }
- Call_Back();
- /*
- ** Load miscellaneous variables, including the map size & the Theater
- */
- Load_Misc_Values(straw);
- /*
- ** Load multiplayer values
- */
- straw.Get(&load_net, sizeof(load_net));
- if (load_net) {
- Load_MPlayer_Values(straw);
- }
- file.Close();
- Decode_All_Pointers();
- Map.Init_IO();
- Map.Flag_To_Redraw(true);
- /*
- ** Fixup any expediency data that can be inferred from the physical
- ** data loaded.
- */
- Post_Load_Game(load_net);
- /*
- ** Re-init unit trackers. They will be garbage pointers after the load
- */
- for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
- HouseClass * hptr = HouseClass::As_Pointer(house);
- if (hptr && hptr->IsActive) {
- hptr->Init_Unit_Trackers();
- }
- }
- Call_Back();
- /*
- ** Set the required CD to be in the drive according to the scenario
- ** loaded.
- */
- if (RequiredCD != -2 && !load_net) {
- #ifdef FIXIT_ANTS
- /*
- ** Determines if this an ant mission. Since the ant mission looks no different from
- ** a regular mission, examining of the scenario name is the only way to tell.
- */
- if (toupper(Scen.ScenarioName[0]) == 'S' &&
- toupper(Scen.ScenarioName[1]) == 'C' &&
- toupper(Scen.ScenarioName[2]) == 'A' &&
- toupper(Scen.ScenarioName[3]) == '0' &&
- toupper(Scen.ScenarioName[5]) == 'E' &&
- toupper(Scen.ScenarioName[6]) == 'A') {
- AntsEnabled = true;
- } else{
- AntsEnabled = false;
- }
- #endif
- if (Scen.Scenario == 1) {
- RequiredCD = -1;
- } else {
- #ifdef FIXIT_ANTS
- if (Scen.Scenario > 19 || AntsEnabled) {
- RequiredCD = 2;
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- if(Scen.Scenario >= 36) {
- RequiredCD = 3;
- #ifdef BOGUSCD
- RequiredCD = -1;
- #endif
- }
- #endif
- } else {
- #endif //FIXIT_ANTS
- if (PlayerPtr->Class->House != HOUSE_USSR && PlayerPtr->Class->House != HOUSE_UKRAINE) {
- RequiredCD = 0;
- } else {
- RequiredCD = 1;
- }
- #ifdef FIXIT_ANTS
- }
- #endif //FIXIT_ANTS
- }
- }else{
- if ( load_net ){
- CCFileClass scenario_file (Scen.ScenarioName);
- /*
- ** Fix up the session class variables
- */
- for ( int s=0 ; s<Session.Scenarios.Count() ; s++ ) {
- if (Session.Scenarios[s]->Description() == Scen.Description){
- memcpy (Session.Options.ScenarioDescription, Scen.Description,
- sizeof (Session.Options.ScenarioDescription));
- memcpy (Session.ScenarioFileName, Scen.ScenarioName,
- sizeof (Session.ScenarioFileName));
- Session.ScenarioFileLength = scenario_file.Size();
- memcpy (Session.ScenarioDigest, Session.Scenarios[s]->Get_Digest(),
- sizeof (Session.ScenarioDigest));
- Session.ScenarioIsOfficial = Session.Scenarios[s]->Get_Official();
- Scen.Scenario = s;
- Session.Options.ScenarioIndex = s;
- break;
- }
- }
- }
- }
- if (!Force_CD_Available(RequiredCD)) {
- Prog_End("Load_Game Force_CD_Available failed", true);
- Emergency_Exit(EXIT_FAILURE);
- }
- ScenarioInit = 0;
- if (load_net) {
- // Removed as this is ensured by the GlyphX & DLL save/load code. ST - 10/22/2019 5:20PM
- //if (!Reconcile_Players()) { // (must do after Decode pointers)
- // return(false);
- //}
-
- //!!!!!!!!!! put Fixup_Player_Units() here
- Session.LoadGame = true;
- }
- Map.Reload_Sidebar(); // re-load sidebar art.
- /*
- ** Rescan the scenario file for any rules updates.
- */
- CCINIClass ini;
- int result = ini.Load(CCFileClass(Scen.ScenarioName), true);
- /*
- ** Reset the rules values to their initial settings.
- */
- Rule.General(RuleINI);
- Rule.Recharge(RuleINI);
- Rule.AI(RuleINI);
- Rule.Powerups(RuleINI);
- Rule.Land_Types(RuleINI);
- Rule.Themes(RuleINI);
- Rule.IQ(RuleINI);
- Rule.Objects(RuleINI);
- Rule.Difficulty(RuleINI);
- #ifdef FIXIT_CSII // checked - ajw 9/28/98 - But does this incorporate *changes*? - NO.
- Rule.General(AftermathINI);
- Rule.Recharge(AftermathINI);
- Rule.AI(AftermathINI);
- Rule.Powerups(AftermathINI);
- Rule.Land_Types(AftermathINI);
- Rule.Themes(AftermathINI);
- Rule.IQ(AftermathINI);
- Rule.Objects(AftermathINI);
- Rule.Difficulty(AftermathINI);
- #endif
- /*
- ** Override any rules values specified in this
- ** particular scenario file.
- */
- Rule.General(ini);
- Rule.Recharge(ini);
- Rule.AI(ini);
- Rule.Powerups(ini);
- Rule.Land_Types(ini); \
- Rule.Themes(ini);
- Rule.IQ(ini);
- Rule.Objects(ini);
- Rule.Difficulty(ini);
- #ifdef FIXIT_CSII // ajw - Added runtime check for Aftermath to skirmish mode.
- if (load_net) {
- bool readini = false;
- switch(Session.Type) {
- case GAME_NORMAL:
- readini = false;
- break;
- case GAME_SKIRMISH:
- readini = Is_Aftermath_Installed();
- break;
- default:
- #ifdef FIXIT_VERSION_3
- readini = bAftermathMultiplayer;
- #else
- if (PlayingAgainstVersion >= VERSION_AFTERMATH_CS) {
- readini = true;
- }
- #endif
- break;
- }
- if(readini) {
- /*
- ** Find out if the CD in the current drive is the Aftermath disc.
- */
- if(Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != 3) {
- GamePalette.Set(FADE_PALETTE_FAST, Call_Back);
- if (!Force_CD_Available(3)) { // force Aftermath CD in drive.
- Prog_End("Load_Game Force_CD_Available(3) failed", true);
- #ifndef FIXIT_VERSION_3 // WChat eliminated.
- #ifdef WIN32
- if(Special.IsFromWChat || SpawnedFromWChat) {
- char packet[10] = {"Hello"};
- Send_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);
- }
- #endif
- #endif
- Emergency_Exit(EXIT_FAILURE);
- }
- }
- CCINIClass mpini;
- if (mpini.Load(CCFileClass("MPLAYER.INI"), false)) {
- Rule.General(mpini);
- Rule.Recharge(mpini);
- Rule.AI(mpini);
- Rule.Powerups(mpini);
- Rule.Land_Types(mpini);
- Rule.Themes(mpini);
- Rule.IQ(mpini);
- Rule.Objects(mpini);
- Rule.Difficulty(mpini);
- }
- }
- }
- #endif
- if (Scen.TransitTheme == THEME_NONE) {
- Theme.Queue_Song(THEME_FIRST);
- } else {
- Theme.Queue_Song(Scen.TransitTheme);
- }
-
- if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
- Rule.IsSmartDefense = true;
- }
-
- return(true);
- }
- /***************************************************************************
- * Save_Misc_Values -- saves miscellaneous variables *
- * *
- * INPUT: *
- * file file to use for writing *
- * *
- * OUTPUT: *
- * true = success, false = failure *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/29/1994 BR : Created. *
- * 03/12/1996 JLB : Simplified. *
- *=========================================================================*/
- bool Save_Misc_Values(Pipe & file)
- {
- int i, j;
- int count; // # ptrs in 'CurrentObject'
- ObjectClass * ptr; // for saving 'CurrentObject' ptrs
- /*
- ** Player's House.
- */
- int x = PlayerPtr->Class->House;
- file.Put(&x, sizeof(x));
- /*
- ** Save frame #.
- */
- file.Put(&Frame, sizeof(Frame));
- /*
- ** Save currently-selected objects list.
- ** Save the # of ptrs in the list.
- */
- for (i = 0; i < SelectedObjectsType::COUNT; i++) {
- DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
- count = selection.Count();
- file.Put(&count, sizeof(count));
- /*
- ** Save the pointers.
- */
- for (j = 0; j < count; j++) {
- ptr = selection[j];
- file.Put(&ptr, sizeof(ptr));
- }
- }
- /*
- ** Save the chronal vortex
- */
- ChronalVortex.Save(file);
- /*
- ** Save Tanya flags.
- */
- file.Put(&IsTanyaDead, sizeof(IsTanyaDead));
- file.Put(&SaveTanya, sizeof(SaveTanya));
- return(true);
- }
- /***********************************************************************************************
- * Load_Misc_Values -- Loads miscellaneous variables. *
- * *
- * INPUT: file -- The file to load the misc values from. *
- * *
- * OUTPUT: Was the misc load process successful? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/24/1995 BRR : Created. *
- * 03/12/1996 JLB : Simplified. *
- *=============================================================================================*/
- bool Load_Misc_Values(Straw & file)
- {
- ObjectClass * ptr; // for loading 'CurrentObject' ptrs
- /*
- ** Player's House.
- */
- int x;
- file.Get(&x, sizeof(x));
- // file.Get(&PlayerPtr, sizeof(PlayerPtr));
- PlayerPtr = HouseClass::As_Pointer((HousesType)x);
- /*
- ** Load frame #.
- */
- file.Get(&Frame, sizeof(Frame));
- for (int i = 0; i < SelectedObjectsType::COUNT; i++) {
- /*
- ** Load currently-selected objects list.
- ** Load the # of ptrs in the list.
- */
- DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
- int count; // # ptrs in 'CurrentObject'
- file.Get(&count, sizeof(count));
- /*
- ** Load the pointers.
- */
- for (int j = 0; j < count; j++) {
- file.Get(&ptr, sizeof(ptr));
- selection.Add(ptr); // add to the list
- }
- }
- /*
- ** Load the chronal vortex
- */
- ChronalVortex.Load(file);
- /*
- ** Save Tanya flags.
- */
- file.Get(&IsTanyaDead, sizeof(IsTanyaDead));
- file.Get(&SaveTanya, sizeof(SaveTanya));
- return(true);
- }
- /***************************************************************************
- * Save_MPlayer_Values -- Saves multiplayer-specific values *
- * *
- * This routine saves multiplayer values that need to be restored for a *
- * save game. In addition to saving the random # seed for this scenario, *
- * it saves the contents of the actual random number generator; this *
- * ensures that the random # sequencer will pick up where it left off when *
- * the game was saved. *
- * This routine also saves the header for a Recording file, so it must *
- * save some data not needed specifically by a save-game file (ie Seed). *
- * *
- * INPUT: *
- * file file to save to *
- * *
- * OUTPUT: *
- * true = success, false = failure *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 09/28/1995 BRR : Created. *
- *=========================================================================*/
- bool Save_MPlayer_Values(Pipe & file)
- {
- Session.Save(file);
- file.Put(&BuildLevel, sizeof(BuildLevel));
- file.Put(&Debug_Unshroud, sizeof(Debug_Unshroud));
- file.Put(&Seed, sizeof(Seed));
- file.Put(&Whom, sizeof(Whom));
- file.Put(&Special, sizeof(SpecialClass));
- file.Put(&Options, sizeof(GameOptionsClass));
- return (true);
- }
- /***************************************************************************
- * Load_MPlayer_Values -- Loads multiplayer-specific values *
- * *
- * INPUT: *
- * file file to load from *
- * *
- * OUTPUT: *
- * true = success, false = failure *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 09/28/1995 BRR : Created. *
- *=========================================================================*/
- bool Load_MPlayer_Values(Straw & file)
- {
- Session.Load(file);
- file.Get(&BuildLevel, sizeof(BuildLevel));
- file.Get(&Debug_Unshroud, sizeof(Debug_Unshroud));
- file.Get(&Seed, sizeof(Seed));
- file.Get(&Whom, sizeof(Whom));
- file.Get(&Special, sizeof(SpecialClass));
- file.Get(&Options, sizeof(GameOptionsClass));
- return (true);
- }
- /*
- ** ST - 9/26/2019 11:43AM
- */
- extern void DLL_Code_Pointers(void);
- extern void DLL_Decode_Pointers(void);
- /***********************************************************************************************
- * Code_All_Pointers -- Code all pointers. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/24/1995 BRR : Created. *
- *=============================================================================================*/
- void Code_All_Pointers(void)
- {
- int i, j;
- /*
- ** The Map.
- */
- Map.Code_Pointers();
- /*
- ** The ArrayOf's.
- */
- TeamTypes.Code_Pointers();
- Teams.Code_Pointers();
- Triggers.Code_Pointers();
- Aircraft.Code_Pointers();
- Anims.Code_Pointers();
- Buildings.Code_Pointers();
- Bullets.Code_Pointers();
- Infantry.Code_Pointers();
- Overlays.Code_Pointers();
- Smudges.Code_Pointers();
- Templates.Code_Pointers();
- Terrains.Code_Pointers();
- Units.Code_Pointers();
- Factories.Code_Pointers();
- Vessels.Code_Pointers();
- /*
- ** The Layers.
- */
- Logic.Code_Pointers();
- for (i = 0; i < LAYER_COUNT; i++) {
- Map.Layer[i].Code_Pointers();
- }
- /*
- ** The Score.
- */
- Score.Code_Pointers();
- /*
- ** The Base.
- */
- Base.Code_Pointers();
- /*
- ** PlayerPtr.
- */
- // PlayerPtr = (HouseClass *)(PlayerPtr->Class->House);
- /*
- ** Currently-selected objects.
- */
- for (i = 0; i < SelectedObjectsType::COUNT; i++) {
- DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
- for (j = 0; j < selection.Count(); j++) {
- selection[j] = (ObjectClass *)selection[j]->As_Target();
- }
- }
- /*
- ** DLL data
- */
- DLL_Code_Pointers();
- /*
- ** Houses must be coded last, because the Class->House member of the HouseClass
- ** is used to code HouseClass pointers for all other objects, and if Class is
- ** coded, it will point to a meaningless value.
- */
- Houses.Code_Pointers();
- }
- /***********************************************************************************************
- * Decode_All_Pointers -- Decodes all pointers. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/24/1995 BRR : Created. *
- *=============================================================================================*/
- void Decode_All_Pointers(void)
- {
- /*
- ** The Map.
- */
- Map.Decode_Pointers();
- /*
- ** Decode houses first, so we can properly decode all other objects'
- ** House pointers
- */
- Houses.Decode_Pointers();
- /*
- ** DLL data
- */
- DLL_Decode_Pointers();
- /*
- ** The ArrayOf's.
- */
- TeamTypes.Decode_Pointers();
- Teams.Decode_Pointers();
- Triggers.Decode_Pointers();
- Aircraft.Decode_Pointers();
- Anims.Decode_Pointers();
- Buildings.Decode_Pointers();
- Bullets.Decode_Pointers();
- Infantry.Decode_Pointers();
- Overlays.Decode_Pointers();
- Smudges.Decode_Pointers();
- Templates.Decode_Pointers();
- Terrains.Decode_Pointers();
- Units.Decode_Pointers();
- Factories.Decode_Pointers();
- Vessels.Decode_Pointers();
- /*
- ** The Layers.
- */
- Logic.Decode_Pointers();
- for (int i = 0; i < LAYER_COUNT; i++) {
- Map.Layer[i].Decode_Pointers();
- }
- /*
- ** The Score.
- */
- Score.Decode_Pointers();
- /*
- ** The Base.
- */
- Base.Decode_Pointers();
- /*
- ** PlayerPtr.
- */
- // PlayerPtr = HouseClass::As_Pointer((HousesType)PlayerPtr);
- Whom = PlayerPtr->Class->House;
- assert(PlayerPtr != NULL);
- /*
- ** Currently-selected objects.
- */
- for (int index = 0; index < SelectedObjectsType::COUNT; index++) {
- DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(index);
- for (int j = 0; j < selection.Count(); j++) {
- selection[j] = As_Object((TARGET)selection[j]);
- assert(selection[j] != NULL);
- }
- }
- /*
- ** Last-Minute Fixups; to resolve these pointers properly requires all other
- ** pointers to be loaded & decoded.
- */
- if (Map.PendingObjectPtr) {
- Map.PendingObject = &Map.PendingObjectPtr->Class_Of();
- assert(Map.PendingObject != NULL);
- Map.Set_Cursor_Shape(Map.PendingObject->Occupy_List(true));
- #ifdef BG
- Map.Set_Placement_List(Map.PendingObject->Placement_List(true));
- #endif
- } else {
- Map.PendingObject = 0;
- Map.Set_Cursor_Shape(0);
- }
- }
- /***************************************************************************
- * Get_Savefile_Info -- gets description, scenario #, house *
- * *
- * INPUT: *
- * id numerical ID, for the file extension *
- * buf buffer to store description in *
- * scenp ptr to variable to hold scenario *
- * housep ptr to variable to hold house *
- * *
- * OUTPUT: *
- * true = OK, false = error (save-game file invalid) *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/12/1995 BR : Created. *
- *=========================================================================*/
- bool Get_Savefile_Info(int id, char * buf, unsigned * scenp, HousesType * housep)
- {
- char name[_MAX_FNAME+_MAX_EXT];
- unsigned long version;
- char descr_buf[DESCRIP_MAX];
- /*
- ** Generate the filename to load
- */
- sprintf(name, "SAVEGAME.%03d", id);
- BufferIOFileClass file(name);
- FileStraw straw(file);
- /*
- ** Read in the description, scenario #, and the house
- */
- if (straw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
- return(false);
- }
- descr_buf[strlen(descr_buf) - 2] = '\0'; // trim off CR/LF
- strcpy(buf, descr_buf);
- if (straw.Get(scenp, sizeof(unsigned)) != sizeof(unsigned)) {
- return(false);
- }
- if (straw.Get(housep, sizeof(HousesType)) != sizeof(HousesType)) {
- return(false);
- }
- /*
- ** Read & verify the save-game version #
- */
- if (straw.Get(&version, sizeof(version)) != sizeof(version)) {
- return(false);
- }
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- if (version != SAVEGAME_VERSION && ((version-1 != SAVEGAME_VERSION)) ) {
- #else
- if (version != SAVEGAME_VERSION) {
- #endif
- return(false);
- }
- return(true);
- }
- /***************************************************************************
- * Reconcile_Players -- Reconciles loaded data with the 'Players' vector *
- * *
- * This function is for supporting loading a saved multiplayer game. *
- * When the game is loaded, we have to figure out which house goes with *
- * which entry in the Players vector. We also have to figure out if *
- * everyone who was originally in the game is still with us, and if not, *
- * turn their stuff over to the computer. *
- * *
- * So, this function does the following: *
- * - For every name in 'Players', makes sure that name is in the House *
- * array; if not, it's a fatal error. *
- * - For every human-controlled house, makes sure there's a player *
- * with that name; if not, it turns that house over to the computer. *
- * - Fills in the Player's house ID *
- * *
- * This assumes that each player MUST keep their name the same as it was *
- * when the game was saved! It's also assumed that the network *
- * connections have not been formed yet, since Player[i]->Player.ID will *
- * be invalid until this routine has been called. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 09/29/1995 BRR : Created. *
- *=========================================================================*/
- static int Reconcile_Players(void)
- {
- int i;
- int found;
- HousesType house;
- HouseClass * housep;
- /*
- ** If there are no players, there's nothing to do.
- */
- if (Session.Players.Count()==0)
- return (true);
- /*
- ** Make sure every name we're connected to can be found in a House
- */
- for (i = 0; i < Session.Players.Count(); i++) {
- found = 0;
- for (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +
- Session.MaxPlayers; house++) {
- housep = HouseClass::As_Pointer(house);
- if (!housep) {
- continue;
- }
- if (!stricmp(Session.Players[i]->Name, housep->IniName)) {
- found = 1;
- break;
- }
- }
- if (!found)
- return (false);
- }
- //
- // Loop through all Houses; if we find a human-owned house that we're
- // not connected to, turn it over to the computer.
- //
- for (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +
- Session.MaxPlayers; house++) {
- housep = HouseClass::As_Pointer(house);
- if (!housep) {
- continue;
- }
- //
- // Skip this house if it wasn't human to start with.
- //
- if (!housep->IsHuman) {
- continue;
- }
- //
- // Try to find this name in the Players vector; if it's found, set
- // its ID to this house.
- //
- found = 0;
- for (i = 0; i < Session.Players.Count(); i++) {
- if (!stricmp(Session.Players[i]->Name, housep->IniName)) {
- found = 1;
- Session.Players[i]->Player.ID = house;
- break;
- }
- }
- /*
- ** If this name wasn't found, remove it
- */
- if (!found) {
- /*
- ** Turn the player's house over to the computer's AI
- */
- housep->IsHuman = false;
- housep->IsStarted = true;
- // housep->Smartness = IQ_MENSA;
- housep->IQ = Rule.MaxIQ;
- strcpy (housep->IniName, Text_String(TXT_COMPUTER));
- Session.NumPlayers--;
- }
- }
- //
- // If all went well, our Session.NumPlayers value should now equal the value
- // from the saved game, minus any players we removed.
- //
- if (Session.NumPlayers == Session.Players.Count()) {
- return (true);
- } else {
- return (false);
- }
- }
- /***************************************************************************
- * MPlayer_Save_Message -- pops up a "saving..." message *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 10/30/1995 BRR : Created. *
- *=========================================================================*/
- void MPlayer_Save_Message(void)
- {
- //char *txt = Text_String(
- }
|