mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-15 00:05:02 +02:00
Significant changes to saving system. Now both client and server store their lib part.
Desync detection upon loading. Fixed many desyncs. (more remain) Monsters won't have creature count 0 even if that is set as creature properties.
This commit is contained in:
@ -246,7 +246,7 @@ void CCallback::setSelection(const CArmedInstance * obj)
|
|||||||
cl->calculatePaths(static_cast<const CGHeroInstance *>(obj));
|
cl->calculatePaths(static_cast<const CGHeroInstance *>(obj));
|
||||||
|
|
||||||
//nasty workaround. TODO: nice workaround
|
//nasty workaround. TODO: nice workaround
|
||||||
cl->gs->getPlayer(*player)->currentSelection = obj->id;
|
//cl->gs->getPlayer(*player)->currentSelection = obj->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,7 +905,7 @@ void CSelectionScreen::startScenario()
|
|||||||
overWrite += boost::bind(&CCallback::save, LOCPLINT->cb, saveGameName);
|
overWrite += boost::bind(&CCallback::save, LOCPLINT->cb, saveGameName);
|
||||||
overWrite += bind(&CGuiHandler::popIntTotally, &GH, this);
|
overWrite += bind(&CGuiHandler::popIntTotally, &GH, this);
|
||||||
|
|
||||||
if(CResourceHandler::get()->existsResource(ResourceID(saveGameName, EResType::LIB_SAVEGAME)))
|
if(CResourceHandler::get()->existsResource(ResourceID(saveGameName, EResType::CLIENT_SAVEGAME)))
|
||||||
{
|
{
|
||||||
std::string hlp = CGI->generaltexth->allTexts[493]; //%s exists. Overwrite?
|
std::string hlp = CGI->generaltexth->allTexts[493]; //%s exists. Overwrite?
|
||||||
boost::algorithm::replace_first(hlp, "%s", sel->txt->text);
|
boost::algorithm::replace_first(hlp, "%s", sel->txt->text);
|
||||||
@ -1124,13 +1124,13 @@ void SelectionTab::parseGames(const std::vector<ResourceID> &files, bool multi)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
CLoadFile lf(CResourceHandler::get()->getResourceName(files[i]));
|
CLoadFile lf(CResourceHandler::get()->getResourceName(files[i]));
|
||||||
|
lf.checkMagicBytes(SAVEGAME_MAGIC);
|
||||||
ui8 sign[8];
|
// ui8 sign[8];
|
||||||
lf >> sign;
|
// lf >> sign;
|
||||||
if(std::memcmp(sign,"VCMISVG",7))
|
// if(std::memcmp(sign,"VCMISVG",7))
|
||||||
{
|
// {
|
||||||
throw std::runtime_error("not a correct savefile!");
|
// throw std::runtime_error("not a correct savefile!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Create the map info object
|
// Create the map info object
|
||||||
CMapInfo mapInfo;
|
CMapInfo mapInfo;
|
||||||
@ -1207,7 +1207,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
|
|||||||
|
|
||||||
case CMenuScreen::loadGame:
|
case CMenuScreen::loadGame:
|
||||||
case CMenuScreen::saveGame:
|
case CMenuScreen::saveGame:
|
||||||
parseGames(getFiles("Saves/", EResType::LIB_SAVEGAME), MultiPlayer);
|
parseGames(getFiles("Saves/", EResType::CLIENT_SAVEGAME), MultiPlayer);
|
||||||
if(tabType == CMenuScreen::loadGame)
|
if(tabType == CMenuScreen::loadGame)
|
||||||
{
|
{
|
||||||
positions = 18;
|
positions = 18;
|
||||||
@ -1343,7 +1343,7 @@ void SelectionTab::select( int position )
|
|||||||
if(txt)
|
if(txt)
|
||||||
{
|
{
|
||||||
std::string filename = CResourceHandler::get()->getResourceName(
|
std::string filename = CResourceHandler::get()->getResourceName(
|
||||||
ResourceID(curItems[py]->fileURI, EResType::LIB_SAVEGAME));
|
ResourceID(curItems[py]->fileURI, EResType::CLIENT_SAVEGAME));
|
||||||
txt->setTxt(CFileInfo(filename).getBaseName());
|
txt->setTxt(CFileInfo(filename).getBaseName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1476,7 +1476,7 @@ void SelectionTab::printMaps(SDL_Surface *to)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
name = CFileInfo(CResourceHandler::get()->getResourceName(
|
name = CFileInfo(CResourceHandler::get()->getResourceName(
|
||||||
ResourceID(currentItem->fileURI, EResType::LIB_SAVEGAME))).getBaseName();
|
ResourceID(currentItem->fileURI, EResType::CLIENT_SAVEGAME))).getBaseName();
|
||||||
}
|
}
|
||||||
|
|
||||||
//print name
|
//print name
|
||||||
|
@ -232,29 +232,27 @@ void CClient::loadGame( const std::string & fname )
|
|||||||
|
|
||||||
CStopWatch tmh;
|
CStopWatch tmh;
|
||||||
{
|
{
|
||||||
char sig[8];
|
auto clientSaveName = CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
|
||||||
CMapHeader dum;
|
auto controlServerSaveName = CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME));
|
||||||
const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
|
|
||||||
StartInfo *si;
|
|
||||||
|
|
||||||
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::LIB_SAVEGAME)));
|
|
||||||
lf >> sig >> dum >> si;
|
|
||||||
tlog0 <<"Reading save signature: "<<tmh.getDiff()<<std::endl;
|
|
||||||
|
|
||||||
lf >> *VLC;
|
|
||||||
const_cast<CGameInfo*>(CGI)->setFromLib();
|
|
||||||
tlog0 <<"Reading handlers: "<<tmh.getDiff()<<std::endl;
|
|
||||||
|
|
||||||
lf >> gs;
|
|
||||||
tlog0 <<"Reading gamestate: "<<tmh.getDiff()<<std::endl;
|
|
||||||
|
|
||||||
|
unique_ptr<CLoadFile> loader;
|
||||||
|
{
|
||||||
|
CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName);
|
||||||
|
loadCommonState(checkingLoader);
|
||||||
|
loader = checkingLoader.decay();
|
||||||
|
}
|
||||||
|
tlog0 << "Loaded common part of save " << tmh.getDiff()<<std::endl;
|
||||||
const_cast<CGameInfo*>(CGI)->state = gs;
|
const_cast<CGameInfo*>(CGI)->state = gs;
|
||||||
|
const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
|
||||||
const_cast<CGameInfo*>(CGI)->mh->map = gs->map;
|
const_cast<CGameInfo*>(CGI)->mh->map = gs->map;
|
||||||
pathInfo = new CPathsInfo(int3(gs->map->width, gs->map->height, gs->map->twoLevel ? 2 : 1));
|
pathInfo = new CPathsInfo(int3(gs->map->width, gs->map->height, gs->map->twoLevel ? 2 : 1));
|
||||||
CGI->mh->init();
|
CGI->mh->init();
|
||||||
|
|
||||||
tlog0 <<"Initing maphandler: "<<tmh.getDiff()<<std::endl;
|
tlog0 <<"Initing maphandler: "<<tmh.getDiff()<<std::endl;
|
||||||
|
|
||||||
|
*loader >> *this;
|
||||||
|
tlog0 << "Loaded client part of save " << tmh.getDiff()<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
serv = sh.connectToServer();
|
serv = sh.connectToServer();
|
||||||
serv->addStdVecItems(gs);
|
serv->addStdVecItems(gs);
|
||||||
|
|
||||||
@ -280,10 +278,6 @@ void CClient::loadGame( const std::string & fname )
|
|||||||
serv->enableStackSendingByID();
|
serv->enableStackSendingByID();
|
||||||
serv->disableSmartPointerSerialization();
|
serv->disableSmartPointerSerialization();
|
||||||
|
|
||||||
{
|
|
||||||
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME)));
|
|
||||||
lf >> *this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::newGame( CConnection *con, StartInfo *si )
|
void CClient::newGame( CConnection *con, StartInfo *si )
|
||||||
|
@ -191,6 +191,7 @@ public:
|
|||||||
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE {};
|
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE {};
|
||||||
void removeArtifact(const ArtifactLocation &al) OVERRIDE {};
|
void removeArtifact(const ArtifactLocation &al) OVERRIDE {};
|
||||||
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE {return false;};
|
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE {return false;};
|
||||||
|
void synchronizeArtifactHandlerLists() OVERRIDE {};
|
||||||
|
|
||||||
void showCompInfo(ShowInInfobox * comp) OVERRIDE {};
|
void showCompInfo(ShowInInfobox * comp) OVERRIDE {};
|
||||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE {};
|
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE {};
|
||||||
|
@ -781,12 +781,32 @@ void SaveGame::applyCl(CClient *cl)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
CSaveFile save(CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::CLIENT_SAVEGAME)));
|
CSaveFile save(CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::CLIENT_SAVEGAME)));
|
||||||
|
cl->saveCommonState(save);
|
||||||
save << *cl;
|
save << *cl;
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
tlog1 << "Failed to save game:" << e.what() << std::endl;
|
tlog1 << "Failed to save game:" << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// auto clientPart = CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::CLIENT_SAVEGAME));
|
||||||
|
// auto libPart = CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::LIB_SAVEGAME));
|
||||||
|
// CLoadIntegrityValidator checker(clientPart, libPart);
|
||||||
|
//
|
||||||
|
// CMapHeader mh;
|
||||||
|
// StartInfo *si;
|
||||||
|
// LibClasses *lib;
|
||||||
|
// CGameState *game;
|
||||||
|
//
|
||||||
|
// checker.checkMagicBytes(SAVEGAME_MAGIC);
|
||||||
|
// checker >> mh >> si >> lib >> game;
|
||||||
|
// }
|
||||||
|
// catch(...)
|
||||||
|
// {
|
||||||
|
// tlog1 << "Desync!!!\n";
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMessage::applyCl(CClient *cl)
|
void PlayerMessage::applyCl(CClient *cl)
|
||||||
|
@ -646,7 +646,7 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
|
|||||||
else //blit normal object
|
else //blit normal object
|
||||||
{
|
{
|
||||||
const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
|
const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
|
||||||
SDL_Surface *bitmap = ourImages[(anim+obj->animPhaseShift)%ourImages.size()].bitmap;
|
SDL_Surface *bitmap = ourImages[(anim+getPhaseShift(obj))%ourImages.size()].bitmap;
|
||||||
|
|
||||||
//setting appropriate flag color
|
//setting appropriate flag color
|
||||||
if(color < 8 || color==255)
|
if(color < 8 || color==255)
|
||||||
@ -1101,6 +1101,19 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
|
|||||||
out = CGI->generaltexth->terrainNames[t.terType];
|
out = CGI->generaltexth->terrainNames[t.terType];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui8 CMapHandler::getPhaseShift(const CGObjectInstance *object) const
|
||||||
|
{
|
||||||
|
auto i = animationPhase.find(object);
|
||||||
|
if(i == animationPhase.end())
|
||||||
|
{
|
||||||
|
ui8 ret = rand() % 255;
|
||||||
|
animationPhase[object] = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
TerrainTile2::TerrainTile2()
|
TerrainTile2::TerrainTile2()
|
||||||
:terbitmap(0)
|
:terbitmap(0)
|
||||||
{}
|
{}
|
||||||
|
@ -99,6 +99,8 @@ public:
|
|||||||
|
|
||||||
std::vector<std::vector<std::vector<ui8> > > hideBitmap; //specifies number of graphic that should be used to fully hide a tile
|
std::vector<std::vector<std::vector<ui8> > > hideBitmap; //specifies number of graphic that should be used to fully hide a tile
|
||||||
|
|
||||||
|
mutable std::map<const CGObjectInstance*, ui8> animationPhase;
|
||||||
|
|
||||||
static const bool MARK_BLOCKED_POSITIONS;
|
static const bool MARK_BLOCKED_POSITIONS;
|
||||||
static const bool MARK_VISITABLE_POSITIONS;
|
static const bool MARK_VISITABLE_POSITIONS;
|
||||||
|
|
||||||
@ -106,6 +108,7 @@ public:
|
|||||||
~CMapHandler(); //d-tor
|
~CMapHandler(); //d-tor
|
||||||
|
|
||||||
std::pair<SDL_Surface *, bool> getVisBitmap(const int3 & pos, const std::vector< std::vector< std::vector<ui8> > > & visibilityMap) const; //returns appropriate bitmap and info if alpha blitting is necessary
|
std::pair<SDL_Surface *, bool> getVisBitmap(const int3 & pos, const std::vector< std::vector< std::vector<ui8> > > & visibilityMap) const; //returns appropriate bitmap and info if alpha blitting is necessary
|
||||||
|
ui8 getPhaseShift(const CGObjectInstance *object) const;
|
||||||
|
|
||||||
std::vector< std::string > getObjDescriptions(int3 pos); //returns desriptions of objects blocking given position
|
std::vector< std::string > getObjDescriptions(int3 pos); //returns desriptions of objects blocking given position
|
||||||
void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear
|
void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear
|
||||||
|
@ -561,40 +561,10 @@ ArtifactID CArtHandler::getRandomArt(int flags)
|
|||||||
}
|
}
|
||||||
ArtifactID CArtHandler::getArtSync (ui32 rand, int flags, bool erasePicked)
|
ArtifactID CArtHandler::getArtSync (ui32 rand, int flags, bool erasePicked)
|
||||||
{
|
{
|
||||||
auto erasePickedArt = [&]( ArtifactID id )
|
auto getAllowedArts = [&](std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, CArtifact::EartClass flag)
|
||||||
{
|
|
||||||
std::vector<CArtifact*>* ptr;
|
|
||||||
CArtifact *art = artifacts[id];
|
|
||||||
switch (art->aClass)
|
|
||||||
{
|
|
||||||
case CArtifact::ART_TREASURE:
|
|
||||||
ptr = &treasures;
|
|
||||||
break;
|
|
||||||
case CArtifact::ART_MINOR:
|
|
||||||
ptr = &minors;
|
|
||||||
break;
|
|
||||||
case CArtifact::ART_MAJOR:
|
|
||||||
ptr = &majors;
|
|
||||||
break;
|
|
||||||
case CArtifact::ART_RELIC:
|
|
||||||
ptr = &relics;
|
|
||||||
break;
|
|
||||||
default: //special artifacts should not be erased
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ptr->erase (std::find(ptr->begin(), ptr->end(), art)); //remove the artifact from available list
|
|
||||||
};
|
|
||||||
|
|
||||||
auto getAllowedArts = [&](std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag)
|
|
||||||
{
|
{
|
||||||
if (arts->empty()) //restock available arts
|
if (arts->empty()) //restock available arts
|
||||||
{
|
fillList(*arts, flag);
|
||||||
for (int i = 0; i < allowedArtifacts.size(); ++i)
|
|
||||||
{
|
|
||||||
if (allowedArtifacts[i]->aClass == flag)
|
|
||||||
arts->push_back(allowedArtifacts[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < arts->size(); ++i)
|
for (int i = 0; i < arts->size(); ++i)
|
||||||
{
|
{
|
||||||
@ -625,6 +595,8 @@ ArtifactID CArtHandler::getArtSync (ui32 rand, int flags, bool erasePicked)
|
|||||||
out.resize (64);
|
out.resize (64);
|
||||||
std::fill_n (out.begin(), 64, artifacts[2]); //Give Grail - this can't be banned (hopefully)
|
std::fill_n (out.begin(), 64, artifacts[2]); //Give Grail - this can't be banned (hopefully)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlog0 << "Treasure count: " << treasures.size() << std::endl;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ConstTransitivePtr<CArtifact> > out;
|
std::vector<ConstTransitivePtr<CArtifact> > out;
|
||||||
@ -829,6 +801,55 @@ std::vector<bool> CArtHandler::getDefaultAllowedArtifacts() const
|
|||||||
return allowedArtifacts;
|
return allowedArtifacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CArtHandler::erasePickedArt(ArtifactID id)
|
||||||
|
{
|
||||||
|
CArtifact *art = artifacts[id];
|
||||||
|
|
||||||
|
if(auto artifactList = listFromClass(art->aClass))
|
||||||
|
{
|
||||||
|
if(artifactList->empty())
|
||||||
|
fillList(*artifactList, art->aClass);
|
||||||
|
|
||||||
|
auto itr = vstd::find(*artifactList, art);
|
||||||
|
if(itr != artifactList->end())
|
||||||
|
{
|
||||||
|
artifactList->erase(itr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tlog2 << "Problem: cannot erase artifact " << art->Name() << " from list, it was not present\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tlog2 << "Problem: cannot find list for artifact " << art->Name() << ", strange class. (special?)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<std::vector<CArtifact*>&> CArtHandler::listFromClass( CArtifact::EartClass artifactClass )
|
||||||
|
{
|
||||||
|
switch(artifactClass)
|
||||||
|
{
|
||||||
|
case CArtifact::ART_TREASURE:
|
||||||
|
return treasures;
|
||||||
|
case CArtifact::ART_MINOR:
|
||||||
|
return minors;
|
||||||
|
case CArtifact::ART_MAJOR:
|
||||||
|
return majors;
|
||||||
|
case CArtifact::ART_RELIC:
|
||||||
|
return relics;
|
||||||
|
default: //special artifacts should not be erased
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CArtHandler::fillList( std::vector<CArtifact*> &listToBeFilled, CArtifact::EartClass artifactClass )
|
||||||
|
{
|
||||||
|
assert(listToBeFilled.empty());
|
||||||
|
for (int i = 0; i < allowedArtifacts.size(); ++i)
|
||||||
|
{
|
||||||
|
if (allowedArtifacts[i]->aClass == artifactClass)
|
||||||
|
listToBeFilled.push_back(allowedArtifacts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CArtifactInstance::CArtifactInstance()
|
CArtifactInstance::CArtifactInstance()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
@ -212,6 +212,12 @@ public:
|
|||||||
void addBonuses();
|
void addBonuses();
|
||||||
void clear();
|
void clear();
|
||||||
void clearHlpLists();
|
void clearHlpLists();
|
||||||
|
|
||||||
|
//void restockArtifactList()''
|
||||||
|
void fillList(std::vector<CArtifact*> &listToBeFilled, CArtifact::EartClass artifactClass); //fills given empty list with allowed artifacts of gibven class. No side effects
|
||||||
|
|
||||||
|
boost::optional<std::vector<CArtifact*>&> listFromClass(CArtifact::EartClass artifactClass);
|
||||||
|
void erasePickedArt(ArtifactID id);
|
||||||
ArtifactID getRandomArt (int flags);
|
ArtifactID getRandomArt (int flags);
|
||||||
ArtifactID getArtSync (ui32 rand, int flags, bool erasePicked = false);
|
ArtifactID getArtSync (ui32 rand, int flags, bool erasePicked = false);
|
||||||
bool legalArtifact(ArtifactID id);
|
bool legalArtifact(ArtifactID id);
|
||||||
|
@ -56,6 +56,7 @@ void foofoofoo()
|
|||||||
registerTypes((COSer<CConnection>&)*ccc);
|
registerTypes((COSer<CConnection>&)*ccc);
|
||||||
registerTypes((CSaveFile&)*ccc);
|
registerTypes((CSaveFile&)*ccc);
|
||||||
registerTypes((CLoadFile&)*ccc);
|
registerTypes((CLoadFile&)*ccc);
|
||||||
|
registerTypes((CLoadIntegrityValidator&)*ccc);
|
||||||
registerTypes((CTypeList&)*ccc);
|
registerTypes((CTypeList&)*ccc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,7 +816,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CScenarioTravel::STravelBonus::ARTIFACT:
|
case CScenarioTravel::STravelBonus::ARTIFACT:
|
||||||
gs->giveHeroArtifact(hero, curBonus->info2);
|
gs->giveHeroArtifact(hero, static_cast<ArtifactID>(curBonus->info2));
|
||||||
break;
|
break;
|
||||||
case CScenarioTravel::STravelBonus::SPELL_SCROLL:
|
case CScenarioTravel::STravelBonus::SPELL_SCROLL:
|
||||||
{
|
{
|
||||||
@ -962,8 +963,8 @@ void CGameState::init(StartInfo * si)
|
|||||||
|
|
||||||
day = 0;
|
day = 0;
|
||||||
|
|
||||||
tlog4 << "Initialization:";
|
tlog4 << "Initialization:\n";
|
||||||
tlog4 << "\tPicking grail position";
|
tlog4 << "\tPicking grail position\n";
|
||||||
//pick grail location
|
//pick grail location
|
||||||
if(map->grailPos.x < 0 || map->grailRadious) //grail not set or set within a radius around some place
|
if(map->grailPos.x < 0 || map->grailRadious) //grail not set or set within a radius around some place
|
||||||
{
|
{
|
||||||
@ -1003,7 +1004,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//picking random factions for players
|
//picking random factions for players
|
||||||
tlog4 << "\tPicking random factions for players";
|
tlog4 << "\tPicking random factions for players\n";
|
||||||
for(auto it = scenarioOps->playerInfos.begin();
|
for(auto it = scenarioOps->playerInfos.begin();
|
||||||
it != scenarioOps->playerInfos.end(); ++it)
|
it != scenarioOps->playerInfos.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -1018,7 +1019,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//randomizing objects
|
//randomizing objects
|
||||||
tlog4 << "\tRandomizing objects";
|
tlog4 << "\tRandomizing objects\n";
|
||||||
BOOST_FOREACH(CGObjectInstance *obj, map->objects)
|
BOOST_FOREACH(CGObjectInstance *obj, map->objects)
|
||||||
{
|
{
|
||||||
if(!obj)
|
if(!obj)
|
||||||
@ -1040,7 +1041,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
|
//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
|
||||||
|
|
||||||
/*********creating players entries in gs****************************************/
|
/*********creating players entries in gs****************************************/
|
||||||
tlog4 << "\tCreating player entries in gs";
|
tlog4 << "\tCreating player entries in gs\n";
|
||||||
for(auto it = scenarioOps->playerInfos.begin();
|
for(auto it = scenarioOps->playerInfos.begin();
|
||||||
it != scenarioOps->playerInfos.end(); ++it)
|
it != scenarioOps->playerInfos.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -1054,7 +1055,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*********give starting hero****************************************/
|
/*********give starting hero****************************************/
|
||||||
tlog4 << "\tGiving starting hero";
|
tlog4 << "\tGiving starting hero\n";
|
||||||
{
|
{
|
||||||
bool campaignGiveHero = false;
|
bool campaignGiveHero = false;
|
||||||
if(scenarioOps->campState)
|
if(scenarioOps->campState)
|
||||||
@ -1093,7 +1094,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*************************replace hero placeholders*****************************/
|
/*************************replace hero placeholders*****************************/
|
||||||
tlog4 << "\tReplacing hero placeholders";
|
tlog4 << "\tReplacing hero placeholders\n";
|
||||||
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > campHeroReplacements; //instance, id in vector
|
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > campHeroReplacements; //instance, id in vector
|
||||||
if (scenarioOps->campState)
|
if (scenarioOps->campState)
|
||||||
{
|
{
|
||||||
@ -1186,7 +1187,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/******************RESOURCES****************************************************/
|
/******************RESOURCES****************************************************/
|
||||||
tlog4 << "\tSetting up resources";
|
tlog4 << "\tSetting up resources\n";
|
||||||
const JsonNode config(ResourceID("config/startres.json"));
|
const JsonNode config(ResourceID("config/startres.json"));
|
||||||
const JsonVector &vector = config["difficulty"].Vector();
|
const JsonVector &vector = config["difficulty"].Vector();
|
||||||
const JsonNode &level = vector[scenarioOps->difficulty];
|
const JsonNode &level = vector[scenarioOps->difficulty];
|
||||||
@ -1240,7 +1241,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
|
|
||||||
|
|
||||||
/*************************HEROES************************************************/
|
/*************************HEROES************************************************/
|
||||||
tlog4 << "\tSetting up heroes";
|
tlog4 << "\tSetting up heroes\n";
|
||||||
//Replace placeholders with heroes from previous missions
|
//Replace placeholders with heroes from previous missions
|
||||||
BOOST_FOREACH(auto obj, campHeroReplacements)
|
BOOST_FOREACH(auto obj, campHeroReplacements)
|
||||||
{
|
{
|
||||||
@ -1374,7 +1375,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*************************FOG**OF**WAR******************************************/
|
/*************************FOG**OF**WAR******************************************/
|
||||||
tlog4 << "\tFog of war"; //FIXME: should be initialized after all bonuses are set
|
tlog4 << "\tFog of war\n"; //FIXME: should be initialized after all bonuses are set
|
||||||
for(auto k=teams.begin(); k!=teams.end(); ++k)
|
for(auto k=teams.begin(); k!=teams.end(); ++k)
|
||||||
{
|
{
|
||||||
k->second.fogOfWarMap.resize(map->width);
|
k->second.fogOfWarMap.resize(map->width);
|
||||||
@ -1403,7 +1404,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog4 << "\tStarting bonuses";
|
tlog4 << "\tStarting bonuses\n";
|
||||||
for(auto k=players.begin(); k!=players.end(); ++k)
|
for(auto k=players.begin(); k!=players.end(); ++k)
|
||||||
{
|
{
|
||||||
//starting bonus
|
//starting bonus
|
||||||
@ -1445,7 +1446,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/****************************TOWNS************************************************/
|
/****************************TOWNS************************************************/
|
||||||
tlog4 << "\tTowns";
|
tlog4 << "\tTowns\n";
|
||||||
|
|
||||||
//campaign bonuses for towns
|
//campaign bonuses for towns
|
||||||
if (scenarioOps->mode == StartInfo::CAMPAIGN)
|
if (scenarioOps->mode == StartInfo::CAMPAIGN)
|
||||||
@ -1519,16 +1520,16 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//town events
|
//town events
|
||||||
BOOST_FOREACH(CCastleEvent *ev, vti->events)
|
BOOST_FOREACH(CCastleEvent &ev, vti->events)
|
||||||
{
|
{
|
||||||
for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
|
for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
|
||||||
if (vstd::contains(ev->buildings,(-31-i))) //if we have horde for this level
|
if (vstd::contains(ev.buildings,(-31-i))) //if we have horde for this level
|
||||||
{
|
{
|
||||||
ev->buildings.erase(BuildingID(-31-i));
|
ev.buildings.erase(BuildingID(-31-i));
|
||||||
if (vti->town->hordeLvl[0] == i)
|
if (vti->town->hordeLvl[0] == i)
|
||||||
ev->buildings.insert(BuildingID::HORDE_1);
|
ev.buildings.insert(BuildingID::HORDE_1);
|
||||||
if (vti->town->hordeLvl[1] == i)
|
if (vti->town->hordeLvl[1] == i)
|
||||||
ev->buildings.insert(BuildingID::HORDE_2);
|
ev.buildings.insert(BuildingID::HORDE_2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//init spells
|
//init spells
|
||||||
@ -1573,7 +1574,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
getPlayer(vti->getOwner())->towns.push_back(vti);
|
getPlayer(vti->getOwner())->towns.push_back(vti);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog4 << "\tObject initialization";
|
tlog4 << "\tObject initialization\n";
|
||||||
objCaller->preInit();
|
objCaller->preInit();
|
||||||
BOOST_FOREACH(CGObjectInstance *obj, map->objects)
|
BOOST_FOREACH(CGObjectInstance *obj, map->objects)
|
||||||
{
|
{
|
||||||
@ -1627,7 +1628,7 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tlog4 << "\tChecking objectives";
|
tlog4 << "\tChecking objectives\n";
|
||||||
map->checkForObjectives(); //needs to be run when all objects are properly placed
|
map->checkForObjectives(); //needs to be run when all objects are properly placed
|
||||||
|
|
||||||
int seedAfterInit = ran();
|
int seedAfterInit = ran();
|
||||||
@ -2643,7 +2644,7 @@ void CGameState::attachArmedObjects()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameState::giveHeroArtifact(CGHeroInstance *h, int aid)
|
void CGameState::giveHeroArtifact(CGHeroInstance *h, ArtifactID aid)
|
||||||
{
|
{
|
||||||
CArtifact * const artifact = VLC->arth->artifacts[aid]; //pointer to constant object
|
CArtifact * const artifact = VLC->arth->artifacts[aid]; //pointer to constant object
|
||||||
CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact);
|
CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact);
|
||||||
|
@ -394,7 +394,7 @@ public:
|
|||||||
void randomizeObject(CGObjectInstance *cur);
|
void randomizeObject(CGObjectInstance *cur);
|
||||||
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
|
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
|
||||||
int pickHero(int owner);
|
int pickHero(int owner);
|
||||||
void giveHeroArtifact(CGHeroInstance *h, int aid);
|
void giveHeroArtifact(CGHeroInstance *h, ArtifactID aid);
|
||||||
|
|
||||||
void apply(CPack *pack);
|
void apply(CPack *pack);
|
||||||
BFieldType battleGetBattlefieldType(int3 tile) const;
|
BFieldType battleGetBattlefieldType(int3 tile) const;
|
||||||
|
@ -257,7 +257,7 @@ int CGObjectInstance::getOwner() const
|
|||||||
return tempOwner; //won't have owner
|
return tempOwner; //won't have owner
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance::CGObjectInstance(): animPhaseShift(rand()%0xff)
|
CGObjectInstance::CGObjectInstance()
|
||||||
{
|
{
|
||||||
pos = int3(-1,-1,-1);
|
pos = int3(-1,-1,-1);
|
||||||
//std::cout << "Tworze obiekt "<<this<<std::endl;
|
//std::cout << "Tworze obiekt "<<this<<std::endl;
|
||||||
@ -3141,6 +3141,12 @@ void CGCreature::initObj()
|
|||||||
amount = c.ammMax;
|
amount = c.ammMax;
|
||||||
else
|
else
|
||||||
amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
|
amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
|
||||||
|
|
||||||
|
if(!amount) //armies with 0 creatures are illegal
|
||||||
|
{
|
||||||
|
tlog2 << "Problem: stack " << nodeName() << " cannot have 0 creatures. Check properties of " << c.nodeName() << std::endl;
|
||||||
|
amount = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
temppower = stacks[SlotID(0)]->count * 1000;
|
temppower = stacks[SlotID(0)]->count * 1000;
|
||||||
@ -3506,13 +3512,13 @@ void CGResource::initObj()
|
|||||||
switch(subID)
|
switch(subID)
|
||||||
{
|
{
|
||||||
case 6:
|
case 6:
|
||||||
amount = 500 + (rand()%6)*100;
|
amount = 500 + (ran()%6)*100;
|
||||||
break;
|
break;
|
||||||
case 0: case 2:
|
case 0: case 2:
|
||||||
amount = 6 + (rand()%5);
|
amount = 6 + (ran()%5);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
amount = 3 + (rand()%3);
|
amount = 3 + (ran()%3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5894,43 +5900,56 @@ void CBank::reset(ui16 var1) //prevents desync
|
|||||||
|
|
||||||
void CBank::initialize() const
|
void CBank::initialize() const
|
||||||
{
|
{
|
||||||
cb->setObjProperty (id, 14, ran()); //synchronous reset
|
cb->setObjProperty (id, ObjProperty::BANK_RESET, ran()); //synchronous reset
|
||||||
|
|
||||||
for (ui8 i = 0; i <= 3; i++)
|
for (ui8 i = 0; i <= 3; i++)
|
||||||
{
|
{
|
||||||
for (ui8 n = 0; n < bc->artifacts[i]; n++) //new function using proper randomization algorithm
|
for (ui8 n = 0; n < bc->artifacts[i]; n++)
|
||||||
{
|
{
|
||||||
cb->setObjProperty (id, 18 + i, ran()); //synchronic artifacts
|
CArtifact::EartClass artClass;
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case 0: artClass = CArtifact::ART_TREASURE; break;
|
||||||
|
case 1: artClass = CArtifact::ART_MINOR; break;
|
||||||
|
case 2: artClass = CArtifact::ART_MAJOR; break;
|
||||||
|
case 3: artClass = CArtifact::ART_RELIC; break;
|
||||||
|
default: assert(0); continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int artID = cb->getArtSync(ran(), artClass, true);
|
||||||
|
cb->setObjProperty(id, ObjProperty::BANK_ADD_ARTIFACT, artID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cb->setObjProperty (id, 17, ran()); //get army
|
|
||||||
|
cb->setObjProperty (id, ObjProperty::BANK_INIT_ARMY, ran()); //get army
|
||||||
}
|
}
|
||||||
void CBank::setPropertyDer (ui8 what, ui32 val)
|
void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||||
/// random values are passed as arguments and processed identically on all clients
|
/// random values are passed as arguments and processed identically on all clients
|
||||||
{
|
{
|
||||||
switch (what)
|
switch (what)
|
||||||
{
|
{
|
||||||
case 11: //daycounter
|
case ObjProperty::BANK_DAYCOUNTER: //daycounter
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
daycounter = 1; //yes, 1
|
daycounter = 1; //yes, 1
|
||||||
else
|
else
|
||||||
daycounter++;
|
daycounter++;
|
||||||
break;
|
break;
|
||||||
case 12: //multiplier, in percent
|
case ObjProperty::BANK_MULTIPLIER: //multiplier, in percent
|
||||||
multiplier = val / 100.0;
|
multiplier = val / 100.0;
|
||||||
break;
|
break;
|
||||||
case 13: //bank preset
|
case 13: //bank preset
|
||||||
bc = VLC->objh->banksInfo[index][val];
|
bc = VLC->objh->banksInfo[index][val];
|
||||||
break;
|
break;
|
||||||
case 14:
|
case ObjProperty::BANK_RESET:
|
||||||
reset (val%100);
|
reset (val%100);
|
||||||
break;
|
break;
|
||||||
case 15:
|
case ObjProperty::BANK_CLEAR_CONFIG:
|
||||||
bc = NULL;
|
bc = NULL;
|
||||||
break;
|
break;
|
||||||
case 16: //remove rewards from Derelict Ship
|
case ObjProperty::BANK_CLEAR_ARTIFACTS: //remove rewards from Derelict Ship
|
||||||
artifacts.clear();
|
artifacts.clear();
|
||||||
break;
|
break;
|
||||||
case 17: //set ArmedInstance army
|
case ObjProperty::BANK_INIT_ARMY: //set ArmedInstance army
|
||||||
{
|
{
|
||||||
int upgraded = 0;
|
int upgraded = 0;
|
||||||
if (val%100 < bc->upgradeChance) //once again anti-desync
|
if (val%100 < bc->upgradeChance) //once again anti-desync
|
||||||
@ -5975,28 +5994,9 @@ void CBank::setPropertyDer (ui8 what, ui32 val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 18: //add Artifact
|
case ObjProperty::BANK_ADD_ARTIFACT: //add Artifact
|
||||||
{
|
{
|
||||||
int id = cb->getArtSync(val, CArtifact::ART_TREASURE, true);
|
artifacts.push_back (val);
|
||||||
artifacts.push_back (id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 19: //add Artifact
|
|
||||||
{
|
|
||||||
int id = cb->getArtSync(val, CArtifact::ART_MINOR, true);
|
|
||||||
artifacts.push_back (id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 20: //add Artifact
|
|
||||||
{
|
|
||||||
int id = cb->getArtSync(val, CArtifact::ART_MAJOR, true);
|
|
||||||
artifacts.push_back (id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 21: //add Artifact
|
|
||||||
{
|
|
||||||
int id = cb->getArtSync(val, CArtifact::ART_RELIC, true);
|
|
||||||
artifacts.push_back (id);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6011,15 +6011,15 @@ void CBank::newTurn() const
|
|||||||
else if (daycounter >= 28 && (subID < 13 || subID > 16)) //no reset for Emissaries
|
else if (daycounter >= 28 && (subID < 13 || subID > 16)) //no reset for Emissaries
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
cb->setObjProperty (id, 11, 0); //daycounter 0
|
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 0); //daycounter 0
|
||||||
if (ID == Obj::DERELICT_SHIP && cb->getDate() > 1)
|
if (ID == Obj::DERELICT_SHIP && cb->getDate() > 1)
|
||||||
{
|
{
|
||||||
cb->setObjProperty (id, 12, 0);//ugly hack to make derelict ships usable only once
|
cb->setObjProperty (id, ObjProperty::BANK_MULTIPLIER, 0);//ugly hack to make derelict ships usable only once
|
||||||
cb->setObjProperty (id, 16, 0);
|
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_ARTIFACTS, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cb->setObjProperty (id, 11, 1); //daycounter++
|
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool CBank::wasVisited (TPlayerColor player) const
|
bool CBank::wasVisited (TPlayerColor player) const
|
||||||
@ -6215,7 +6215,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
|
|||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
cb->giveCreatures(this, h, ourArmy, false);
|
cb->giveCreatures(this, h, ourArmy, false);
|
||||||
}
|
}
|
||||||
cb->setObjProperty (id, 15, 0); //bc = NULL
|
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_CONFIG, 0); //bc = NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -6227,13 +6227,13 @@ void CGPyramid::initObj()
|
|||||||
if (available.size())
|
if (available.size())
|
||||||
{
|
{
|
||||||
bc = VLC->objh->banksInfo[21].front(); //TODO: remove hardcoded value?
|
bc = VLC->objh->banksInfo[21].front(); //TODO: remove hardcoded value?
|
||||||
spell = (available[rand()%available.size()]);
|
spell = (available[ran()%available.size()]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tlog1 <<"No spells available for Pyramid! Object set to empty.\n";
|
tlog1 <<"No spells available for Pyramid! Object set to empty.\n";
|
||||||
}
|
}
|
||||||
setPropertyDer (17,ran()); //set guards at game start
|
setPropertyDer (ObjProperty::BANK_INIT_ARMY,ran()); //set guards at game start
|
||||||
}
|
}
|
||||||
const std::string & CGPyramid::getHoverText() const
|
const std::string & CGPyramid::getHoverText() const
|
||||||
{
|
{
|
||||||
@ -6284,7 +6284,7 @@ void CGPyramid::endBattle (const CGHeroInstance *h, const BattleResult *result)
|
|||||||
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
|
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
|
||||||
}
|
}
|
||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
cb->setObjProperty (id, 15, 0);
|
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_CONFIG, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8
|
void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8
|
||||||
|
@ -172,7 +172,6 @@ public:
|
|||||||
si32 subID; //normal subID (this one from OH3 maps ;])
|
si32 subID; //normal subID (this one from OH3 maps ;])
|
||||||
ObjectInstanceID id;//number of object in map's vector
|
ObjectInstanceID id;//number of object in map's vector
|
||||||
CGDefInfo * defInfo;
|
CGDefInfo * defInfo;
|
||||||
ui8 animPhaseShift;
|
|
||||||
|
|
||||||
TPlayerColor tempOwner;
|
TPlayerColor tempOwner;
|
||||||
bool blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile
|
bool blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile
|
||||||
@ -211,7 +210,7 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & hoverName & pos & ID & subID & id & animPhaseShift & tempOwner & blockVisit & defInfo;
|
h & hoverName & pos & ID & subID & id & tempOwner & blockVisit & defInfo;
|
||||||
//definfo is handled by map serializer
|
//definfo is handled by map serializer
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
@ -591,7 +590,7 @@ public:
|
|||||||
std::vector<CGTownBuilding*> bonusingBuildings;
|
std::vector<CGTownBuilding*> bonusingBuildings;
|
||||||
std::vector<SpellID> possibleSpells, obligatorySpells;
|
std::vector<SpellID> possibleSpells, obligatorySpells;
|
||||||
std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
|
std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
|
||||||
std::list<CCastleEvent*> events;
|
std::list<CCastleEvent> events;
|
||||||
std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
|
std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -344,6 +344,11 @@ void CSaveFile::clear()
|
|||||||
sfile = nullptr;
|
sfile = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSaveFile::putMagicBytes( const std::string &text )
|
||||||
|
{
|
||||||
|
write(text.c_str(), text.length());
|
||||||
|
}
|
||||||
|
|
||||||
CLoadFile::CLoadFile(const std::string &fname, int minimalVersion /*= version*/)
|
CLoadFile::CLoadFile(const std::string &fname, int minimalVersion /*= version*/)
|
||||||
{
|
{
|
||||||
registerTypes(*this);
|
registerTypes(*this);
|
||||||
@ -424,6 +429,14 @@ void CLoadFile::clear()
|
|||||||
fileVersion = 0;
|
fileVersion = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CLoadFile::checkMagicBytes( const std::string &text )
|
||||||
|
{
|
||||||
|
std::string loaded = text;
|
||||||
|
read(loaded.c_str(), text.length());
|
||||||
|
if(loaded != text)
|
||||||
|
throw std::runtime_error("Magic bytes doesn't match!");
|
||||||
|
}
|
||||||
|
|
||||||
CTypeList::CTypeList()
|
CTypeList::CTypeList()
|
||||||
{
|
{
|
||||||
registerTypes(*this);
|
registerTypes(*this);
|
||||||
@ -477,3 +490,47 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
|
|||||||
registerVectoredType(&gs->map->quests, &CQuest::qid);
|
registerVectoredType(&gs->map->quests, &CQuest::qid);
|
||||||
smartVectorMembersSerialization = true;
|
smartVectorMembersSerialization = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLoadIntegrityValidator::CLoadIntegrityValidator( const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion /*= version*/ )
|
||||||
|
: foundDesync(false)
|
||||||
|
{
|
||||||
|
registerTypes(*this);
|
||||||
|
primaryFile = make_unique<CLoadFile>(primaryFileName, minimalVersion);
|
||||||
|
controlFile = make_unique<CLoadFile>(controlFileName, minimalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLoadIntegrityValidator::read( const void * data, unsigned size )
|
||||||
|
{
|
||||||
|
assert(primaryFile);
|
||||||
|
assert(controlFile);
|
||||||
|
|
||||||
|
if(!size)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
std::vector<ui8> controlData(size);
|
||||||
|
auto ret = primaryFile->read(data, size);
|
||||||
|
controlFile->read(controlData.data(), size);
|
||||||
|
|
||||||
|
if(!foundDesync && std::memcmp(data, controlData.data(), size))
|
||||||
|
{
|
||||||
|
tlog1 << "Desync found! Position: " << primaryFile->sfile->tellg() << std::endl;
|
||||||
|
foundDesync = true;
|
||||||
|
//throw std::runtime_error("Savegame dsynchronized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
|
||||||
|
{
|
||||||
|
return std::move(primaryFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLoadIntegrityValidator::checkMagicBytes( const std::string &text )
|
||||||
|
{
|
||||||
|
assert(primaryFile);
|
||||||
|
assert(controlFile);
|
||||||
|
|
||||||
|
primaryFile->checkMagicBytes(text);
|
||||||
|
controlFile->checkMagicBytes(text);
|
||||||
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#include "CObjectHandler.h" //for CArmedInstance
|
#include "CObjectHandler.h" //for CArmedInstance
|
||||||
#include "Mapping/CCampaignHandler.h" //for CCampaignState
|
#include "Mapping/CCampaignHandler.h" //for CCampaignState
|
||||||
|
|
||||||
const ui32 version = 737;
|
const ui32 version = 738;
|
||||||
|
|
||||||
class CConnection;
|
class CConnection;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
@ -47,6 +47,8 @@ struct CPack;
|
|||||||
extern DLL_LINKAGE LibClasses * VLC;
|
extern DLL_LINKAGE LibClasses * VLC;
|
||||||
namespace mpl = boost::mpl;
|
namespace mpl = boost::mpl;
|
||||||
|
|
||||||
|
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
namespace asio
|
namespace asio
|
||||||
@ -382,7 +384,7 @@ public:
|
|||||||
si32 idAsNumber = idToNumber(id);
|
si32 idAsNumber = idToNumber(id);
|
||||||
|
|
||||||
assert(oInfo.vector);
|
assert(oInfo.vector);
|
||||||
assert(oInfo.vector->size() > idAsNumber);
|
assert(static_cast<si32>(oInfo.vector->size()) > idAsNumber);
|
||||||
return const_cast<T*>((*oInfo.vector)[idAsNumber].get());
|
return const_cast<T*>((*oInfo.vector)[idAsNumber].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1218,6 +1220,8 @@ public:
|
|||||||
void openNextFile(const std::string &fname); //throws!
|
void openNextFile(const std::string &fname); //throws!
|
||||||
void clear();
|
void clear();
|
||||||
void reportState(CLogger &out);
|
void reportState(CLogger &out);
|
||||||
|
|
||||||
|
void putMagicBytes(const std::string &text);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CLoadFile
|
class DLL_LINKAGE CLoadFile
|
||||||
@ -1239,6 +1243,22 @@ public:
|
|||||||
void openNextFile(const std::string &fname, int minimalVersion); //throws!
|
void openNextFile(const std::string &fname, int minimalVersion); //throws!
|
||||||
void clear();
|
void clear();
|
||||||
void reportState(CLogger &out);
|
void reportState(CLogger &out);
|
||||||
|
|
||||||
|
void checkMagicBytes(const std::string &text);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE CLoadIntegrityValidator : public CISer<CLoadIntegrityValidator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unique_ptr<CLoadFile> primaryFile, controlFile;
|
||||||
|
bool foundDesync;
|
||||||
|
|
||||||
|
CLoadIntegrityValidator(const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion = version); //throws!
|
||||||
|
|
||||||
|
int read(const void * data, unsigned size); //throws!
|
||||||
|
void checkMagicBytes(const std::string &text);
|
||||||
|
|
||||||
|
unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
|
typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
|
||||||
|
@ -198,7 +198,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Der>
|
template<typename Der>
|
||||||
DLL_LINKAGE std::ostream & operator << (std::ostream & os, BaseForID<Der> id);
|
std::ostream & operator << (std::ostream & os, BaseForID<Der> id);
|
||||||
|
|
||||||
template<typename Der>
|
template<typename Der>
|
||||||
std::ostream & operator << (std::ostream & os, BaseForID<Der> id)
|
std::ostream & operator << (std::ostream & os, BaseForID<Der> id)
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#include "CBuildingHandler.h"
|
#include "CBuildingHandler.h"
|
||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "CModHandler.h"
|
#include "CModHandler.h"
|
||||||
|
#include "CDefObjInfoHandler.h"
|
||||||
|
|
||||||
|
#include "Connection.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IGameCallback.cpp, part of VCMI engine
|
* IGameCallback.cpp, part of VCMI engine
|
||||||
@ -210,6 +213,48 @@ void CPrivilagedInfoCallback::getAllowedSpells(std::vector<SpellID> &out, ui16 l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Loader>
|
||||||
|
void CPrivilagedInfoCallback::loadCommonState(Loader &in)
|
||||||
|
{
|
||||||
|
tlog0 << "Loading lib part of game...\n";
|
||||||
|
in.checkMagicBytes(SAVEGAME_MAGIC);
|
||||||
|
|
||||||
|
CMapHeader dum;
|
||||||
|
StartInfo *si;
|
||||||
|
|
||||||
|
tlog0 <<"\tReading header"<<std::endl;
|
||||||
|
in >> dum;
|
||||||
|
|
||||||
|
tlog0 << "\tReading options"<<std::endl;
|
||||||
|
in >> si;
|
||||||
|
|
||||||
|
tlog0 <<"\tReading handlers"<<std::endl;
|
||||||
|
in >> *VLC;
|
||||||
|
|
||||||
|
tlog0 <<"\tReading gamestate"<<std::endl;
|
||||||
|
in >> gs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Saver>
|
||||||
|
void CPrivilagedInfoCallback::saveCommonState(Saver &out) const
|
||||||
|
{
|
||||||
|
tlog0 << "Saving lib part of game...";
|
||||||
|
out.putMagicBytes(SAVEGAME_MAGIC);
|
||||||
|
tlog0 <<"\tSaving header"<<std::endl;
|
||||||
|
out << static_cast<CMapHeader&>(*gs->map);
|
||||||
|
tlog0 << "\tSaving options"<<std::endl;
|
||||||
|
out << gs->scenarioOps;
|
||||||
|
tlog0 << "\tSaving handlers"<<std::endl;
|
||||||
|
out << *VLC;
|
||||||
|
tlog0 << "\tSaving gamestate"<<std::endl;
|
||||||
|
out << gs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template DLL_LINKAGE void CPrivilagedInfoCallback::loadCommonState<CLoadIntegrityValidator>(CLoadIntegrityValidator&);
|
||||||
|
template DLL_LINKAGE void CPrivilagedInfoCallback::loadCommonState<CLoadFile>(CLoadFile&);
|
||||||
|
template DLL_LINKAGE void CPrivilagedInfoCallback::saveCommonState<CSaveFile>(CSaveFile&) const;
|
||||||
|
|
||||||
inline TerrainTile * CNonConstInfoCallback::getTile( int3 pos )
|
inline TerrainTile * CNonConstInfoCallback::getTile( int3 pos )
|
||||||
{
|
{
|
||||||
if(!gs->map->isInTheMap(pos))
|
if(!gs->map->isInTheMap(pos))
|
||||||
|
@ -58,7 +58,8 @@ class CStackBasicDescriptor;
|
|||||||
struct TeamState;
|
struct TeamState;
|
||||||
struct QuestInfo;
|
struct QuestInfo;
|
||||||
class CGCreature;
|
class CGCreature;
|
||||||
|
class CSaveFile;
|
||||||
|
class CLoadFile;
|
||||||
|
|
||||||
class DLL_LINKAGE CGameInfoCallback : public virtual CCallbackBase
|
class DLL_LINKAGE CGameInfoCallback : public virtual CCallbackBase
|
||||||
{
|
{
|
||||||
@ -176,6 +177,12 @@ public:
|
|||||||
ArtifactID getArtSync (ui32 rand, int flags, bool erasePicked); //synchronous
|
ArtifactID getArtSync (ui32 rand, int flags, bool erasePicked); //synchronous
|
||||||
void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||||
void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
|
void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
|
||||||
|
|
||||||
|
template<typename Saver>
|
||||||
|
void saveCommonState(Saver &out) const; //stores GS and VLC
|
||||||
|
|
||||||
|
template<typename Loader>
|
||||||
|
void loadCommonState(Loader &in); //loads GS and VLC
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CNonConstInfoCallback : public CPrivilagedInfoCallback
|
class DLL_LINKAGE CNonConstInfoCallback : public CPrivilagedInfoCallback
|
||||||
@ -235,6 +242,7 @@ public:
|
|||||||
virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
|
virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
|
||||||
virtual void removeArtifact(const ArtifactLocation &al) = 0;
|
virtual void removeArtifact(const ArtifactLocation &al) = 0;
|
||||||
virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
|
virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
|
||||||
|
virtual void synchronizeArtifactHandlerLists() = 0;
|
||||||
|
|
||||||
virtual void showCompInfo(ShowInInfobox * comp)=0;
|
virtual void showCompInfo(ShowInInfobox * comp)=0;
|
||||||
virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
||||||
|
@ -158,11 +158,6 @@ CMap::~CMap()
|
|||||||
}
|
}
|
||||||
delete [] terrain;
|
delete [] terrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::list<ConstTransitivePtr<CMapEvent> >::iterator i = events.begin(); i != events.end(); i++)
|
|
||||||
{
|
|
||||||
i->dellNull();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
|
void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
|
||||||
|
@ -743,7 +743,7 @@ public:
|
|||||||
std::vector<bool> allowedAbilities;
|
std::vector<bool> allowedAbilities;
|
||||||
|
|
||||||
/** list of map events */
|
/** list of map events */
|
||||||
std::list<ConstTransitivePtr<CMapEvent> > events;
|
std::list<CMapEvent> events;
|
||||||
|
|
||||||
/** specifies the position of the grail */
|
/** specifies the position of the grail */
|
||||||
int3 grailPos;
|
int3 grailPos;
|
||||||
|
@ -1959,39 +1959,39 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID)
|
|||||||
|
|
||||||
for(int gh = 0; gh < numberOfEvent; ++gh)
|
for(int gh = 0; gh < numberOfEvent; ++gh)
|
||||||
{
|
{
|
||||||
CCastleEvent * nce = new CCastleEvent();
|
CCastleEvent nce;
|
||||||
nce->town = nt;
|
nce.town = nt;
|
||||||
nce->name = reader.readString();
|
nce.name = reader.readString();
|
||||||
nce->message = reader.readString();
|
nce.message = reader.readString();
|
||||||
|
|
||||||
readResourses(nce->resources);
|
readResourses(nce.resources);
|
||||||
|
|
||||||
nce->players = reader.readUInt8();
|
nce.players = reader.readUInt8();
|
||||||
if(map->version > EMapFormat::AB)
|
if(map->version > EMapFormat::AB)
|
||||||
{
|
{
|
||||||
nce->humanAffected = reader.readUInt8();
|
nce.humanAffected = reader.readUInt8();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nce->humanAffected = true;
|
nce.humanAffected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nce->computerAffected = reader.readUInt8();
|
nce.computerAffected = reader.readUInt8();
|
||||||
nce->firstOccurence = reader.readUInt16();
|
nce.firstOccurence = reader.readUInt16();
|
||||||
nce->nextOccurence = reader.readUInt8();
|
nce.nextOccurence = reader.readUInt8();
|
||||||
|
|
||||||
reader.skip(17);
|
reader.skip(17);
|
||||||
|
|
||||||
// New buildings
|
// New buildings
|
||||||
|
|
||||||
readBitmask(nce->buildings,6,48,false);
|
readBitmask(nce.buildings,6,48,false);
|
||||||
|
|
||||||
nce->buildings = convertBuildings(nce->buildings, castleID, false);
|
nce.buildings = convertBuildings(nce.buildings, castleID, false);
|
||||||
|
|
||||||
nce->creatures.resize(7);
|
nce.creatures.resize(7);
|
||||||
for(int vv = 0; vv < 7; ++vv)
|
for(int vv = 0; vv < 7; ++vv)
|
||||||
{
|
{
|
||||||
nce->creatures[vv] = reader.readUInt16();
|
nce.creatures[vv] = reader.readUInt16();
|
||||||
}
|
}
|
||||||
reader.skip(4);
|
reader.skip(4);
|
||||||
nt->events.push_back(nce);
|
nt->events.push_back(nce);
|
||||||
@ -2072,23 +2072,23 @@ void CMapLoaderH3M::readEvents()
|
|||||||
int numberOfEvents = reader.readUInt32();
|
int numberOfEvents = reader.readUInt32();
|
||||||
for(int yyoo = 0; yyoo < numberOfEvents; ++yyoo)
|
for(int yyoo = 0; yyoo < numberOfEvents; ++yyoo)
|
||||||
{
|
{
|
||||||
CMapEvent * ne = new CMapEvent();
|
CMapEvent ne;
|
||||||
ne->name = reader.readString();
|
ne.name = reader.readString();
|
||||||
ne->message = reader.readString();
|
ne.message = reader.readString();
|
||||||
|
|
||||||
readResourses(ne->resources);
|
readResourses(ne.resources);
|
||||||
ne->players = reader.readUInt8();
|
ne.players = reader.readUInt8();
|
||||||
if(map->version > EMapFormat::AB)
|
if(map->version > EMapFormat::AB)
|
||||||
{
|
{
|
||||||
ne->humanAffected = reader.readUInt8();
|
ne.humanAffected = reader.readUInt8();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ne->humanAffected = true;
|
ne.humanAffected = true;
|
||||||
}
|
}
|
||||||
ne->computerAffected = reader.readUInt8();
|
ne.computerAffected = reader.readUInt8();
|
||||||
ne->firstOccurence = reader.readUInt16();
|
ne.firstOccurence = reader.readUInt16();
|
||||||
ne->nextOccurence = reader.readUInt8();
|
ne.nextOccurence = reader.readUInt8();
|
||||||
|
|
||||||
reader.skip(17);
|
reader.skip(17);
|
||||||
|
|
||||||
|
@ -577,6 +577,44 @@ struct PrepareForAdvancingCampaign : public CPackForClient //122
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UpdateArtHandlerLists : public CPackForClient //123
|
||||||
|
{
|
||||||
|
UpdateArtHandlerLists(){type = 123;};
|
||||||
|
std::vector<CArtifact*> treasures, minors, majors, relics;
|
||||||
|
|
||||||
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & treasures & minors & majors & relics;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UpdateMapEvents : public CPackForClient //124
|
||||||
|
{
|
||||||
|
UpdateMapEvents(){type = 124;}
|
||||||
|
|
||||||
|
std::list<CMapEvent> events;
|
||||||
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & events;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UpdateCastleEvents : public CPackForClient //125
|
||||||
|
{
|
||||||
|
UpdateCastleEvents(){type = 125;}
|
||||||
|
|
||||||
|
ObjectInstanceID town;
|
||||||
|
std::list<CCastleEvent> events;
|
||||||
|
|
||||||
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & town & events;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct RemoveObject : public CPackForClient //500
|
struct RemoveObject : public CPackForClient //500
|
||||||
{
|
{
|
||||||
RemoveObject(){type = 500;};
|
RemoveObject(){type = 500;};
|
||||||
@ -1133,8 +1171,11 @@ namespace ObjProperty
|
|||||||
|
|
||||||
//town-specific
|
//town-specific
|
||||||
STRUCTURE_ADD_VISITING_HERO, STRUCTURE_CLEAR_VISITORS, STRUCTURE_ADD_GARRISONED_HERO, //changing buildings state
|
STRUCTURE_ADD_VISITING_HERO, STRUCTURE_CLEAR_VISITORS, STRUCTURE_ADD_GARRISONED_HERO, //changing buildings state
|
||||||
BONUS_VALUE_FIRST, BONUS_VALUE_SECOND //used in Rampart for special building that generates resources (storing resource type and quantity)
|
BONUS_VALUE_FIRST, BONUS_VALUE_SECOND, //used in Rampart for special building that generates resources (storing resource type and quantity)
|
||||||
|
|
||||||
|
//creature-bank specific
|
||||||
|
BANK_DAYCOUNTER, BANK_CLEAR_ARTIFACTS, BANK_ADD_ARTIFACT, BANK_MULTIPLIER, BANK_CONFIG_PRESET,
|
||||||
|
BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +116,26 @@ DLL_LINKAGE void AddQuest::applyGs(CGameState *gs)
|
|||||||
tlog2 << "Warning! Attempt to add duplicated quest\n";
|
tlog2 << "Warning! Attempt to add duplicated quest\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLL_LINKAGE void UpdateArtHandlerLists::applyGs(CGameState *gs)
|
||||||
|
{
|
||||||
|
VLC->arth->minors = minors;
|
||||||
|
VLC->arth->majors = majors;
|
||||||
|
VLC->arth->treasures = treasures;
|
||||||
|
VLC->arth->relics = relics;
|
||||||
|
}
|
||||||
|
|
||||||
|
DLL_LINKAGE void UpdateMapEvents::applyGs(CGameState *gs)
|
||||||
|
{
|
||||||
|
gs->map->events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DLL_LINKAGE void UpdateCastleEvents::applyGs(CGameState *gs)
|
||||||
|
{
|
||||||
|
auto t = gs->getTown(town);
|
||||||
|
t->events = events;
|
||||||
|
}
|
||||||
|
|
||||||
DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs )
|
DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
CGHeroInstance *h = gs->getHero(hid);
|
CGHeroInstance *h = gs->getHero(hid);
|
||||||
@ -794,7 +814,7 @@ DLL_LINKAGE void MoveArtifact::applyGs( CGameState *gs )
|
|||||||
{
|
{
|
||||||
CGHeroInstance *h = *hPtr;
|
CGHeroInstance *h = *hPtr;
|
||||||
if(h && !h->hasSpellbook())
|
if(h && !h->hasSpellbook())
|
||||||
gs->giveHeroArtifact(h, 0);
|
gs->giveHeroArtifact(h, ArtifactID::SPELLBOOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,9 @@ void registerTypes2(Serializer &s)
|
|||||||
s.template registerType<RemoveBonus>();
|
s.template registerType<RemoveBonus>();
|
||||||
s.template registerType<UpdateCampaignState>();
|
s.template registerType<UpdateCampaignState>();
|
||||||
s.template registerType<PrepareForAdvancingCampaign>();
|
s.template registerType<PrepareForAdvancingCampaign>();
|
||||||
|
s.template registerType<UpdateArtHandlerLists>();
|
||||||
|
s.template registerType<UpdateMapEvents>();
|
||||||
|
s.template registerType<UpdateCastleEvents>();
|
||||||
s.template registerType<RemoveObject>();
|
s.template registerType<RemoveObject>();
|
||||||
s.template registerType<TryMoveHero>();
|
s.template registerType<TryMoveHero>();
|
||||||
//s.template registerType<SetGarrisons>();
|
//s.template registerType<SetGarrisons>();
|
||||||
|
@ -1111,9 +1111,9 @@ void CGameHandler::init(StartInfo *si)
|
|||||||
states.addPlayer(i->first);
|
states.addPlayer(i->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool evntCmp(const CMapEvent *a, const CMapEvent *b)
|
static bool evntCmp(const CMapEvent &a, const CMapEvent &b)
|
||||||
{
|
{
|
||||||
return a->earlierThan(*b);
|
return a.earlierThan(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false, bool clear = false)
|
void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false, bool clear = false)
|
||||||
@ -1501,6 +1501,8 @@ void CGameHandler::newTurn()
|
|||||||
sendAndApply(&iw);
|
sendAndApply(&iw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronizeArtifactHandlerLists(); //new day events may have changed them. TODO better of managing that
|
||||||
}
|
}
|
||||||
void CGameHandler::run(bool resume)
|
void CGameHandler::run(bool resume)
|
||||||
{
|
{
|
||||||
@ -2306,16 +2308,18 @@ void CGameHandler::save(const std::string & filename )
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
{
|
// {
|
||||||
tlog0 << "Serializing game info...\n";
|
// tlog0 << "Serializing game info...\n";
|
||||||
CSaveFile save(CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::LIB_SAVEGAME)));
|
// CSaveFile save(CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::LIB_SAVEGAME)));
|
||||||
char hlp[8] = "VCMISVG";
|
// // char hlp[8] = "VCMISVG";
|
||||||
save << hlp << static_cast<CMapHeader&>(*gs->map) << gs->scenarioOps << *VLC << gs;
|
// // save << hlp;
|
||||||
}
|
// saveCommonState(save);
|
||||||
|
// }
|
||||||
|
|
||||||
{
|
{
|
||||||
tlog0 << "Serializing server info...\n";
|
|
||||||
CSaveFile save(CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::SERVER_SAVEGAME)));
|
CSaveFile save(CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::SERVER_SAVEGAME)));
|
||||||
|
saveCommonState(save);
|
||||||
|
tlog0 << "Saving server state\n";
|
||||||
save << *this;
|
save << *this;
|
||||||
}
|
}
|
||||||
tlog0 << "Game has been successfully saved!\n";
|
tlog0 << "Game has been successfully saved!\n";
|
||||||
@ -4688,34 +4692,34 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
|
|||||||
void CGameHandler::handleTimeEvents()
|
void CGameHandler::handleTimeEvents()
|
||||||
{
|
{
|
||||||
gs->map->events.sort(evntCmp);
|
gs->map->events.sort(evntCmp);
|
||||||
while(gs->map->events.size() && gs->map->events.front()->firstOccurence+1 == gs->day)
|
while(gs->map->events.size() && gs->map->events.front().firstOccurence+1 == gs->day)
|
||||||
{
|
{
|
||||||
CMapEvent *ev = gs->map->events.front();
|
CMapEvent ev = gs->map->events.front();
|
||||||
for(int player = 0; player < GameConstants::PLAYER_LIMIT; player++)
|
for(int player = 0; player < GameConstants::PLAYER_LIMIT; player++)
|
||||||
{
|
{
|
||||||
PlayerState *pinfo = gs->getPlayer(player);
|
PlayerState *pinfo = gs->getPlayer(player);
|
||||||
|
|
||||||
if( pinfo //player exists
|
if( pinfo //player exists
|
||||||
&& (ev->players & 1<<player) //event is enabled to this player
|
&& (ev.players & 1<<player) //event is enabled to this player
|
||||||
&& ((ev->computerAffected && !pinfo->human)
|
&& ((ev.computerAffected && !pinfo->human)
|
||||||
|| (ev->humanAffected && pinfo->human)
|
|| (ev.humanAffected && pinfo->human)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//give resources
|
//give resources
|
||||||
SetResources sr;
|
SetResources sr;
|
||||||
sr.player = player;
|
sr.player = player;
|
||||||
sr.res = pinfo->resources + ev->resources;
|
sr.res = pinfo->resources + ev.resources;
|
||||||
|
|
||||||
//prepare dialog
|
//prepare dialog
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = player;
|
iw.player = player;
|
||||||
iw.text << ev->message;
|
iw.text << ev.message;
|
||||||
|
|
||||||
for (int i=0; i<ev->resources.size(); i++)
|
for (int i=0; i<ev.resources.size(); i++)
|
||||||
{
|
{
|
||||||
if(ev->resources[i]) //if resource is changed, we add it to the dialog
|
if(ev.resources[i]) //if resource is changed, we add it to the dialog
|
||||||
iw.components.push_back(Component(Component::RESOURCE,i,ev->resources[i],0));
|
iw.components.push_back(Component(Component::RESOURCE,i,ev.resources[i],0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iw.components.size())
|
if (iw.components.size())
|
||||||
@ -4728,59 +4732,62 @@ void CGameHandler::handleTimeEvents()
|
|||||||
}
|
}
|
||||||
} //PLAYERS LOOP
|
} //PLAYERS LOOP
|
||||||
|
|
||||||
if(ev->nextOccurence)
|
if(ev.nextOccurence)
|
||||||
{
|
{
|
||||||
gs->map->events.pop_front();
|
gs->map->events.pop_front();
|
||||||
|
|
||||||
ev->firstOccurence += ev->nextOccurence;
|
ev.firstOccurence += ev.nextOccurence;
|
||||||
std::list<ConstTransitivePtr<CMapEvent> >::iterator it = gs->map->events.begin();
|
auto it = gs->map->events.begin();
|
||||||
while ( it !=gs->map->events.end() && (*it)->earlierThanOrEqual(*ev))
|
while ( it !=gs->map->events.end() && it->earlierThanOrEqual(ev))
|
||||||
it++;
|
it++;
|
||||||
gs->map->events.insert(it, ev);
|
gs->map->events.insert(it, ev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete ev;
|
|
||||||
gs->map->events.pop_front();
|
gs->map->events.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO send only if changed
|
||||||
|
UpdateMapEvents ume;
|
||||||
|
ume.events = gs->map->events;
|
||||||
|
sendAndApply(&ume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<ObjectInstanceID, std::map<si32, si32> > &newCreas)
|
void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<ObjectInstanceID, std::map<si32, si32> > &newCreas)
|
||||||
{
|
{
|
||||||
//TODO event removing desync!!!
|
|
||||||
town->events.sort(evntCmp);
|
town->events.sort(evntCmp);
|
||||||
while(town->events.size() && town->events.front()->firstOccurence == gs->day)
|
while(town->events.size() && town->events.front().firstOccurence == gs->day)
|
||||||
{
|
{
|
||||||
ui8 player = town->tempOwner;
|
ui8 player = town->tempOwner;
|
||||||
CCastleEvent *ev = town->events.front();
|
CCastleEvent ev = town->events.front();
|
||||||
PlayerState *pinfo = gs->getPlayer(player);
|
PlayerState *pinfo = gs->getPlayer(player);
|
||||||
|
|
||||||
if( pinfo //player exists
|
if( pinfo //player exists
|
||||||
&& (ev->players & 1<<player) //event is enabled to this player
|
&& (ev.players & 1<<player) //event is enabled to this player
|
||||||
&& ((ev->computerAffected && !pinfo->human)
|
&& ((ev.computerAffected && !pinfo->human)
|
||||||
|| (ev->humanAffected && pinfo->human) ) )
|
|| (ev.humanAffected && pinfo->human) ) )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// dialog
|
// dialog
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = player;
|
iw.player = player;
|
||||||
iw.text << ev->message;
|
iw.text << ev.message;
|
||||||
|
|
||||||
if(ev->resources.nonZero())
|
if(ev.resources.nonZero())
|
||||||
{
|
{
|
||||||
TResources was = n.res[player];
|
TResources was = n.res[player];
|
||||||
n.res[player] += ev->resources;
|
n.res[player] += ev.resources;
|
||||||
n.res[player].amax(0);
|
n.res[player].amax(0);
|
||||||
|
|
||||||
for (int i=0; i<ev->resources.size(); i++)
|
for (int i=0; i<ev.resources.size(); i++)
|
||||||
if(ev->resources[i] && pinfo->resources[i] != n.res[player][i]) //if resource had changed, we add it to the dialog
|
if(ev.resources[i] && pinfo->resources[i] != n.res[player][i]) //if resource had changed, we add it to the dialog
|
||||||
iw.components.push_back(Component(Component::RESOURCE,i,n.res[player][i]-was[i],0));
|
iw.components.push_back(Component(Component::RESOURCE,i,n.res[player][i]-was[i],0));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(auto & i, ev->buildings)
|
BOOST_FOREACH(auto & i, ev.buildings)
|
||||||
{
|
{
|
||||||
if ( town->hasBuilt(i))
|
if ( town->hasBuilt(i))
|
||||||
{
|
{
|
||||||
@ -4789,34 +4796,39 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(si32 i=0;i<ev->creatures.size();i++) //creature growths
|
for(si32 i=0;i<ev.creatures.size();i++) //creature growths
|
||||||
{
|
{
|
||||||
if(town->creatureDwellingLevel(i) >= 0 && ev->creatures[i])//there is dwelling
|
if(town->creatureDwellingLevel(i) >= 0 && ev.creatures[i])//there is dwelling
|
||||||
{
|
{
|
||||||
newCreas[town->id][i] += ev->creatures[i];
|
newCreas[town->id][i] += ev.creatures[i];
|
||||||
iw.components.push_back(Component(Component::CREATURE,
|
iw.components.push_back(Component(Component::CREATURE,
|
||||||
town->creatures[i].second.back(), ev->creatures[i], 0));
|
town->creatures[i].second.back(), ev.creatures[i], 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendAndApply(&iw); //show dialog
|
sendAndApply(&iw); //show dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ev->nextOccurence)
|
if(ev.nextOccurence)
|
||||||
{
|
{
|
||||||
town->events.pop_front();
|
town->events.pop_front();
|
||||||
|
|
||||||
ev->firstOccurence += ev->nextOccurence;
|
ev.firstOccurence += ev.nextOccurence;
|
||||||
std::list<CCastleEvent*>::iterator it = town->events.begin();
|
auto it = town->events.begin();
|
||||||
while ( it !=town->events.end() && (*it)->earlierThanOrEqual(*ev))
|
while ( it != town->events.end() && it->earlierThanOrEqual(ev))
|
||||||
it++;
|
it++;
|
||||||
town->events.insert(it, ev);
|
town->events.insert(it, ev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete ev;
|
|
||||||
town->events.pop_front();
|
town->events.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO send only if changed
|
||||||
|
UpdateCastleEvents uce;
|
||||||
|
uce.town = town->id;
|
||||||
|
uce.events = town->events;
|
||||||
|
sendAndApply(&uce);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::complain( const std::string &problem )
|
bool CGameHandler::complain( const std::string &problem )
|
||||||
@ -6182,6 +6194,16 @@ void CGameHandler::removeObstacle(const CObstacleInstance &obstacle)
|
|||||||
sendAndApply(&obsRem);
|
sendAndApply(&obsRem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGameHandler::synchronizeArtifactHandlerLists()
|
||||||
|
{
|
||||||
|
UpdateArtHandlerLists uahl;
|
||||||
|
uahl.treasures = VLC->arth->treasures;
|
||||||
|
uahl.minors = VLC->arth->minors;
|
||||||
|
uahl.majors = VLC->arth->majors;
|
||||||
|
uahl.relics = VLC->arth->relics;
|
||||||
|
sendAndApply(&uahl);
|
||||||
|
}
|
||||||
|
|
||||||
CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
|
CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
|
||||||
{
|
{
|
||||||
heroWithDeadCommander = ObjectInstanceID();
|
heroWithDeadCommander = ObjectInstanceID();
|
||||||
|
@ -159,6 +159,7 @@ public:
|
|||||||
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE;
|
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE;
|
||||||
void removeArtifact(const ArtifactLocation &al) OVERRIDE;
|
void removeArtifact(const ArtifactLocation &al) OVERRIDE;
|
||||||
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE;
|
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE;
|
||||||
|
void synchronizeArtifactHandlerLists() OVERRIDE;
|
||||||
|
|
||||||
void showCompInfo(ShowInInfobox * comp) OVERRIDE;
|
void showCompInfo(ShowInInfobox * comp) OVERRIDE;
|
||||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE;
|
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) OVERRIDE;
|
||||||
|
@ -448,25 +448,26 @@ void CVCMIServer::loadGame()
|
|||||||
|
|
||||||
c >> clients >> fname; //how many clients should be connected - TODO: support more than one
|
c >> clients >> fname; //how many clients should be connected - TODO: support more than one
|
||||||
|
|
||||||
{
|
// {
|
||||||
char sig[8];
|
// char sig[8];
|
||||||
CMapHeader dum;
|
// CMapHeader dum;
|
||||||
StartInfo *si;
|
// StartInfo *si;
|
||||||
|
//
|
||||||
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::LIB_SAVEGAME)));
|
// CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::LIB_SAVEGAME)));
|
||||||
lf >> sig >> dum >> si;
|
// lf >> sig >> dum >> si;
|
||||||
tlog0 <<"Reading save signature"<<std::endl;
|
// tlog0 <<"Reading save signature"<<std::endl;
|
||||||
|
//
|
||||||
lf >> *VLC;
|
// lf >> *VLC;
|
||||||
tlog0 <<"Reading handlers"<<std::endl;
|
// tlog0 <<"Reading handlers"<<std::endl;
|
||||||
|
//
|
||||||
lf >> (gh.gs);
|
// lf >> (gh.gs);
|
||||||
c.addStdVecItems(gh.gs);
|
// c.addStdVecItems(gh.gs);
|
||||||
tlog0 <<"Reading gamestate"<<std::endl;
|
// tlog0 <<"Reading gamestate"<<std::endl;
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
{
|
||||||
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME)));
|
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME)));
|
||||||
|
gh.loadCommonState(lf);
|
||||||
lf >> gh;
|
lf >> gh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user