diff --git a/client/Client.cpp b/client/Client.cpp index 13b6bf265..ab73d621e 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -334,13 +334,14 @@ void CClient::newGame( CConnection *con, StartInfo *si ) ui32 seed, sum; - c >> si >> sum >> seed; + si32 seedPostInit; + c >> si >> sum >> seed >> seedPostInit; tlog0 <<"\tSending/Getting info to/from the server: "<(CGI)->state; gs->scenarioOps = si; - gs->init(si, sum, seed); + gs->init(si, sum, seed, seedPostInit); tlog0 <<"Initializing GameState (together): "<map) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 1038e2710..a629678c4 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -23,7 +23,7 @@ #include "../lib/JsonNode.h" #include "GameConstants.h" -boost::rand48 ran; +DLL_LINKAGE boost::rand48 ran; class CGObjectInstance; #ifdef min @@ -813,7 +813,7 @@ BattleInfo * CGameState::setupBattle(int3 tile, const CArmedInstance *armies[2], return BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town); } -void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) +void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostInitSeed /*= -1*/) { struct HLP { @@ -1570,6 +1570,12 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) map->checkForObjectives(); //needs to be run when all objects are properly placed + + if(expectedPostInitSeed >= 0) + { + int actualSeed = ran(); + assert(expectedPostInitSeed == actualSeed); //RNG must be in the same state on all machines when initialization is done (otherwise we have desync) + } } int CGameState::battleGetBattlefieldType(int3 tile) diff --git a/lib/CGameState.h b/lib/CGameState.h index 1cf7c3cec..5963e47bc 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -373,7 +373,7 @@ public: boost::shared_mutex *mx; - void init(StartInfo * si, ui32 checksum, int Seed); + void init(StartInfo * si, ui32 checksum, int Seed, int expectedPostInitSeed = -1); void loadTownDInfos(); void randomizeObject(CGObjectInstance *cur); std::pair pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 2940baae1..44b4b08dc 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1031,6 +1031,13 @@ DLL_LINKAGE void StartAction::applyGs( CGameState *gs ) return; } + if(gs->curB->tacticDistance) + { + // moves in tactics phase do not affect creature status + // (tactics stack queue is managed by client) + return; + } + if(ba.actionType != BattleAction::HERO_SPELL) //don't check for stack if it's custom action by hero { assert(st); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 2177d06e8..7adf33db1 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -21,9 +21,6 @@ #include "../lib/VCMIDirs.h" #include "../client/CSoundBase.h" #include "CGameHandler.h" -#include -#include -#include #include "../lib/CCreatureSet.h" #include "../lib/CThreadHelper.h" #include "../lib/GameConstants.h" @@ -43,6 +40,7 @@ #ifndef _MSC_VER #include #endif +#include extern bool end2; #ifdef min #undef min @@ -60,9 +58,6 @@ extern bool end2; CondSh battleMadeAction; CondSh battleResult(NULL); -std::ptrdiff_t randomizer (ptrdiff_t i) {return rand() % i;} -std::ptrdiff_t (*p_myrandom)(std::ptrdiff_t) = randomizer; - template class CApplyOnGH; class CBaseForGHApply @@ -799,6 +794,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest) CGameHandler::CGameHandler(void) { + seedInitial = seedPostInit = -1; QID = 1; //gs = NULL; IObjectInterface::cb = this; @@ -815,11 +811,16 @@ CGameHandler::~CGameHandler(void) delete gs; } -void CGameHandler::init(StartInfo *si, int Seed) +void CGameHandler::init(StartInfo *si) { + extern DLL_LINKAGE boost::rand48 ran; + if(seedInitial < 0) + seedInitial = std::time(NULL); + gs = new CGameState(); tlog0 << "Gamestate created!" << std::endl; - gs->init(si, 0, Seed); + gs->init(si, 0, seedInitial); + seedPostInit = ran(); tlog0 << "Gamestate initialized!" << std::endl; for(std::map::iterator i = gs->players.begin(); i != gs->players.end(); i++) @@ -1207,7 +1208,7 @@ void CGameHandler::run(bool resume) if(!resume) { ui32 sum = gs->map ? gs->map->checksum : 612; - (*cc) << gs->initialOpts << sum << gs->seed; // gs->scenarioOps + (*cc) << gs->initialOpts << sum << gs->seed << seedPostInit; // gs->scenarioOps } (*cc) >> quantity; //how many players will be handled at that client @@ -5619,7 +5620,7 @@ void CGameHandler::spawnWanderingMonsters(int creatureID) std::vector tiles; getFreeTiles(tiles); ui32 amount = tiles.size() / 200; //Chance is 0.5% for each tile - std::random_shuffle(tiles.begin(), tiles.end(), p_myrandom); + std::random_shuffle(tiles.begin(), tiles.end()); tlog5 << "Spawning wandering monsters. Found " << tiles.size() << " free tiles. Creature type: " << creatureID << std::endl; const CCreature *cre = VLC->creh->creatures[creatureID]; for (int i = 0; i < amount; ++i) diff --git a/server/CGameHandler.h b/server/CGameHandler.h index d65497292..6cb15090d 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -91,6 +91,8 @@ public: PlayerStatuses states; //player color -> player state std::set conns; + si32 seedInitial, seedPostInit; + //queries stuff boost::recursive_mutex gsm; ui32 QID; @@ -187,7 +189,7 @@ public: void commitPackage(CPackForClient *pack) OVERRIDE; - void init(StartInfo *si, int Seed); + void init(StartInfo *si); void handleConnection(std::set players, CConnection &c); int getPlayerAt(CConnection *c) const; diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index daff0eab8..acf96324b 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -1,14 +1,5 @@ #include "StdInc.h" -#include //no i/o just types -#include -#include -#include -#include -#include - - - #include "../lib/CCampaignHandler.h" #include "../lib/CThreadHelper.h" #include "../lib/Connection.h" @@ -32,7 +23,6 @@ #include "../lib/CObjectHandler.h" #include "../lib/GameConstants.h" -#include #include "../lib/UnlockGuard.h" std::string NAME_AFFIX = "server"; @@ -345,7 +335,7 @@ CGameHandler * CVCMIServer::initGhFromHostingConnection(CConnection &c) c << ui8(0); //OK! } - gh->init(&si,std::time(NULL)); + gh->init(&si); c.addStdVecItems(gh->gs); gh->conns.insert(&c); @@ -378,7 +368,7 @@ void CVCMIServer::newPregame() { CGameHandler gh; gh.conns = cps->connections; - gh.init(cps->curStartInfo,std::clock()); + gh.init(cps->curStartInfo); BOOST_FOREACH(CConnection *c, gh.conns) c->addStdVecItems(gh.gs); diff --git a/server/StdInc.h b/server/StdInc.h index 76e828312..9d8032c99 100644 --- a/server/StdInc.h +++ b/server/StdInc.h @@ -2,6 +2,13 @@ #include "../Global.h" -// This header should be treated as a pre compiled header file(PCH) in the compiler building settings. - -// Here you can add specific libraries and macros which are specific to this project. \ No newline at end of file +#include +#include //no i/o just types +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/server/VCMI_server.vcxproj b/server/VCMI_server.vcxproj index c87f13e49..aad8f5ef5 100644 --- a/server/VCMI_server.vcxproj +++ b/server/VCMI_server.vcxproj @@ -94,7 +94,7 @@ - /MP4 %(AdditionalOptions) + /MP4 %(AdditionalOptions)/Zm200 Disabled %(AdditionalIncludeDirectories) false @@ -115,7 +115,7 @@ - /MP4 %(AdditionalOptions) + /MP4 %(AdditionalOptions)/Zm200 Disabled %(AdditionalIncludeDirectories) false @@ -135,7 +135,7 @@ - /Oy- %(AdditionalOptions) + /Oy- %(AdditionalOptions)/Zm200 MaxSpeed true Speed @@ -166,7 +166,7 @@ - /Oy- %(AdditionalOptions) + /Oy- %(AdditionalOptions)/Zm200 MaxSpeed true Speed