瀏覽代碼

Next set of fixes, mostly for deserialization.

Michał W. Urbańczyk 14 年之前
父節點
當前提交
a46ad0b7ef

+ 5 - 5
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

+ 1 - 1
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);
 		}

+ 2 - 0
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__

+ 2 - 0
lib/CArtHandler.h

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

+ 20 - 6
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();
 }

+ 5 - 0
lib/CCreatureHandler.h

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

+ 6 - 2
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()

+ 1 - 0
lib/CCreatureSet.h

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

+ 23 - 21
lib/CGameState.cpp

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

+ 5 - 1
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 <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)
 		{

+ 34 - 0
lib/CObjectHandler.cpp

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

+ 8 - 4
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<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();

+ 0 - 1
lib/Connection.h

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

+ 11 - 7
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)
 }

+ 20 - 29
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<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(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);
+			if(obj->ID == TOWNI_TYPE)
+			{
+				CGTownInstance *t = static_cast<CGTownInstance*>(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 )

+ 1 - 1
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<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!")