瀏覽代碼

Statue of Legion is finally functional.
You can see my attempt to create very generic handling of global effects, but I abandoned it since no other items might actually use it.

However, Statue's constituents are buggy, so may be assembling & dissasembling them. Most likely this issue is general.

DjWarmonger 15 年之前
父節點
當前提交
717141ab0b
共有 7 個文件被更改,包括 67 次插入23 次删除
  1. 6 2
      client/CCastleInterface.cpp
  2. 1 1
      hch/CArtHandler.cpp
  3. 14 6
      hch/CObjectHandler.cpp
  4. 1 0
      hch/CObjectHandler.h
  5. 19 9
      lib/CGameState.cpp
  6. 12 4
      lib/HeroBonus.cpp
  7. 14 1
      lib/HeroBonus.h

+ 6 - 2
client/CCastleInterface.cpp

@@ -1138,7 +1138,8 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 	if(down)
 	{
 		CCastleInterface * ci=LOCPLINT->castleInt;
-		std::set<si32> bld =ci->town->builtBuildings;
+		const CGTownInstance * town = ci->town;
+		std::set<si32> bld = ci->town->builtBuildings;
 		int summ=0, cnt=0;
 		std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number
 		boost::algorithm::replace_first(descr,"%s",CGI->creh->creatures[crid]->nameSing);
@@ -1156,9 +1157,12 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 			else if ( bld.find(8)!=bld.end())//else if citadel+50% to basic
 				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][8]->Name()+" %+d",descr,summ/2);
 
-			summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr,
+			summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr, //plague
 				summ * CGI->creh->creatures[crid]->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100);
 
+			summ+=AddToString(CGI->generaltexth->artifNames[133] + " %+d",descr,
+				summ * ci->town->valOfGlobalBonuses(Bonus::CREATURE_GROWTH_PERCENT, -1)/100); //Statue of Legion 
+
 			if(ci->town->town->hordeLvl[0]==level)//horde, x to summ
 			if((bld.find(18)!=bld.end()) || (bld.find(19)!=bld.end()))
 				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][18]->Name()+" %+d",descr,

+ 1 - 1
hch/CArtHandler.cpp

@@ -673,7 +673,7 @@ void CArtHandler::addBonuses()
 	giveArtBonus(132, Bonus::OPENING_BATTLE_SPELL, 50, 52); // Misfortune
 
 	// Statue of Legion - gives only 50% growth
-	giveArtBonus(133, Bonus::CREATURE_GROWTH_PERCENT, 50);
+	giveArtBonus(133, Bonus::CREATURE_GROWTH_PERCENT, 50, -1);
 
 	//Power of the Dragon Father
 	giveArtBonus(134, Bonus::LEVEL_SPELL_IMMUNITY, 4);

+ 14 - 6
hch/CObjectHandler.cpp

