1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Next set of fixes, mostly for deserialization.

This commit is contained in:
Michał W. Urbańczyk 2011-02-22 09:47:25 +00:00
parent 1458cf64c2
commit a46ad0b7ef
16 changed files with 144 additions and 78 deletions

View File

@ -1713,14 +1713,14 @@ void CBattleInterface::show(SDL_Surface * to)
if(tacticsMode) if(tacticsMode)
{ {
btactNext->show(to); btactNext->showAll(to);
btactEnd->show(to); btactEnd->showAll(to);
} }
else else
{ {
console->show(to); console->showAll(to);
bConsoleUp->show(to); bConsoleUp->showAll(to);
bConsoleDown->show(to); bConsoleDown->showAll(to);
} }
//showing buttons //showing buttons

View File

@ -475,7 +475,7 @@ void CClient::serialize( Handler &h, const int version )
else else
nInt = new CPlayerInterface(pid); nInt = new CPlayerInterface(pid);
playerint[pid] = nInt; battleints[pid] = playerint[pid] = nInt;
nInt->init(callback); nInt->init(callback);
nInt->serialize(h, version); nInt->serialize(h, version);
} }

View File

@ -683,4 +683,6 @@ static inline ui32 read_unaligned_u32(const void *p)
#define OVERRIDE //is there any working counterpart? #define OVERRIDE //is there any working counterpart?
#endif #endif
#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving) deserializationFix();
#endif // __GLOBAL_H__ #endif // __GLOBAL_H__

View File

@ -92,6 +92,7 @@ public:
{ {
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
h & artType & id; h & artType & id;
BONUS_TREE_DESERIALIZATION_FIX
} }
static CArtifactInstance *createScroll(const CSpell *s); static CArtifactInstance *createScroll(const CSpell *s);
@ -136,6 +137,7 @@ public:
{ {
h & static_cast<CArtifactInstance&>(*this); h & static_cast<CArtifactInstance&>(*this);
h & constituentsInfo; h & constituentsInfo;
BONUS_TREE_DESERIALIZATION_FIX
} }
}; };

View File

@ -487,15 +487,11 @@ void CCreatureHandler::loadCreatures()
break; break;
CCreature *c = creatures[id]; CCreature *c = creatures[id];
c->level = lvl; c->level = lvl;
if(isbetw(lvl, 0, ARRAY_COUNT(creaturesOfLevel)))
c->attachTo(&creaturesOfLevel[lvl]);
else
c->attachTo(&creaturesOfLevel[0]);
} }
} }
BOOST_FOREACH(CBonusSystemNode &b, creaturesOfLevel) buildBonusTreeForTiers();
b.attachTo(&allCreatures);
ifs.close(); ifs.close();
ifs.clear(); ifs.clear();
@ -1110,3 +1106,21 @@ void CCreatureHandler::addBonusForAllCreatures(Bonus *b)
{ {
allCreatures.addNewBonus(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();
}

View File

@ -117,7 +117,10 @@ public:
std::vector<ui32> maxExpPerBattle; //%, tiers same as above std::vector<ui32> maxExpPerBattle; //%, tiers same as above
si8 expAfterUpgrade;//multiplier in % si8 expAfterUpgrade;//multiplier in %
void deserializationFix();
void loadCreatures(); void loadCreatures();
void buildBonusTreeForTiers();
void loadAnimationInfo(); void loadAnimationInfo();
void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i); void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i);
void loadStackExp(Bonus & b, BonusList & bl, std::string & src, int & it); 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) //TODO: should be optimized, not all these informations needs to be serialized (same for ccreature)
h & notUsedMonsters & creatures & nameToID & idToProjectile & idToProjectileSpin & factionToTurretCreature; h & notUsedMonsters & creatures & nameToID & idToProjectile & idToProjectileSpin & factionToTurretCreature;
h & stackBonuses & expRanks & maxExpPerBattle & expAfterUpgrade;
h & allCreatures; h & allCreatures;
h & creaturesOfLevel; h & creaturesOfLevel;
BONUS_TREE_DESERIALIZATION_FIX
} }
}; };

