2019-09-19 22:42:45 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
|
|
Copyright (C) 2019 Nuke.YKT
|
|
|
|
|
|
|
|
This file is part of NBlood.
|
|
|
|
|
|
|
|
NBlood is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License version 2
|
|
|
|
as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-09-21 18:59:54 +00:00
|
|
|
#include "ns.h" // Must come before everything else!
|
|
|
|
|
2019-09-19 22:42:45 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "build.h"
|
|
|
|
#include "compat.h"
|
|
|
|
#include "mmulti.h"
|
|
|
|
#include "common_game.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "ai.h"
|
|
|
|
#include "asound.h"
|
|
|
|
#include "blood.h"
|
|
|
|
#include "demo.h"
|
|
|
|
#include "globals.h"
|
|
|
|
#include "db.h"
|
|
|
|
#include "messages.h"
|
2019-12-05 18:00:40 +00:00
|
|
|
#include "gamemenu.h"
|
2019-09-19 22:42:45 +00:00
|
|
|
#include "network.h"
|
|
|
|
#include "loadsave.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "screen.h"
|
|
|
|
#include "sectorfx.h"
|
|
|
|
#include "seq.h"
|
|
|
|
#include "sfx.h"
|
|
|
|
#include "sound.h"
|
2019-11-01 23:38:30 +00:00
|
|
|
#include "i_specialpaths.h"
|
2019-09-19 22:42:45 +00:00
|
|
|
#include "view.h"
|
2020-02-07 19:47:43 +00:00
|
|
|
#include "nnexts.h"
|
2019-11-14 20:07:43 +00:00
|
|
|
#include "savegamehelp.h"
|
2020-04-12 06:07:48 +00:00
|
|
|
#include "raze_music.h"
|
2019-12-10 21:22:59 +00:00
|
|
|
#include "mapinfo.h"
|
2019-09-19 22:42:45 +00:00
|
|
|
|
2020-02-11 23:22:11 +00:00
|
|
|
#include "aibat.h"
|
|
|
|
#include "aibeast.h"
|
|
|
|
#include "aiboneel.h"
|
|
|
|
#include "aiburn.h"
|
|
|
|
#include "aicaleb.h"
|
|
|
|
#include "aicerber.h"
|
|
|
|
#include "aicult.h"
|
|
|
|
#include "aigarg.h"
|
|
|
|
#include "aighost.h"
|
|
|
|
#include "aigilbst.h"
|
|
|
|
#include "aihand.h"
|
|
|
|
#include "aihound.h"
|
|
|
|
#include "aiinnoc.h"
|
|
|
|
#include "aipod.h"
|
|
|
|
#include "airat.h"
|
|
|
|
#include "aispid.h"
|
|
|
|
#include "aitchern.h"
|
|
|
|
#include "aizomba.h"
|
|
|
|
#include "aizombf.h"
|
|
|
|
#include "aiunicult.h"
|
|
|
|
|
|
|
|
|
2019-09-22 06:39:22 +00:00
|
|
|
BEGIN_BLD_NS
|
|
|
|
|
2020-02-11 23:22:11 +00:00
|
|
|
// All AI states for assigning an index.
|
|
|
|
static AISTATE* allAIStates[] =
|
|
|
|
{
|
|
|
|
nullptr,
|
|
|
|
&genIdle,
|
|
|
|
&genRecoil,
|
|
|
|
&batIdle,
|
|
|
|
&batFlyIdle,
|
|
|
|
&batChase,
|
|
|
|
&batPonder,
|
|
|
|
&batGoto,
|
|
|
|
&batBite,
|
|
|
|
&batRecoil,
|
|
|
|
&batSearch,
|
|
|
|
&batSwoop,
|
|
|
|
&batFly,
|
|
|
|
&batTurn,
|
|
|
|
&batHide,
|
|
|
|
&batDodgeUp,
|
|
|
|
&batDodgeUpRight,
|
|
|
|
&batDodgeUpLeft,
|
|
|
|
&batDodgeDown,
|
|
|
|
&batDodgeDownRight,
|
|
|
|
&batDodgeDownLeft,
|
|
|
|
&beastIdle,
|
|
|
|
&beastChase,
|
|
|
|
&beastDodge,
|
|
|
|
&beastGoto,
|
|
|
|
&beastSlash,
|
|
|
|
&beastStomp,
|
|
|
|
&beastSearch,
|
|
|
|
&beastRecoil,
|
|
|
|
&beastTeslaRecoil,
|
|
|
|
&beastSwimIdle,
|
|
|
|
&beastSwimChase,
|
|
|
|
&beastSwimDodge,
|
|
|
|
&beastSwimGoto,
|
|
|
|
&beastSwimSearch,
|
|
|
|
&beastSwimSlash,
|
|
|
|
&beastSwimRecoil,
|
|
|
|
&beastMorphToBeast,
|
|
|
|
&beastMorphFromCultist,
|
|
|
|
&beast138FB4,
|
|
|
|
&beast138FD0,
|
|
|
|
&beast138FEC,
|
|
|
|
&eelIdle,
|
|
|
|
&eelFlyIdle,
|
|
|
|
&eelChase,
|
|
|
|
&eelPonder,
|
|
|
|
&eelGoto,
|
|
|
|
&eelBite,
|
|
|
|
&eelRecoil,
|
|
|
|
&eelSearch,
|
|
|
|
&eelSwoop,
|
|
|
|
&eelFly,
|
|
|
|
&eelTurn,
|
|
|
|
&eelHide,
|
|
|
|
&eelDodgeUp,
|
|
|
|
&eelDodgeUpRight,
|
|
|
|
&eelDodgeUpLeft,
|
|
|
|
&eelDodgeDown,
|
|
|
|
&eelDodgeDownRight,
|
|
|
|
&eelDodgeDownLeft,
|
|
|
|
&cultistBurnIdle,
|
|
|
|
&cultistBurnChase,
|
|
|
|
&cultistBurnGoto,
|
|
|
|
&cultistBurnSearch,
|
|
|
|
&cultistBurnAttack,
|
|
|
|
&zombieABurnChase,
|
|
|
|
&zombieABurnGoto,
|
|
|
|
&zombieABurnSearch,
|
|
|
|
&zombieABurnAttack,
|
|
|
|
&zombieFBurnChase,
|
|
|
|
&zombieFBurnGoto,
|
|
|
|
&zombieFBurnSearch,
|
|
|
|
&zombieFBurnAttack,
|
|
|
|
&innocentBurnChase,
|
|
|
|
&innocentBurnGoto,
|
|
|
|
&innocentBurnSearch,
|
|
|
|
&innocentBurnAttack,
|
|
|
|
&beastBurnChase,
|
|
|
|
&beastBurnGoto,
|
|
|
|
&beastBurnSearch,
|
|
|
|
&beastBurnAttack,
|
|
|
|
&tinycalebBurnChase,
|
|
|
|
&tinycalebBurnGoto,
|
|
|
|
&tinycalebBurnSearch,
|
|
|
|
&tinycalebBurnAttack,
|
|
|
|
&genDudeBurnIdle,
|
|
|
|
&genDudeBurnChase,
|
|
|
|
&genDudeBurnGoto,
|
|
|
|
&genDudeBurnSearch,
|
|
|
|
&genDudeBurnAttack,
|
|
|
|
&tinycalebIdle,
|
|
|
|
&tinycalebChase,
|
|
|
|
&tinycalebDodge,
|
|
|
|
&tinycalebGoto,
|
|
|
|
&tinycalebAttack,
|
|
|
|
&tinycalebSearch,
|
|
|
|
&tinycalebRecoil,
|
|
|
|
&tinycalebTeslaRecoil,
|
|
|
|
&tinycalebSwimIdle,
|
|
|
|
&tinycalebSwimChase,
|
|
|
|
&tinycalebSwimDodge,
|
|
|
|
&tinycalebSwimGoto,
|
|
|
|
&tinycalebSwimSearch,
|
|
|
|
&tinycalebSwimAttack,
|
|
|
|
&tinycalebSwimRecoil,
|
|
|
|
&tinycaleb139660,
|
|
|
|
&tinycaleb13967C,
|
|
|
|
&tinycaleb139698,
|
|
|
|
&cerberusIdle,
|
|
|
|
&cerberusSearch,
|
|
|
|
&cerberusChase,
|
|
|
|
&cerberusRecoil,
|
|
|
|
&cerberusTeslaRecoil,
|
|
|
|
&cerberusGoto,
|
|
|
|
&cerberusBite,
|
|
|
|
&cerberusBurn,
|
|
|
|
&cerberus3Burn,
|
|
|
|
&cerberus2Idle,
|
|
|
|
&cerberus2Search,
|
|
|
|
&cerberus2Chase,
|
|
|
|
&cerberus2Recoil,
|
|
|
|
&cerberus2Goto,
|
|
|
|
&cerberus2Bite,
|
|
|
|
&cerberus2Burn,
|
|
|
|
&cerberus4Burn,
|
|
|
|
&cerberus139890,
|
|
|
|
&cerberus1398AC,
|
|
|
|
&cultistIdle,
|
|
|
|
&cultistProneIdle,
|
|
|
|
&fanaticProneIdle,
|
|
|
|
&cultistProneIdle3,
|
|
|
|
&cultistChase,
|
|
|
|
&fanaticChase,
|
|
|
|
&cultistDodge,
|
|
|
|
&cultistGoto,
|
|
|
|
&cultistProneChase,
|
|
|
|
&cultistProneDodge,
|
|
|
|
&cultistTThrow,
|
|
|
|
&cultistSThrow,
|
|
|
|
&cultistTsThrow,
|
|
|
|
&cultistDThrow,
|
|
|
|
&cultist139A78,
|
|
|
|
&cultist139A94,
|
|
|
|
&cultist139AB0,
|
|
|
|
&cultist139ACC,
|
|
|
|
&cultist139AE8,
|
|
|
|
&cultistSearch,
|
|
|
|
&cultistSFire,
|
|
|
|
&cultistTFire,
|
|
|
|
&cultistTsFire,
|
|
|
|
&cultistSProneFire,
|
|
|
|
&cultistTProneFire,
|
|
|
|
&cultistTsProneFire,
|
|
|
|
&cultistRecoil,
|
|
|
|
&cultistProneRecoil,
|
|
|
|
&cultistTeslaRecoil,
|
|
|
|
&cultistSwimIdle,
|
|
|
|
&cultistSwimChase,
|
|
|
|
&cultistSwimDodge,
|
|
|
|
&cultistSwimGoto,
|
|
|
|
&cultistSwimSearch,
|
|
|
|
&cultistSSwimFire,
|
|
|
|
&cultistTSwimFire,
|
|
|
|
&cultistTsSwimFire,
|
|
|
|
&cultistSwimRecoil,
|
|
|
|
&gargoyleFIdle,
|
|
|
|
&gargoyleStatueIdle,
|
|
|
|
&gargoyleFChase,
|
|
|
|
&gargoyleFGoto,
|
|
|
|
&gargoyleFSlash,
|
|
|
|
&gargoyleFThrow,
|
|
|
|
&gargoyleSThrow,
|
|
|
|
&gargoyleSBlast,
|
|
|
|
&gargoyleFRecoil,
|
|
|
|
&gargoyleFSearch,
|
|
|
|
&gargoyleFMorph2,
|
|
|
|
&gargoyleFMorph,
|
|
|
|
&gargoyleSMorph2,
|
|
|
|
&gargoyleSMorph,
|
|
|
|
&gargoyleSwoop,
|
|
|
|
&gargoyleFly,
|
|
|
|
&gargoyleTurn,
|
|
|
|
&gargoyleDodgeUp,
|
|
|
|
&gargoyleFDodgeUpRight,
|
|
|
|
&gargoyleFDodgeUpLeft,
|
|
|
|
&gargoyleDodgeDown,
|
|
|
|
&gargoyleFDodgeDownRight,
|
|
|
|
&gargoyleFDodgeDownLeft,
|
|
|
|
&statueFBreakSEQ,
|
|
|
|
&statueSBreakSEQ,
|
|
|
|
&ghostIdle,
|
|
|
|
&ghostChase,
|
|
|
|
&ghostGoto,
|
|
|
|
&ghostSlash,
|
|
|
|
&ghostThrow,
|
|
|
|
&ghostBlast,
|
|
|
|
&ghostRecoil,
|
|
|
|
&ghostTeslaRecoil,
|
|
|
|
&ghostSearch,
|
|
|
|
&ghostSwoop,
|
|
|
|
&ghostFly,
|
|
|
|
&ghostTurn,
|
|
|
|
&ghostDodgeUp,
|
|
|
|
&ghostDodgeUpRight,
|
|
|
|
&ghostDodgeUpLeft,
|
|
|
|
&ghostDodgeDown,
|
|
|
|
&ghostDodgeDownRight,
|
|
|
|
&ghostDodgeDownLeft,
|
|
|
|
&gillBeastIdle,
|
|
|
|
&gillBeastChase,
|
|
|
|
&gillBeastDodge,
|
|
|
|
&gillBeastGoto,
|
|
|
|
&gillBeastBite,
|
|
|
|
&gillBeastSearch,
|
|
|
|
&gillBeastRecoil,
|
|
|
|
&gillBeastSwimIdle,
|
|
|
|
&gillBeastSwimChase,
|
|
|
|
&gillBeastSwimDodge,
|
|
|
|
&gillBeastSwimGoto,
|
|
|
|
&gillBeastSwimSearch,
|
|
|
|
&gillBeastSwimBite,
|
|
|
|
&gillBeastSwimRecoil,
|
|
|
|
&gillBeast13A138,
|
|
|
|
&gillBeast13A154,
|
|
|
|
&gillBeast13A170,
|
|
|
|
&handIdle,
|
|
|
|
&hand13A3B4,
|
|
|
|
&handSearch,
|
|
|
|
&handChase,
|
|
|
|
&handRecoil,
|
|
|
|
&handGoto,
|
|
|
|
&handJump,
|
|
|
|
&houndIdle,
|
|
|
|
&houndSearch,
|
|
|
|
&houndChase,
|
|
|
|
&houndRecoil,
|
|
|
|
&houndTeslaRecoil,
|
|
|
|
&houndGoto,
|
|
|
|
&houndBite,
|
|
|
|
&houndBurn,
|
|
|
|
&innocentIdle,
|
|
|
|
&innocentSearch,
|
|
|
|
&innocentChase,
|
|
|
|
&innocentRecoil,
|
|
|
|
&innocentTeslaRecoil,
|
|
|
|
&innocentGoto,
|
|
|
|
&podIdle,
|
|
|
|
&pod13A600,
|
|
|
|
&podSearch,
|
|
|
|
&pod13A638,
|
|
|
|
&podRecoil,
|
|
|
|
&podChase,
|
|
|
|
&tentacleIdle,
|
|
|
|
&tentacle13A6A8,
|
|
|
|
&tentacle13A6C4,
|
|
|
|
&tentacle13A6E0,
|
|
|
|
&tentacle13A6FC,
|
|
|
|
&tentacle13A718,
|
|
|
|
&tentacleSearch,
|
|
|
|
&tentacle13A750,
|
|
|
|
&tentacleRecoil,
|
|
|
|
&tentacleChase,
|
|
|
|
&ratIdle,
|
|
|
|
&ratSearch,
|
|
|
|
&ratChase,
|
|
|
|
&ratDodge,
|
|
|
|
&ratRecoil,
|
|
|
|
&ratGoto,
|
|
|
|
&ratBite,
|
|
|
|
&spidIdle,
|
|
|
|
&spidChase,
|
|
|
|
&spidDodge,
|
|
|
|
&spidGoto,
|
|
|
|
&spidSearch,
|
|
|
|
&spidBite,
|
|
|
|
&spidJump,
|
|
|
|
&spid13A92C,
|
|
|
|
&tchernobogIdle,
|
|
|
|
&tchernobogSearch,
|
|
|
|
&tchernobogChase,
|
|
|
|
&tchernobogRecoil,
|
|
|
|
&tcherno13A9B8,
|
|
|
|
&tcherno13A9D4,
|
|
|
|
&tcherno13A9F0,
|
|
|
|
&tcherno13AA0C,
|
|
|
|
&tcherno13AA28,
|
|
|
|
&genDudeIdleL,
|
|
|
|
&genDudeIdleW,
|
|
|
|
&genDudeSearchL,
|
|
|
|
&genDudeSearchW,
|
|
|
|
&genDudeSearchShortL,
|
|
|
|
&genDudeSearchShortW,
|
|
|
|
&genDudeSearchNoWalkL,
|
|
|
|
&genDudeSearchNoWalkW,
|
|
|
|
&genDudeGotoL,
|
|
|
|
&genDudeGotoW,
|
|
|
|
&genDudeDodgeL,
|
|
|
|
&genDudeDodgeD,
|
|
|
|
&genDudeDodgeW,
|
|
|
|
&genDudeDodgeShortL,
|
|
|
|
&genDudeDodgeShortD,
|
|
|
|
&genDudeDodgeShortW,
|
|
|
|
&genDudeDodgeShorterL,
|
|
|
|
&genDudeDodgeShorterD,
|
|
|
|
&genDudeDodgeShorterW,
|
|
|
|
&genDudeChaseL,
|
|
|
|
&genDudeChaseD,
|
|
|
|
&genDudeChaseW,
|
|
|
|
&genDudeChaseNoWalkL,
|
|
|
|
&genDudeChaseNoWalkD,
|
|
|
|
&genDudeChaseNoWalkW,
|
|
|
|
&genDudeFireL,
|
|
|
|
&genDudeFireD,
|
|
|
|
&genDudeFireW,
|
|
|
|
&genDudeRecoilL,
|
|
|
|
&genDudeRecoilD,
|
|
|
|
&genDudeRecoilW,
|
|
|
|
&genDudeRecoilTesla,
|
|
|
|
&genDudeThrow,
|
|
|
|
&genDudeThrow2,
|
|
|
|
&genDudePunch,
|
|
|
|
&zombieAIdle,
|
|
|
|
&zombieAChase,
|
|
|
|
&zombieAPonder,
|
|
|
|
&zombieAGoto,
|
|
|
|
&zombieAHack,
|
|
|
|
&zombieASearch,
|
|
|
|
&zombieARecoil,
|
|
|
|
&zombieATeslaRecoil,
|
|
|
|
&zombieARecoil2,
|
|
|
|
&zombieAStand,
|
|
|
|
&zombieEIdle,
|
|
|
|
&zombieEUp2,
|
|
|
|
&zombieEUp,
|
|
|
|
&zombie2Idle,
|
|
|
|
&zombie2Search,
|
|
|
|
&zombieSIdle,
|
|
|
|
&zombie13AC2C,
|
|
|
|
&zombieFIdle,
|
|
|
|
&zombieFChase,
|
|
|
|
&zombieFGoto,
|
|
|
|
&zombieFDodge,
|
|
|
|
&zombieFHack,
|
|
|
|
&zombieFPuke,
|
|
|
|
&zombieFThrow,
|
|
|
|
&zombieFSearch,
|
|
|
|
&zombieFRecoil,
|
|
|
|
&zombieFTeslaRecoil,
|
|
|
|
};
|
|
|
|
|
|
|
|
void IndexAIState(AISTATE*& state)
|
|
|
|
{
|
|
|
|
int i = 0;
|
2020-02-13 23:00:35 +00:00
|
|
|
auto savestate = state;
|
2020-02-11 23:22:11 +00:00
|
|
|
for (auto cstate : allAIStates)
|
|
|
|
{
|
|
|
|
if (state == cstate)
|
|
|
|
{
|
|
|
|
state = (AISTATE*)(intptr_t)i;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
state = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnindexAIState(AISTATE*& state)
|
|
|
|
{
|
|
|
|
auto index = intptr_t(state);
|
|
|
|
if (index >= 0 && index < countof(allAIStates))
|
|
|
|
{
|
|
|
|
state = allAIStates[index];
|
|
|
|
}
|
2020-02-13 23:00:35 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
state = nullptr;
|
|
|
|
}
|
2020-02-11 23:22:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-19 22:42:45 +00:00
|
|
|
|
|
|
|
unsigned int dword_27AA38 = 0;
|
|
|
|
unsigned int dword_27AA3C = 0;
|
|
|
|
unsigned int dword_27AA40 = 0;
|
|
|
|
|
2019-11-13 17:23:45 +00:00
|
|
|
FileWriter *LoadSave::hSFile = NULL;
|
2019-10-21 15:16:08 +00:00
|
|
|
FileReader LoadSave::hLFile;
|
2019-12-24 18:47:34 +00:00
|
|
|
TDeletingArray<LoadSave*> LoadSave::loadSaves;
|
2019-09-19 22:42:45 +00:00
|
|
|
|
|
|
|
void sub_76FD4(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSave::Save(void)
|
|
|
|
{
|
|
|
|
ThrowError("Pure virtual function called");
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSave::Load(void)
|
|
|
|
{
|
|
|
|
ThrowError("Pure virtual function called");
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSave::Read(void *pData, int nSize)
|
|
|
|
{
|
|
|
|
dword_27AA38 += nSize;
|
2019-10-21 15:16:08 +00:00
|
|
|
dassert(hLFile.isOpen());
|
|
|
|
if (hLFile.Read(pData, nSize) != nSize)
|
2019-09-19 22:42:45 +00:00
|
|
|
ThrowError("Error reading save file.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSave::Write(void *pData, int nSize)
|
|
|
|
{
|
|
|
|
dword_27AA38 += nSize;
|
|
|
|
dword_27AA3C += nSize;
|
|
|
|
dassert(hSFile != NULL);
|
2019-11-13 17:23:45 +00:00
|
|
|
if (hSFile->Write(pData, nSize) != (size_t)nSize)
|
2019-09-19 22:42:45 +00:00
|
|
|
ThrowError("File error #%d writing save file.", errno);
|
|
|
|
}
|
|
|
|
|
2019-12-01 21:54:52 +00:00
|
|
|
bool GameInterface::LoadGame(FSaveGameNode* node)
|
2019-09-19 22:42:45 +00:00
|
|
|
{
|
|
|
|
bool demoWasPlayed = gDemo.at1;
|
|
|
|
if (gDemo.at1)
|
|
|
|
gDemo.Close();
|
|
|
|
|
|
|
|
sndKillAllSounds();
|
|
|
|
sfxKillAllSounds();
|
|
|
|
ambKillAll();
|
|
|
|
seqKillAll();
|
|
|
|
if (!gGameStarted)
|
|
|
|
{
|
|
|
|
memset(xsprite, 0, sizeof(xsprite));
|
|
|
|
}
|
2019-12-01 21:54:52 +00:00
|
|
|
LoadSave::hLFile = ReadSavegameChunk("snapshot.bld");
|
|
|
|
if (!LoadSave::hLFile.isOpen())
|
|
|
|
return false;
|
2019-12-24 18:47:34 +00:00
|
|
|
|
|
|
|
for (auto rover : LoadSave::loadSaves)
|
2019-09-19 22:42:45 +00:00
|
|
|
{
|
|
|
|
rover->Load();
|
|
|
|
}
|
2019-11-13 17:23:45 +00:00
|
|
|
|
2019-12-01 21:54:52 +00:00
|
|
|
LoadSave::hLFile.Close();
|
2019-11-14 20:07:43 +00:00
|
|
|
FinishSavegameRead();
|
2019-09-19 22:42:45 +00:00
|
|
|
InitSectorFX();
|
|
|
|
viewInitializePrediction();
|
|
|
|
PreloadCache();
|
2019-10-21 19:46:41 +00:00
|
|
|
if (!bVanilla && !gMe->packSlots[1].isActive) // if diving suit is not active, turn off reverb sound effect
|
2019-09-19 22:42:45 +00:00
|
|
|
sfxSetReverb(0);
|
|
|
|
ambInit();
|
|
|
|
memset(myMinLag, 0, sizeof(myMinLag));
|
|
|
|
otherMinLag = 0;
|
|
|
|
myMaxLag = 0;
|
|
|
|
gNetFifoClock = 0;
|
|
|
|
gNetFifoTail = 0;
|
|
|
|
memset(gNetFifoHead, 0, sizeof(gNetFifoHead));
|
|
|
|
gPredictTail = 0;
|
|
|
|
gNetFifoMasterTail = 0;
|
|
|
|
memset(gFifoInput, 0, sizeof(gFifoInput));
|
|
|
|
memset(gChecksum, 0, sizeof(gChecksum));
|
|
|
|
memset(gCheckFifo, 0, sizeof(gCheckFifo));
|
|
|
|
memset(gCheckHead, 0, sizeof(gCheckHead));
|
|
|
|
gSendCheckTail = 0;
|
|
|
|
gCheckTail = 0;
|
|
|
|
gBufferJitter = 0;
|
|
|
|
bOutOfSync = 0;
|
|
|
|
for (int i = 0; i < gNetPlayers; i++)
|
2019-10-21 19:46:41 +00:00
|
|
|
playerSetRace(&gPlayer[i], gPlayer[i].lifeMode);
|
2019-09-19 06:10:18 +00:00
|
|
|
if (VanillaMode())
|
|
|
|
viewSetMessage("");
|
|
|
|
else
|
|
|
|
gGameMessageMgr.Clear();
|
2019-09-19 22:42:45 +00:00
|
|
|
viewSetErrorMessage("");
|
|
|
|
if (!gGameStarted)
|
|
|
|
{
|
|
|
|
netWaitForEveryone(0);
|
|
|
|
memset(gPlayerReady, 0, sizeof(gPlayerReady));
|
|
|
|
}
|
|
|
|
gFrameTicks = 0;
|
|
|
|
gFrame = 0;
|
|
|
|
gFrameRate = 0;
|
2019-09-07 13:15:39 +00:00
|
|
|
totalclock = 0;
|
2020-05-29 01:20:40 +00:00
|
|
|
paused = 0;
|
2019-09-19 22:42:45 +00:00
|
|
|
gGameStarted = 1;
|
|
|
|
bVanilla = false;
|
2020-01-02 13:37:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
Polymost_prepare_loadboard();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef POLYMER
|
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
|
|
|
polymer_loadboard();
|
|
|
|
|
|
|
|
// this light pointer nulling needs to be outside the videoGetRenderMode check
|
|
|
|
// because we might be loading the savegame using another renderer but
|
|
|
|
// change to Polymer later
|
|
|
|
for (int i=0; i<kMaxSprites; i++)
|
|
|
|
{
|
|
|
|
gPolymerLight[i].lightptr = NULL;
|
|
|
|
gPolymerLight[i].lightId = -1;
|
|
|
|
}
|
|
|
|
#endif
|
2019-09-19 22:42:45 +00:00
|
|
|
|
2019-12-26 12:04:29 +00:00
|
|
|
Mus_ResumeSaved();
|
2019-09-19 22:42:45 +00:00
|
|
|
|
|
|
|
netBroadcastPlayerInfo(myconnectindex);
|
2019-12-01 21:54:52 +00:00
|
|
|
return true;
|
2019-09-19 22:42:45 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 21:54:52 +00:00
|
|
|
bool GameInterface::SaveGame(FSaveGameNode* node)
|
2019-09-19 22:42:45 +00:00
|
|
|
{
|
2019-12-01 21:54:52 +00:00
|
|
|
LoadSave::hSFile = WriteSavegameChunk("snapshot.bld");
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
dword_27AA38 = 0;
|
|
|
|
dword_27AA40 = 0;
|
2019-12-24 18:47:34 +00:00
|
|
|
for (auto rover : LoadSave::loadSaves)
|
2019-12-01 21:54:52 +00:00
|
|
|
{
|
|
|
|
rover->Save();
|
|
|
|
if (dword_27AA38 > dword_27AA40)
|
|
|
|
dword_27AA40 = dword_27AA38;
|
|
|
|
dword_27AA38 = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-04-11 21:50:43 +00:00
|
|
|
catch (CRecoverableError & err)
|
2019-12-01 21:54:52 +00:00
|
|
|
{
|
|
|
|
// Let's not abort for write errors.
|
|
|
|
Printf(TEXTCOLOR_RED "%s\n", err.what());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
LoadSave::hSFile = NULL;
|
2019-11-26 23:41:26 +00:00
|
|
|
|
2019-12-01 21:54:52 +00:00
|
|
|
return FinishSavegameWrite();
|
2019-09-19 22:42:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class MyLoadSave : public LoadSave
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void Load(void);
|
|
|
|
virtual void Save(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
void MyLoadSave::Load(void)
|
|
|
|
{
|
2020-07-14 22:06:19 +00:00
|
|
|
psky_t *pSky = tileSetupSky(DEFAULTPSKY);
|
2019-09-19 22:42:45 +00:00
|
|
|
int id;
|
|
|
|
Read(&id, sizeof(id));
|
|
|
|
if (id != 0x5653424e/*'VSBN'*/)
|
|
|
|
ThrowError("Old saved game found");
|
|
|
|
short version;
|
|
|
|
Read(&version, sizeof(version));
|
|
|
|
if (version != BYTEVERSION)
|
|
|
|
ThrowError("Incompatible version of saved game found!");
|
|
|
|
Read(&gGameOptions, sizeof(gGameOptions));
|
2020-01-21 20:51:05 +00:00
|
|
|
|
2019-09-19 22:42:45 +00:00
|
|
|
int nNumSprites;
|
|
|
|
Read(&nNumSprites, sizeof(nNumSprites));
|
|
|
|
Read(qsector_filler, sizeof(qsector_filler[0])*numsectors);
|
|
|
|
Read(qsprite_filler, sizeof(qsprite_filler[0])*kMaxSprites);
|
|
|
|
Read(&pSky->horizfrac, sizeof(pSky->horizfrac));
|
|
|
|
Read(&pSky->yoffs, sizeof(pSky->yoffs));
|
|
|
|
Read(&pSky->yscale, sizeof(pSky->yscale));
|
|
|
|
Read(&gVisibility, sizeof(gVisibility));
|
|
|
|
Read(pSky->tileofs, sizeof(pSky->tileofs));
|
|
|
|
Read(&pSky->lognumtiles, sizeof(pSky->lognumtiles));
|
|
|
|
Read(gotpic, sizeof(gotpic));
|
|
|
|
Read(gotsector, sizeof(gotsector));
|
|
|
|
Read(&gFrameClock, sizeof(gFrameClock));
|
|
|
|
Read(&gFrameTicks, sizeof(gFrameTicks));
|
|
|
|
Read(&gFrame, sizeof(gFrame));
|
2019-09-07 13:15:39 +00:00
|
|
|
Read(&totalclock, sizeof(totalclock));
|
2019-09-19 22:42:45 +00:00
|
|
|
Read(&gLevelTime, sizeof(gLevelTime));
|
2020-05-29 01:20:40 +00:00
|
|
|
Read(&paused, sizeof(paused));
|
2019-09-19 22:42:45 +00:00
|
|
|
Read(baseWall, sizeof(baseWall[0])*numwalls);
|
|
|
|
Read(baseSprite, sizeof(baseSprite[0])*nNumSprites);
|
|
|
|
Read(baseFloor, sizeof(baseFloor[0])*numsectors);
|
|
|
|
Read(baseCeil, sizeof(baseCeil[0])*numsectors);
|
|
|
|
Read(velFloor, sizeof(velFloor[0])*numsectors);
|
|
|
|
Read(velCeil, sizeof(velCeil[0])*numsectors);
|
|
|
|
Read(&gHitInfo, sizeof(gHitInfo));
|
|
|
|
Read(&byte_1A76C6, sizeof(byte_1A76C6));
|
|
|
|
Read(&byte_1A76C8, sizeof(byte_1A76C8));
|
|
|
|
Read(&byte_1A76C7, sizeof(byte_1A76C7));
|
|
|
|
Read(&byte_19AE44, sizeof(byte_19AE44));
|
|
|
|
Read(gStatCount, sizeof(gStatCount));
|
|
|
|
Read(nextXSprite, sizeof(nextXSprite));
|
|
|
|
Read(nextXWall, sizeof(nextXWall));
|
|
|
|
Read(nextXSector, sizeof(nextXSector));
|
|
|
|
memset(xsprite, 0, sizeof(xsprite));
|
|
|
|
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
|
|
|
{
|
|
|
|
if (sprite[nSprite].statnum < kMaxStatus)
|
|
|
|
{
|
|
|
|
int nXSprite = sprite[nSprite].extra;
|
|
|
|
if (nXSprite > 0)
|
2020-02-11 23:22:11 +00:00
|
|
|
{
|
2019-09-19 22:42:45 +00:00
|
|
|
Read(&xsprite[nXSprite], sizeof(XSPRITE));
|
2020-02-11 23:22:11 +00:00
|
|
|
UnindexAIState(xsprite[nXSprite].aiState);
|
|
|
|
}
|
2019-09-19 22:42:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
memset(xwall, 0, sizeof(xwall));
|
|
|
|
for (int nWall = 0; nWall < numwalls; nWall++)
|
|
|
|
{
|
|
|
|
int nXWall = wall[nWall].extra;
|
|
|
|
if (nXWall > 0)
|
|
|
|
Read(&xwall[nXWall], sizeof(XWALL));
|
|
|
|
}
|
|
|
|
memset(xsector, 0, sizeof(xsector));
|
|
|
|
for (int nSector = 0; nSector < numsectors; nSector++)
|
|
|
|
{
|
|
|
|
int nXSector = sector[nSector].extra;
|
|
|
|
if (nXSector > 0)
|
|
|
|
Read(&xsector[nXSector], sizeof(XSECTOR));
|
|
|
|
}
|
|
|
|
Read(xvel, nNumSprites*sizeof(xvel[0]));
|
|
|
|
Read(yvel, nNumSprites*sizeof(yvel[0]));
|
|
|
|
Read(zvel, nNumSprites*sizeof(zvel[0]));
|
|
|
|
Read(&gMapRev, sizeof(gMapRev));
|
|
|
|
Read(&gSongId, sizeof(gSkyCount));
|
|
|
|
Read(&gFogMode, sizeof(gFogMode));
|
2020-01-26 11:19:01 +00:00
|
|
|
#ifdef NOONE_EXTENSIONS
|
2019-11-08 19:57:01 +00:00
|
|
|
Read(&gModernMap, sizeof(gModernMap));
|
2020-01-26 11:19:01 +00:00
|
|
|
#endif
|
2020-07-14 22:06:19 +00:00
|
|
|
psky_t *skyInfo = tileSetupSky(DEFAULTPSKY);
|
|
|
|
Read(skyInfo, sizeof(*skyInfo));
|
|
|
|
skyInfo->combinedtile = -1;
|
2019-09-19 22:42:45 +00:00
|
|
|
gCheatMgr.sub_5BCF4();
|
2019-09-21 11:02:17 +00:00
|
|
|
|
2019-09-19 22:42:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyLoadSave::Save(void)
|
|
|
|
{
|
|
|
|
psky_t *pSky = tileSetupSky(0);
|
|
|
|
int nNumSprites = 0;
|
|
|
|
int id = 0x5653424e/*'VSBN'*/;
|
|
|
|
Write(&id, sizeof(id));
|
|
|
|
short version = BYTEVERSION;
|
|
|
|
Write(&version, sizeof(version));
|
|
|
|
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
|
|
|
{
|
|
|
|
if (sprite[nSprite].statnum < kMaxStatus && nSprite > nNumSprites)
|
|
|
|
nNumSprites = nSprite;
|
|
|
|
}
|
|
|
|
//nNumSprites += 2;
|
|
|
|
nNumSprites++;
|
|
|
|
Write(&gGameOptions, sizeof(gGameOptions));
|
|
|
|
Write(&nNumSprites, sizeof(nNumSprites));
|
|
|
|
Write(qsector_filler, sizeof(qsector_filler[0])*numsectors);
|
|
|
|
Write(qsprite_filler, sizeof(qsprite_filler[0])*kMaxSprites);
|
|
|
|
Write(&pSky->horizfrac, sizeof(pSky->horizfrac));
|
|
|
|
Write(&pSky->yoffs, sizeof(pSky->yoffs));
|
|
|
|
Write(&pSky->yscale, sizeof(pSky->yscale));
|
|
|
|
Write(&gVisibility, sizeof(gVisibility));
|
|
|
|
Write(pSky->tileofs, sizeof(pSky->tileofs));
|
|
|
|
Write(&pSky->lognumtiles, sizeof(pSky->lognumtiles));
|
|
|
|
Write(gotpic, sizeof(gotpic));
|
|
|
|
Write(gotsector, sizeof(gotsector));
|
|
|
|
Write(&gFrameClock, sizeof(gFrameClock));
|
|
|
|
Write(&gFrameTicks, sizeof(gFrameTicks));
|
|
|
|
Write(&gFrame, sizeof(gFrame));
|
2019-09-07 13:15:39 +00:00
|
|
|
ClockTicks nGameClock = totalclock;
|
2019-09-19 22:42:45 +00:00
|
|
|
Write(&nGameClock, sizeof(nGameClock));
|
|
|
|
Write(&gLevelTime, sizeof(gLevelTime));
|
2020-05-29 01:20:40 +00:00
|
|
|
Write(&paused, sizeof(paused));
|
2019-09-19 22:42:45 +00:00
|
|
|
Write(baseWall, sizeof(baseWall[0])*numwalls);
|
|
|
|
Write(baseSprite, sizeof(baseSprite[0])*nNumSprites);
|
|
|
|
Write(baseFloor, sizeof(baseFloor[0])*numsectors);
|
|
|
|
Write(baseCeil, sizeof(baseCeil[0])*numsectors);
|
|
|
|
Write(velFloor, sizeof(velFloor[0])*numsectors);
|
|
|
|
Write(velCeil, sizeof(velCeil[0])*numsectors);
|
|
|
|
Write(&gHitInfo, sizeof(gHitInfo));
|
|
|
|
Write(&byte_1A76C6, sizeof(byte_1A76C6));
|
|
|
|
Write(&byte_1A76C8, sizeof(byte_1A76C8));
|
|
|
|
Write(&byte_1A76C7, sizeof(byte_1A76C7));
|
|
|
|
Write(&byte_19AE44, sizeof(byte_19AE44));
|
|
|
|
Write(gStatCount, sizeof(gStatCount));
|
|
|
|
Write(nextXSprite, sizeof(nextXSprite));
|
|
|
|
Write(nextXWall, sizeof(nextXWall));
|
|
|
|
Write(nextXSector, sizeof(nextXSector));
|
|
|
|
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
|
|
|
{
|
|
|
|
if (sprite[nSprite].statnum < kMaxStatus)
|
|
|
|
{
|
|
|
|
int nXSprite = sprite[nSprite].extra;
|
|
|
|
if (nXSprite > 0)
|
2020-02-11 23:22:11 +00:00
|
|
|
{
|
|
|
|
IndexAIState(xsprite[nXSprite].aiState);
|
2019-09-19 22:42:45 +00:00
|
|
|
Write(&xsprite[nXSprite], sizeof(XSPRITE));
|
2020-02-11 23:22:11 +00:00
|
|
|
UnindexAIState(xsprite[nXSprite].aiState);
|
|
|
|
}
|
2019-09-19 22:42:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int nWall = 0; nWall < numwalls; nWall++)
|
|
|
|
{
|
|
|
|
int nXWall = wall[nWall].extra;
|
|
|
|
if (nXWall > 0)
|
|
|
|
Write(&xwall[nXWall], sizeof(XWALL));
|
|
|
|
}
|
|
|
|
for (int nSector = 0; nSector < numsectors; nSector++)
|
|
|
|
{
|
|
|
|
int nXSector = sector[nSector].extra;
|
|
|
|
if (nXSector > 0)
|
|
|
|
Write(&xsector[nXSector], sizeof(XSECTOR));
|
|
|
|
}
|
|
|
|
Write(xvel, nNumSprites*sizeof(xvel[0]));
|
|
|
|
Write(yvel, nNumSprites*sizeof(yvel[0]));
|
|
|
|
Write(zvel, nNumSprites*sizeof(zvel[0]));
|
|
|
|
Write(&gMapRev, sizeof(gMapRev));
|
|
|
|
Write(&gSongId, sizeof(gSkyCount));
|
|
|
|
Write(&gFogMode, sizeof(gFogMode));
|
2020-01-26 11:19:01 +00:00
|
|
|
#ifdef NOONE_EXTENSIONS
|
2019-11-08 19:57:01 +00:00
|
|
|
Write(&gModernMap, sizeof(gModernMap));
|
2020-01-26 11:19:01 +00:00
|
|
|
#endif
|
2020-07-14 22:06:19 +00:00
|
|
|
psky_t *skyInfo = tileSetupSky(DEFAULTPSKY);
|
|
|
|
Write(skyInfo, sizeof(*skyInfo));
|
2019-09-19 22:42:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSavedInfo(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateSavedInfo(int nSlot)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static MyLoadSave *myLoadSave;
|
|
|
|
|
|
|
|
|
2019-09-22 06:39:22 +00:00
|
|
|
void ActorLoadSaveConstruct(void);
|
|
|
|
void AILoadSaveConstruct(void);
|
|
|
|
void EndGameLoadSaveConstruct(void);
|
|
|
|
void EventQLoadSaveConstruct(void);
|
|
|
|
void LevelsLoadSaveConstruct(void);
|
|
|
|
void MessagesLoadSaveConstruct(void);
|
|
|
|
void MirrorLoadSaveConstruct(void);
|
|
|
|
void PlayerLoadSaveConstruct(void);
|
|
|
|
void SeqLoadSaveConstruct(void);
|
|
|
|
void TriggersLoadSaveConstruct(void);
|
|
|
|
void ViewLoadSaveConstruct(void);
|
|
|
|
void WarpLoadSaveConstruct(void);
|
|
|
|
void WeaponLoadSaveConstruct(void);
|
2020-02-16 13:54:24 +00:00
|
|
|
#ifdef NOONE_EXTENSIONS
|
2020-02-11 22:15:25 +00:00
|
|
|
void NNLoadSaveConstruct(void);
|
2020-02-16 13:54:24 +00:00
|
|
|
#endif
|
2019-09-22 06:39:22 +00:00
|
|
|
|
2019-09-19 22:42:45 +00:00
|
|
|
void LoadSaveSetup(void)
|
|
|
|
{
|
|
|
|
myLoadSave = new MyLoadSave();
|
|
|
|
|
|
|
|
ActorLoadSaveConstruct();
|
|
|
|
AILoadSaveConstruct();
|
|
|
|
EndGameLoadSaveConstruct();
|
|
|
|
EventQLoadSaveConstruct();
|
|
|
|
LevelsLoadSaveConstruct();
|
|
|
|
MessagesLoadSaveConstruct();
|
|
|
|
MirrorLoadSaveConstruct();
|
|
|
|
PlayerLoadSaveConstruct();
|
|
|
|
SeqLoadSaveConstruct();
|
|
|
|
TriggersLoadSaveConstruct();
|
|
|
|
ViewLoadSaveConstruct();
|
|
|
|
WarpLoadSaveConstruct();
|
|
|
|
WeaponLoadSaveConstruct();
|
2020-02-16 13:54:24 +00:00
|
|
|
#ifdef NOONE_EXTENSIONS
|
2020-02-11 22:15:25 +00:00
|
|
|
NNLoadSaveConstruct();
|
2020-02-16 13:54:24 +00:00
|
|
|
#endif
|
2019-09-22 06:39:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
END_BLD_NS
|