1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +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)
{
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

View File

@ -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);
}

View File

@ -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__

View File

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

View File

@ -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();
@ -1110,3 +1106,21 @@ 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();
}

View File

@ -117,7 +117,10 @@ public:
std::vector<ui32> 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
}
};

View File

@ -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()

View File

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

View File

@ -2851,6 +2851,25 @@ bmap<ui32, ConstTransitivePtr<CGHeroInstance> > 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<ui8, TeamState>::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<CArmedInstance*>(obj))
{
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);
armed->whatShouldBeAttached()->attachTo(armed->whereShouldBeAttached(this));
}
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

View File

@ -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 <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;
if(!h.saving)
{

View File

@ -26,6 +26,8 @@
#include <SDL_stdinc.h>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string/trim.hpp>
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)

View File

@ -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<CGTownInstance> 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();

View File

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

View File

@ -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)
}

View File

@ -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<CGTownInstance *>(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(CArmedInstance *cai = dynamic_cast<CArmedInstance *>(obj))
{
if(obj->ID == TOWNI_TYPE)
{
CGTownInstance *t = static_cast<CGTownInstance*>(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<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);
nodeToMove->attachTo(cai->whereShouldBeAttached(gs));
}
}
else
{
obj->setProperty(what,val);
}
}
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 )
{
CGHeroInstance *hero = gs->getHero(hid);
CGTownInstance *town = const_cast<CGTownInstance*>(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!")