View File

@ -650,8 +650,12 @@ std::string CStackInstance::nodeName() const
void CStackInstance::deserializationFix() void CStackInstance::deserializationFix()
{ {
setType(type); const CCreature *backup = type;
setArmyObj(armyObj); type = NULL;
setType(backup);
const CArmedInstance *armyBackup = _armyObj;
_armyObj = NULL;
setArmyObj(armyBackup);
} }
CStackBasicDescriptor::CStackBasicDescriptor() CStackBasicDescriptor::CStackBasicDescriptor()

View File

@ -41,6 +41,7 @@ public:
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this); h & static_cast<CStackBasicDescriptor&>(*this);
h & _armyObj & experience; h & _armyObj & experience;
BONUS_TREE_DESERIALIZATION_FIX
} }
//overrides CBonusSystemNode //overrides CBonusSystemNode

View File

@ -2851,6 +2851,25 @@ bmap<ui32, ConstTransitivePtr<CGHeroInstance> > CGameState::unusedHeroesFromPool
} }
void CGameState::buildBonusSystemTree() 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<ui8, TeamState>::iterator k=teams.begin(); k!=teams.end(); ++k) for(std::map<ui8, TeamState>::iterator k=teams.begin(); k!=teams.end(); ++k)
{ {
@ -2863,33 +2882,16 @@ void CGameState::buildBonusSystemTree()
assert(p); assert(p);
p->attachTo(t); p->attachTo(t);
} }
}
} }
void CGameState::attachArmedObjects()
{
BOOST_FOREACH(CGObjectInstance *obj, map->objects) BOOST_FOREACH(CGObjectInstance *obj, map->objects)
{ {
if(CArmedInstance *armed = dynamic_cast<CArmedInstance*>(obj)) if(CArmedInstance *armed = dynamic_cast<CArmedInstance*>(obj))
{ armed->whatShouldBeAttached()->attachTo(armed->whereShouldBeAttached(this));
CBonusSystemNode *whereToAttach = armed->tempOwner < PLAYER_LIMIT
? getPlayer(armed->tempOwner)
: &globalEffects;
if(armed->ID == TOWNI_TYPE)
{
CGTownInstance *town = static_cast<CGTownInstance*>(armed);
town->townAndVis.attachTo(whereToAttach);
} }
else
armed->attachTo(whereToAttach);
}
}
BOOST_FOREACH(CGTownInstance *t, map->towns)
{
t->deserializationFix();
}
// CStackInstance <-> CCreature, CStackInstance <-> CArmedInstance, CArtifactInstance <-> CArtifact
// are provided on initializing / deserializing
} }
int3 CPath::startPos() const int3 CPath::startPos() const

View File