@@ -1493,11 +1493,12 @@ int CGHeroInstance::getSpellCost(const CSpell *sp) const
 
 void CGHeroInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
 {
-	CArmedInstance::getParents(out, root);// 	if(visitedTown && source != this && source != visitedTown)
-// 		out.insert(visitedTown);
+	CArmedInstance::getParents(out, root);
 
 	if((root == this || contains(static_cast<const CStackInstance *>(root))) &&  visitedTown)
-		out.insert(visitedTown);
+	{
+			out.insert(visitedTown);
+	}
 
 	for (std::map<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
 		out.insert(VLC->arth->artifacts[i->second]);
@@ -1513,7 +1514,8 @@ void CGHeroInstance::pushPrimSkill(int which, int val)
 void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
 {
 #define FOREACH_OWNER_TOWN(town) if(const PlayerState *p = cb->getPlayerState(tempOwner)) BOOST_FOREACH(const CGTownInstance *town, p->towns)
-	CArmedInstance::getBonuses(out, selector, root);
+
+	CArmedInstance::getBonuses(out, selector, root); ///that's not part of macro!
 
 	//TODO eliminate by moving secondary skills effects to bonus system
 	if(Selector::matchesType(selector, Bonus::LUCK))
@@ -6538,10 +6540,10 @@ void CArmedInstance::randomizeArmy(int type)
 void CArmedInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
 {
 	const PlayerState *p = cb->getPlayerState(tempOwner);
-	if(p)
+	if (p && p != root) 
 		out.insert(p); //hero always inherits bonuses from player
 
-	out.insert(&cb->gameState()->globalEffects); //global effect are always active I believe
+	out.insert(&cb->gameState()->globalEffects); //global effects are always active I believe
 
 	if(battle)
 		out.insert(battle);
@@ -6606,6 +6608,12 @@ void CArmedInstance::getBonuses(BonusList &out, const CSelector &selector, const
 	}
 }
 
+int CArmedInstance::valOfGlobalBonuses(Bonus::BonusType type, int subtype) const
+{
+	//if (tempOwner != NEUTRAL_PLAYER)
+	return cb->gameState()->players[tempOwner].valOfBonuses(type, subtype);
+}
+
 bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
 {
 	switch(mode)

+ 1 - 0
hch/CObjectHandler.h

@@ -228,6 +228,7 @@ public:
 	//////////////////////////////////////////////////////////////////////////
 	void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
 	void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const;
+	int valOfGlobalBonuses(Bonus::BonusType type, int subtype) const; //used only for castle interface
 	//////////////////////////////////////////////////////////////////////////
 
 	CArmedInstance();

+ 19 - 9
lib/CGameState.cpp

@@ -4479,24 +4479,34 @@ PlayerState::PlayerState()
 
 void PlayerState::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
 {
-	/*
-	for (std::vector<CGHeroInstance *>::const_iterator it = heroes.begin(); it != heroes.end(); ++it)
+	//an issue - this way we get quadratic complexity at the moment all objects are called
+	for (std::vector<CGHeroInstance *>::const_iterator it = heroes.begin(); it != heroes.end(); it++)
 	{
-		if (*it != root)
-			(*it)->getParents(out, root);
+		out.insert(*it);
 	}
-	for (std::vector<CGTownInstance *>::const_iterator it = towns.begin(); it != towns.end(); ++it)
+	/*
+	for (std::vector<CGTownInstance *>::const_iterator it = towns.begin(); it != towns.end(); it++)
 	{
-		if (*it != root)
-			(*it)->getParents(out, root);
+			out.insert(*it);
 	}
 	*/
-	//TODO - dwellings
+	if (root != this) 
+	{
+		out.erase(out.find(root)); //don't use yourself
+		root = this; //get all nodes ONLY once - see Armed Instance::getParents
+	}
 }
 
 void PlayerState::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
 {
-	CBonusSystemNode::getBonuses(out, selector, root);
+	if (Selector::matchesType(selector, Bonus::CREATURE_GROWTH_PERCENT))
+		CBonusSystemNode::getBonuses(out, selector, this); //no recursive loops for PlayerState
+	/* //universal solution
+	if (root == this) // called directly
+		CBonusSystemNode::getBonuses(out, selector, this); //no recursive loops for PlayerState
+	else //unused yet
+		CBonusSystemNode::getBonuses(out, selector && Selector::effectRange(Bonus::GLOBAL), root); //only very specific bonuses can be propagated this way
+	*/
 }
 
 InfoAboutHero::InfoAboutHero()

+ 12 - 4
lib/HeroBonus.cpp

@@ -223,9 +223,13 @@ void CBonusSystemNode::getParents(TNodes &out, const CBonusSystemNode *root /*=
 
 void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
 {
-	bonuses.getBonuses(out, selector);
-	FOREACH_CONST_PARENT(p, root ? root : this)
+	//FOREACH_CONST_PARENT(p, root ? root : this) //unwinded macro
+	TCNodes parents;
+	getParents(parents, root ? root : this);
+	BOOST_FOREACH(const CBonusSystemNode *p, parents)
 		p->getBonuses(out, selector, root ? root : this);
+
+	bonuses.getBonuses(out, selector);
 	
 	if(!root)
 		out.limit(*this);
@@ -240,10 +244,14 @@ BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CBonusSy
 
 void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
 {
-	bonuses.getBonuses(out, selector, limit);
-	FOREACH_CONST_PARENT(p, root ? root : this)
+	//FOREACH_CONST_PARENT(p, root ? root : this) //unwinded macro
+	TCNodes parents;
+	getParents(parents, root ? root : this);
+	BOOST_FOREACH(const CBonusSystemNode *p, parents)
 		p->getBonuses(out, selector, limit, root ? root : this);
 
+	bonuses.getBonuses(out, selector, limit);
+
 	if(!root)
 		out.limit(*this);
 }

+ 14 - 1
lib/HeroBonus.h

@@ -201,7 +201,8 @@ struct DLL_EXPORT Bonus
 		NO_LIMIT = 0, 
 		ONLY_DISTANCE_FIGHT=1, ONLY_MELEE_FIGHT, //used to mark bonuses for attack/defense primary skills from spells like Precision (distance only)
 		ONLY_ALLIED_ARMY, ONLY_ENEMY_ARMY,
-		PLAYR_HEROES
+		PLAYR_HEROES,
+		GLOBAL //Statue of Legion etc.
 	};
 
 	enum ValueType
@@ -293,6 +294,18 @@ struct DLL_EXPORT Bonus
 	std::string Description() const;
 };
 
+struct DLL_EXPORT stackExperience : public Bonus
+{
+	std::vector<ui32> expBonuses; // variations for levels 1-10, copied to val field;
+	bool enable; //if true - turns ability on / off for zero value
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<Bonus&>(this);
+		h & expBonuses & enable;
+	}
+};
+
 DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
 
 class BonusList : public std::list<Bonus>