From a46ad0b7ef0ab644e2068755d0a8798a40273e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Tue, 22 Feb 2011 09:47:25 +0000 Subject: [PATCH] Next set of fixes, mostly for deserialization. --- client/CBattleInterface.cpp | 10 ++++---- client/Client.cpp | 2 +- global.h | 2 ++ lib/CArtHandler.h | 2 ++ lib/CCreatureHandler.cpp | 26 +++++++++++++++----- lib/CCreatureHandler.h | 5 ++++ lib/CCreatureSet.cpp | 8 ++++-- lib/CCreatureSet.h | 1 + lib/CGameState.cpp | 44 +++++++++++++++++---------------- lib/CGameState.h | 6 ++++- lib/CObjectHandler.cpp | 34 +++++++++++++++++++++++++ lib/CObjectHandler.h | 12 ++++++--- lib/Connection.h | 1 - lib/HeroBonus.cpp | 18 ++++++++------ lib/NetPacksLib.cpp | 49 +++++++++++++++---------------------- server/CGameHandler.cpp | 2 +- 16 files changed, 144 insertions(+), 78 deletions(-) diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index cf3144081..6f6163c4a 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -1713,14 +1713,14 @@ void CBattleInterface::show(SDL_Surface * to) if(tacticsMode) { - btactNext->show(to); - btactEnd->show(to); + btactNext->showAll(to); + btactEnd->showAll(to); } else { - console->show(to); - bConsoleUp->show(to); - bConsoleDown->show(to); + console->showAll(to); + bConsoleUp->showAll(to); + bConsoleDown->showAll(to); } //showing buttons diff --git a/client/Client.cpp b/client/Client.cpp index 7521cb34b..76676da47 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -475,7 +475,7 @@ void CClient::serialize( Handler &h, const int version ) else nInt = new CPlayerInterface(pid); - playerint[pid] = nInt; + battleints[pid] = playerint[pid] = nInt; nInt->init(callback); nInt->serialize(h, version); } diff --git a/global.h b/global.h index d0f2a70dc..dea0ba034 100644 --- a/global.h +++ b/global.h @@ -683,4 +683,6 @@ static inline ui32 read_unaligned_u32(const void *p) #define OVERRIDE //is there any working counterpart? #endif +#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving) deserializationFix(); + #endif // __GLOBAL_H__ diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 5c3fadb4f..1ad1abd09 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -92,6 +92,7 @@ public: { h & static_cast(*this); h & artType & id; + BONUS_TREE_DESERIALIZATION_FIX } static CArtifactInstance *createScroll(const CSpell *s); @@ -136,6 +137,7 @@ public: { h & static_cast(*this); h & constituentsInfo; + BONUS_TREE_DESERIALIZATION_FIX } }; diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 7bbc1ca38..ea0947baf 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -487,15 +487,11 @@ void CCreatureHandler::loadCreatures() break; CCreature *c = creatures[id]; c->level = lvl; - if(isbetw(lvl, 0, ARRAY_COUNT(creaturesOfLevel))) - c->attachTo(&creaturesOfLevel[lvl]); - else - c->attachTo(&creaturesOfLevel[0]); } } - BOOST_FOREACH(CBonusSystemNode &b, creaturesOfLevel) - b.attachTo(&allCreatures); + buildBonusTreeForTiers(); + ifs.close(); ifs.clear(); @@ -1109,4 +1105,22 @@ void CCreatureHandler::addBonusForTier(int tier, Bonus *b) void CCreatureHandler::addBonusForAllCreatures(Bonus *b) { allCreatures.addNewBonus(b); +} + +void CCreatureHandler::buildBonusTreeForTiers() +{ + BOOST_FOREACH(CCreature *c, creatures) + { + if(isbetw(c->level, 0, ARRAY_COUNT(creaturesOfLevel))) + c->attachTo(&creaturesOfLevel[c->level]); + else + c->attachTo(&creaturesOfLevel[0]); + } + BOOST_FOREACH(CBonusSystemNode &b, creaturesOfLevel) + b.attachTo(&allCreatures); +} + +void CCreatureHandler::deserializationFix() +{ + buildBonusTreeForTiers(); } \ No newline at end of file diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 2a0435e16..6b22d5841 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -117,7 +117,10 @@ public: std::vector maxExpPerBattle; //%, tiers same as above si8 expAfterUpgrade;//multiplier in % + + void deserializationFix(); void loadCreatures(); + void buildBonusTreeForTiers(); void loadAnimationInfo(); void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i); void loadStackExp(Bonus & b, BonusList & bl, std::string & src, int & it); @@ -138,8 +141,10 @@ public: { //TODO: should be optimized, not all these informations needs to be serialized (same for ccreature) h & notUsedMonsters & creatures & nameToID & idToProjectile & idToProjectileSpin & factionToTurretCreature; + h & stackBonuses & expRanks & maxExpPerBattle & expAfterUpgrade; h & allCreatures; h & creaturesOfLevel; + BONUS_TREE_DESERIALIZATION_FIX } }; diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 90cab871b..93932d5fe 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -650,8 +650,12 @@ std::string CStackInstance::nodeName() const void CStackInstance::deserializationFix() { - setType(type); - setArmyObj(armyObj); + const CCreature *backup = type; + type = NULL; + setType(backup); + const CArmedInstance *armyBackup = _armyObj; + _armyObj = NULL; + setArmyObj(armyBackup); } CStackBasicDescriptor::CStackBasicDescriptor() diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 05309ca63..76c50b66f 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -41,6 +41,7 @@ public: h & static_cast(*this); h & static_cast(*this); h & _armyObj & experience; + BONUS_TREE_DESERIALIZATION_FIX } //overrides CBonusSystemNode diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index c0443f74c..82a3674e4 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -2851,6 +2851,25 @@ bmap > CGameState::unusedHeroesFromPool } void CGameState::buildBonusSystemTree() +{ + buildGlobalTeamPlayerTree(); + attachArmedObjects(); + + BOOST_FOREACH(CGTownInstance *t, map->towns) + { + t->deserializationFix(); + } + // CStackInstance <-> CCreature, CStackInstance <-> CArmedInstance, CArtifactInstance <-> CArtifact + // are provided on initializing / deserializing +} + +void CGameState::deserializationFix() +{ + buildGlobalTeamPlayerTree(); + attachArmedObjects(); +} + +void CGameState::buildGlobalTeamPlayerTree() { for(std::map::iterator k=teams.begin(); k!=teams.end(); ++k) { @@ -2863,33 +2882,16 @@ void CGameState::buildBonusSystemTree() assert(p); p->attachTo(t); } - } +} +void CGameState::attachArmedObjects() +{ BOOST_FOREACH(CGObjectInstance *obj, map->objects) { if(CArmedInstance *armed = dynamic_cast(obj)) - { - CBonusSystemNode *whereToAttach = armed->tempOwner < PLAYER_LIMIT - ? getPlayer(armed->tempOwner) - : &globalEffects; - - if(armed->ID == TOWNI_TYPE) - { - CGTownInstance *town = static_cast(armed); - town->townAndVis.attachTo(whereToAttach); - } - else - armed->attachTo(whereToAttach); - } + armed->whatShouldBeAttached()->attachTo(armed->whereShouldBeAttached(this)); } - - BOOST_FOREACH(CGTownInstance *t, map->towns) - { - t->deserializationFix(); - } - // CStackInstance <-> CCreature, CStackInstance <-> CArmedInstance, CArtifactInstance <-> CArtifact - // are provided on initializing / deserializing } int3 CPath::startPos() const diff --git a/lib/CGameState.h b/lib/CGameState.h index fedf38612..a706d48df 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -145,6 +145,7 @@ public: PlayerState(); std::string nodeName() const OVERRIDE; + void deserializationFix(); //override //void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; @@ -350,6 +351,9 @@ public: BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town); void buildBonusSystemTree(); + void attachArmedObjects(); + void buildGlobalTeamPlayerTree(); + void deserializationFix(); bool isVisible(int3 pos, int player); bool isVisible(const CGObjectInstance *obj, int player); @@ -361,7 +365,7 @@ public: int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month template void serialize(Handler &h, const int version) { - h & scenarioOps & seed & currentPlayer & day & map & players & teams & hpool & globalEffects & campaign; + h & scenarioOps & initialOpts & seed & currentPlayer & day & map & players & teams & hpool & globalEffects & campaign; h & villages & forts & capitols; if(!h.saving) { diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 6c6a3da0f..d42d1d538 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -26,6 +26,8 @@ #include #include #include +#include + using namespace boost::assign; /* @@ -1493,6 +1495,19 @@ void CGHeroInstance::deserializationFix() attachTo(&speciality); } +CBonusSystemNode * CGHeroInstance::whereShouldBeAttached(CGameState *gs) +{ + if(visitedTown) + { + if(inTownGarrison) + return visitedTown; + else + return &visitedTown->townAndVis; + } + else + return CArmedInstance::whereShouldBeAttached(gs); +} + void CGDwelling::initObj() { switch(ID) @@ -2367,6 +2382,11 @@ bool CGTownInstance::armedGarrison() const return stacksCount() || garrisonHero; } +CBonusSystemNode * CGTownInstance::whatShouldBeAttached() +{ + return &townAndVis; +} + void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const { if(visitors.find(h->id)==visitors.end()) @@ -6586,6 +6606,7 @@ void CArmedInstance::updateMoraleBonusFromArmy() b->val = 2-factions.size(); b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factions.size() % b->val); //Troops of %d alignments %d } + boost::algorithm::trim(b->description); //-1 modifier for any Necropolis unit in army const ui8 UNDEAD_MODIFIER_ID = -2; @@ -6605,6 +6626,19 @@ void CArmedInstance::armyChanged() updateMoraleBonusFromArmy(); } +CBonusSystemNode * CArmedInstance::whereShouldBeAttached(CGameState *gs) +{ + if(tempOwner < PLAYER_LIMIT) + return gs->getPlayer(tempOwner); + else + return &gs->globalEffects; +} + +CBonusSystemNode * CArmedInstance::whatShouldBeAttached() +{ + return this; +} + bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const { switch(mode) diff --git a/lib/CObjectHandler.h b/lib/CObjectHandler.h index 82db6717d..77aa8f377 100644 --- a/lib/CObjectHandler.h +++ b/lib/CObjectHandler.h @@ -25,6 +25,7 @@ * */ +class CGameState; class CArtifactInstance; struct MetaString; struct BattleInfo; @@ -231,9 +232,9 @@ public: void armyChanged() OVERRIDE; ////////////////////////////////////////////////////////////////////////// - //void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; - //void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const; int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ??? + virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs); + virtual CBonusSystemNode *whatShouldBeAttached(); ////////////////////////////////////////////////////////////////////////// CArmedInstance(); @@ -319,7 +320,7 @@ public: si32 movement; //remaining movement points ui8 sex; ui8 inTownGarrison; // if hero is in town garrison - const CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison + ConstTransitivePtr visitedTown; //set if hero is visiting town or in the town garrison const CGBoat *boat; //set to CGBoat when sailing @@ -361,6 +362,7 @@ public: & sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir; h & type & speciality; + BONUS_TREE_DESERIALIZATION_FIX //visitied town pointer will be restored by map serialization method } ////////////////////////////////////////////////////////////////////////// @@ -433,7 +435,7 @@ public: ////////////////////////////////////////////////////////////////////////// - + virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs) OVERRIDE; virtual std::string nodeName() const OVERRIDE; void deserializationFix(); void setPropertyDer(ui8 what, ui32 val);//synchr @@ -596,10 +598,12 @@ public: (*i)->town = this; h & town & townAndVis; + BONUS_TREE_DESERIALIZATION_FIX //garrison/visiting hero pointers will be restored in the map serialization } ////////////////////////////////////////////////////////////////////////// + virtual CBonusSystemNode *whatShouldBeAttached() OVERRIDE; std::string nodeName() const OVERRIDE; void deserializationFix(); void recreateBuildingsBonuses(); diff --git a/lib/Connection.h b/lib/Connection.h index 037e302b1..30fdbdc64 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -944,6 +944,5 @@ public: }; -#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving) deserializationFix(); #endif // __CONNECTION_H__ diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index e3a811921..680412621 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -12,6 +12,7 @@ #include "CHeroHandler.h" #include "CGeneralTextHandler.h" #include "BattleState.h" +#include "CArtHandler.h" #define FOREACH_CONST_PARENT(pname) TCNodes lparents; getParents(lparents); BOOST_FOREACH(const CBonusSystemNode *pname, lparents) #define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents) @@ -606,20 +607,21 @@ std::string Bonus::Description() const return description; std::ostringstream str; - if(val < 0) - str << '-'; - else if(val > 0) - str << '+'; - - str << val << " "; + str << std::showpos << val << " "; switch(source) { + case ARTIFACT: + str << VLC->arth->artifacts[sid]->Name(); + break;; + case SPELL_EFFECT: + str << VLC->spellh->spells[sid]->name; + break; case CREATURE_ABILITY: str << VLC->creh->creatures[sid]->namePl; break; case SECONDARY_SKILL: - str << VLC->generaltexth->skillName[sid] << " secondary skill"; + str << VLC->generaltexth->skillName[sid]/* << " secondary skill"*/; break; } @@ -824,6 +826,8 @@ bool ILimiter::limit(const Bonus *b, const CBonusSystemNode &node) const /*retur bool CCreatureTypeLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const { const CCreature *c = retrieveCreature(&node); + if(!c) + return true; return c != creature && (!includeUpgrades || !creature->isMyUpgrade(c)); //drop bonus if it's not our creature and (we dont check upgrades or its not our upgrade) } diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index e52daea90..984534e6d 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -246,15 +246,15 @@ DLL_EXPORT void RemoveObject::applyGs( CGameState *gs ) PlayerState *p = gs->getPlayer(h->tempOwner); gs->map->heroes -= h; p->heroes -= h; - h->detachFrom(p); + h->detachFrom(h->whereShouldBeAttached(gs)); h->tempOwner = 255; //no one owns beaten hero - if(CGTownInstance *t = const_cast(h->visitedTown)) + if(h->visitedTown) { if(h->inTownGarrison) - t->garrisonHero = NULL; + h->visitedTown->garrisonHero = NULL; else - t->visitingHero = NULL; + h->visitedTown->visitingHero = NULL; h->visitedTown = NULL; } @@ -800,36 +800,27 @@ DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs ) if(what == ObjProperty::OWNER) { - CBonusSystemNode *nodeToMove = NULL; - if(obj->ID == TOWNI_TYPE) - { - CGTownInstance *t = static_cast(obj); - nodeToMove = &t->townAndVis; - if(t->tempOwner < PLAYER_LIMIT) - gs->getPlayer(t->tempOwner)->towns -= t; - - if(val < PLAYER_LIMIT) - gs->getPlayer(val)->towns.push_back(t); - } if(CArmedInstance *cai = dynamic_cast(obj)) { - if(!nodeToMove) - nodeToMove = cai; - - if(obj->tempOwner < PLAYER_LIMIT) - nodeToMove->detachFrom(gs->getPlayer(obj->tempOwner)); - else - nodeToMove->detachFrom(&gs->globalEffects); - - if(val < PLAYER_LIMIT) - nodeToMove->attachTo(gs->getPlayer(val)); - else - nodeToMove->attachTo(&gs->globalEffects); + if(obj->ID == TOWNI_TYPE) + { + CGTownInstance *t = static_cast(obj); + if(t->tempOwner < PLAYER_LIMIT) + gs->getPlayer(t->tempOwner)->towns -= t; + if(val < PLAYER_LIMIT) + gs->getPlayer(val)->towns.push_back(t); + } + CBonusSystemNode *nodeToMove = cai->whatShouldBeAttached(); + nodeToMove->detachFrom(cai->whereShouldBeAttached(gs)); + obj->setProperty(what,val); + nodeToMove->attachTo(cai->whereShouldBeAttached(gs)); } } - - obj->setProperty(what,val); + else + { + obj->setProperty(what,val); + } } DLL_EXPORT void SetHoverName::applyGs( CGameState *gs ) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 3348a14d3..8f867ac76 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2777,7 +2777,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem bool CGameHandler::buyArtifact( ui32 hid, si32 aid ) { CGHeroInstance *hero = gs->getHero(hid); - CGTownInstance *town = const_cast(hero->visitedTown); + CGTownInstance *town = hero->visitedTown; if(aid==0) //spellbook { if(!vstd::contains(town->builtBuildings,si32(0)) && complain("Cannot buy a spellbook, no mage guild in the town!")