@ -145,6 +145,7 @@ public:
PlayerState(); PlayerState();
std::string nodeName() const OVERRIDE; std::string nodeName() const OVERRIDE;
void deserializationFix();
//override //override
//void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; //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); BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town);
void buildBonusSystemTree(); void buildBonusSystemTree();
void attachArmedObjects();
void buildGlobalTeamPlayerTree();
void deserializationFix();
bool isVisible(int3 pos, int player); bool isVisible(int3 pos, int player);
bool isVisible(const CGObjectInstance *obj, 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 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 <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> 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; h & villages & forts & capitols;
if(!h.saving) if(!h.saving)
{ {

View File

@ -26,6 +26,8 @@
#include <SDL_stdinc.h> #include <SDL_stdinc.h>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/algorithm/string/trim.hpp>
using namespace boost::assign; using namespace boost::assign;
/* /*
@ -1493,6 +1495,19 @@ void CGHeroInstance::deserializationFix()
attachTo(&speciality); 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() void CGDwelling::initObj()
{ {
switch(ID) switch(ID)
@ -2367,6 +2382,11 @@ bool CGTownInstance::armedGarrison() const
return stacksCount() || garrisonHero; return stacksCount() || garrisonHero;
} }
CBonusSystemNode * CGTownInstance::whatShouldBeAttached()
{
return &townAndVis;
}
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
{ {
if(visitors.find(h->id)==visitors.end()) if(visitors.find(h->id)==visitors.end())
@ -6586,6 +6606,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
b->val = 2-factions.size(); b->val = 2-factions.size();
b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factions.size() % b->val); //Troops of %d alignments %d 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 //-1 modifier for any Necropolis unit in army
const ui8 UNDEAD_MODIFIER_ID = -2; const ui8 UNDEAD_MODIFIER_ID = -2;
@ -6605,6 +6626,19 @@ void CArmedInstance::armyChanged()
updateMoraleBonusFromArmy(); 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 bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
{ {
switch(mode) switch(mode)

View File

@ -25,6 +25,7 @@
* *
*/ */
class CGameState;
class CArtifactInstance; class CArtifactInstance;
struct MetaString; struct MetaString;
struct BattleInfo; struct BattleInfo;
@ -231,9 +232,9 @@ public:
void armyChanged() OVERRIDE; 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 ??? int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ???
virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs);
virtual CBonusSystemNode *whatShouldBeAttached();
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
CArmedInstance(); CArmedInstance();
@ -319,7 +320,7 @@ public:
si32 movement; //remaining movement points si32 movement; //remaining movement points
ui8 sex; ui8 sex;
ui8 inTownGarrison; // if hero is in town garrison ui8 inTownGarrison; // if hero is in town garrison
const CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison ConstTransitivePtr<CGTownInstance> visitedTown; //set if hero is visiting town or in the town garrison
const CGBoat *boat; //set to CGBoat when sailing const CGBoat *boat; //set to CGBoat when sailing
@ -361,6 +362,7 @@ public:
& sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir; & sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir;
h & type & speciality; h & type & speciality;
BONUS_TREE_DESERIALIZATION_FIX
//visitied town pointer will be restored by map serialization method //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; virtual std::string nodeName() const OVERRIDE;
void deserializationFix(); void deserializationFix();
void setPropertyDer(ui8 what, ui32 val);//synchr void setPropertyDer(ui8 what, ui32 val);//synchr
@ -596,10 +598,12 @@ public:
(*i)->town = this; (*i)->town = this;
h & town & townAndVis; h & town & townAndVis;
BONUS_TREE_DESERIALIZATION_FIX
//garrison/visiting hero pointers will be restored in the map serialization //garrison/visiting hero pointers will be restored in the map serialization
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
virtual CBonusSystemNode *whatShouldBeAttached() OVERRIDE;
std::string nodeName() const OVERRIDE; std::string nodeName() const OVERRIDE;
void deserializationFix(); void deserializationFix();
void recreateBuildingsBonuses(); void recreateBuildingsBonuses();

View File

@ -944,6 +944,5 @@ public:
}; };
#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving) deserializationFix();
#endif // __CONNECTION_H__ #endif // __CONNECTION_H__

View File

@ -12,6 +12,7 @@
#include "CHeroHandler.h" #include "CHeroHandler.h"
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "BattleState.h" #include "BattleState.h"
#include "CArtHandler.h"
#define FOREACH_CONST_PARENT(pname) TCNodes lparents; getParents(lparents); BOOST_FOREACH(const CBonusSystemNode *pname, lparents) #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) #define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
@ -606,20 +607,21 @@ std::string Bonus::Description() const
return description; return description;
std::ostringstream str; std::ostringstream str;
if(val < 0) str << std::showpos << val << " ";
str << '-';
else if(val > 0)
str << '+';
str << val << " ";
switch(source) switch(source)
{ {
case ARTIFACT:
str << VLC->arth->artifacts[sid]->Name();
break;;
case SPELL_EFFECT:
str << VLC->spellh->spells[sid]->name;
break;
case CREATURE_ABILITY: case CREATURE_ABILITY:
str << VLC->creh->creatures[sid]->namePl; str << VLC->creh->creatures[sid]->namePl;
break; break;
case SECONDARY_SKILL: case SECONDARY_SKILL:
str << VLC->generaltexth->skillName[sid] << " secondary skill"; str << VLC->generaltexth->skillName[sid]/* << " secondary skill"*/;
break; 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 bool CCreatureTypeLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
{ {
const CCreature *c = retrieveCreature(&node); const CCreature *c = retrieveCreature(&node);
if(!c)
return true;
return c != creature && (!includeUpgrades || !creature->isMyUpgrade(c)); 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) //drop bonus if it's not our creature and (we dont check upgrades or its not our upgrade)
} }

View File

@ -246,15 +246,15 @@ DLL_EXPORT void RemoveObject::applyGs( CGameState *gs )
PlayerState *p = gs->getPlayer(h->tempOwner); PlayerState *p = gs->getPlayer(h->tempOwner);
gs->map->heroes -= h; gs->map->heroes -= h;
p->heroes -= h; p->heroes -= h;
h->detachFrom(p); h->detachFrom(h->whereShouldBeAttached(gs));
h->tempOwner = 255; //no one owns beaten hero h->tempOwner = 255; //no one owns beaten hero
if(CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown)) if(h->visitedTown)
{ {
if(h->inTownGarrison) if(h->inTownGarrison)
t->garrisonHero = NULL; h->visitedTown->garrisonHero = NULL;
else else
t->visitingHero = NULL; h->visitedTown->visitingHero = NULL;
h->visitedTown = NULL; h->visitedTown = NULL;
} }
@ -800,36 +800,27 @@ DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs )
if(what == ObjProperty::OWNER) if(what == ObjProperty::OWNER)
{ {
CBonusSystemNode *nodeToMove = NULL; if(CArmedInstance *cai = dynamic_cast<CArmedInstance *>(obj))
{
if(obj->ID == TOWNI_TYPE) if(obj->ID == TOWNI_TYPE)
{ {
CGTownInstance *t = static_cast<CGTownInstance*>(obj); CGTownInstance *t = static_cast<CGTownInstance*>(obj);
nodeToMove = &t->townAndVis;
if(t->tempOwner < PLAYER_LIMIT) if(t->tempOwner < PLAYER_LIMIT)
gs->getPlayer(t->tempOwner)->towns -= t; gs->getPlayer(t->tempOwner)->towns -= t;
if(val < PLAYER_LIMIT) if(val < PLAYER_LIMIT)
gs->getPlayer(val)->towns.push_back(t); gs->getPlayer(val)->towns.push_back(t);
} }
if(CArmedInstance *cai = dynamic_cast<CArmedInstance *>(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);
}
}
CBonusSystemNode *nodeToMove = cai->whatShouldBeAttached();
nodeToMove->detachFrom(cai->whereShouldBeAttached(gs));
obj->setProperty(what,val); obj->setProperty(what,val);
nodeToMove->attachTo(cai->whereShouldBeAttached(gs));
}
}
else
{
obj->setProperty(what,val);
}
} }
DLL_EXPORT void SetHoverName::applyGs( CGameState *gs ) DLL_EXPORT void SetHoverName::applyGs( CGameState *gs )

View File

@ -2777,7 +2777,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
bool CGameHandler::buyArtifact( ui32 hid, si32 aid ) bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
{ {
CGHeroInstance *hero = gs->getHero(hid); CGHeroInstance *hero = gs->getHero(hid);
CGTownInstance *town = const_cast<CGTownInstance*>(hero->visitedTown); CGTownInstance *town = hero->visitedTown;
if(aid==0) //spellbook if(aid==0) //spellbook
{ {
if(!vstd::contains(town->builtBuildings,si32(0)) && complain("Cannot buy a spellbook, no mage guild in the town!") if(!vstd::contains(town->builtBuildings,si32(0)) && complain("Cannot buy a spellbook, no mage guild in the town!")