Răsfoiți Sursa

Fixed #668 and #718.

Hero is now properly attached to his special.

Compile fix for ERM Parser.
DjWarmonger 14 ani în urmă
părinte
comite
7e9033c44f

+ 1 - 1
config/spell_info.txt

@@ -47,7 +47,7 @@
 44 1 25 0 0 0 X
 45 -1 56 0 0 0 X
 46 1 54 0 0 0 X
-47 -1 14 0 0 0 X
+47 -1 14 0 0 0 0
 48 1 0 0 0 0 X
 49 1 20 0 0 0 X
 50 -1 30 0 0 0 X

+ 1 - 39
lib/BattleState.cpp

@@ -2011,34 +2011,8 @@ const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const
 }
 
 void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
-{
+{	
 	si32 power = VLC->spellh->spells[sse.sid]->powers[sse.val];
-	//why, why, WHY this code is here?!?
-// 	Bonus * bonus = getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, sse.id));
-// 	if (bonus)
-// 	{
-// 	 	switch(bonus->additionalInfo)
-// 	 	{
-// 	 		case 0: //normal
-// 	 			switch(type->level)
-// 	 			{
-// 	 				case 1: case 2:
-// 	 					power += 3; //it doesn't necessarily make sense for some spells, use it wisely
-// 	 				break;
-// 	 				case 3: case 4:
-// 	 					power += 2;
-// 	 				break;
-// 	 				case 5: case 6:
-// 	 					power += 1;
-// 	 				break;
-// 	 			}
-// 	 		break;
-// 	 		case 1: //only Coronius as yet
-// 	 			power = std::max(5 - type->level, 0);
-// 	 		break;
-// 	 	}
-// 	}
-	 
 	switch(sse.sid)
 	{
 	case 27: //shield 
@@ -2075,13 +2049,6 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
 	 	sf.back().sid = sse.sid;
 	 	break;
 	case 41: //bless
-// 	 	if (hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, 41)) //TODO: better handling of bonus percentages
-// 	 	{
-// 	 		int damagePercent = dynamic_cast<const CGHeroInstance*>(armyObj)->level * valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / type->level;
-// 	 		sf.push_back(featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, sse.turnsRemain));
-// 	 		sf.back().sid = sse.sid;
-// 	 		sf.back().valType = Bonus::PERCENT_TO_ALL;
-// 	 	}
 	 	sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain));
 	 	sf.back().sid = sse.sid;
 	 	break;
@@ -2143,11 +2110,6 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
 	 	sf.back().sid = sse.sid;
 	 	break;
 	case 55: //slayer
-// 	 	if (bonus) //Coronius
-// 	 	{
-// 	 		sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain));
-// 	 		sf.back().sid = sse.sid;
-// 	 	}
 	 	sf.push_back(featureGenerator(Bonus::SLAYER, 0, sse.val, sse.turnsRemain));
 	 	sf.back().sid = sse.sid;
 	 	break;

+ 1 - 1
lib/CCreatureSet.cpp

@@ -583,7 +583,7 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
 					boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
 					break;
 				case Bonus::SPELL_AFTER_ATTACK:
-					boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->additionalInfo));
+					boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->additionalInfo % 1000));
 					boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name);
 					break;
 				default:

+ 1 - 0
lib/CObjectHandler.cpp

@@ -735,6 +735,7 @@ CGHeroInstance::CGHeroInstance()
 	boat = NULL;
 	secSkills.push_back(std::make_pair(-1, -1));
 	speciality.nodeType = CBonusSystemNode::SPECIALITY;
+	attachTo(&speciality); //do we evert need to detach it?
 }
 
 void CGHeroInstance::initHero(int SUBID)

+ 1 - 0
lib/CSpellHandler.cpp

@@ -291,6 +291,7 @@ void CSpellHandler::loadSpells()
 		nsp->mainEffectAnim = -1;
 		spells.push_back(nsp);
 	}
+	boost::replace_first (spells[47]->attributes, "2", ""); // disrupting ray will now affect single creature
 	//loading of additional spell traits
 	std::ifstream ast;
 	ast.open(DATA_DIR "/config/spell_info.txt", std::ios::binary);

+ 1 - 1
lib/ERMParser.cpp

@@ -559,6 +559,6 @@ void ERMParser::repairEncoding( char * str, int len ) const
 #else
 
 ERMParser::ERMParser(std::string file){}
-std::vector<ERM::TLine> ERMParser::parseFile() {}
+std::vector<ERM::TLine> ERMParser::parseFile() {std::vector<ERM::TLine> dummy; return dummy;} //compile fix
 
 #endif

+ 2 - 1
lib/NetPacks.h

@@ -1364,9 +1364,10 @@ struct SetStackEffect : public CPackForClient //3010
 
 	std::vector<ui32> stacks; //affected stacks (IDs)
 	std::vector<Bonus> effect; //bonuses to apply
+	std::vector<std::pair<ui32, Bonus>> uniqueBonuses; //bonuses per single stack
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & stacks & effect;
+		h & stacks & effect & uniqueBonuses;
 	}
 };
 

+ 26 - 2
lib/NetPacksLib.cpp

@@ -1121,17 +1121,27 @@ void actualizeEffect(CStack * s, const std::vector<Bonus> & ef)
 			}
 		}
 	}
-
+}
+void actualizeEffect(CStack * s, const Bonus & ef)
+{
+	BOOST_FOREACH(Bonus *stackBonus, s->bonuses) //TODO: optimize
+	{
+		if(stackBonus->source == Bonus::SPELL_EFFECT && stackBonus->type == ef.type && stackBonus->subtype == ef.subtype)
+		{
+			stackBonus->turnsRemain = std::max(stackBonus->turnsRemain, ef.turnsRemain);
+		}
+	}
 }
 
 DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
 {
+	int id = effect.begin()->sid; //effects' source ID
+
 	BOOST_FOREACH(ui32 id, stacks)
 	{
 		CStack *s = gs->curB->getStack(id);
 		if(s)
 		{
-			int id = effect.begin()->sid; //effects' source ID
 			if(id == 47 || !s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id)))//disrupting ray or not on the list - just add	
 			{
 				BOOST_FOREACH(Bonus &fromEffect, effect)
@@ -1147,6 +1157,20 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
 		else
 			tlog1 << "Cannot find stack " << id << std::endl;
 	}
+	typedef std::pair<ui32, Bonus> p;
+	BOOST_FOREACH(p para, uniqueBonuses)
+	{
+		CStack *s = gs->curB->getStack(para.first);
+		if (s)
+		{
+			if (!s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id) && Selector::typeSybtype(para.second.type, para.second.subtype)))
+				s->addNewBonus(new Bonus(para.second));
+			else
+				actualizeEffect(s, effect);
+		}
+		else
+			tlog1 << "Cannot find stack " << para.first << std::endl;
+	}
 }
 
 DLL_EXPORT void StacksInjured::applyGs( CGameState *gs )

+ 54 - 5
server/CGameHandler.cpp

@@ -3439,6 +3439,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 				sendAndApply(&si);
 			break;
 		}
+	// permanent effects
 	case 27: //shield 
 	case 28: //air shield
 	case 29: //fire shield
@@ -3470,17 +3471,65 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 	case 62: //blind
 		{
 			SetStackEffect sse;
+			Bonus pseudoBonus;
+			pseudoBonus.sid = spellID;
+			pseudoBonus.val = spellLvl;
+			pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower);
+			CStack::stackEffectToFeature(sse.effect, pseudoBonus);
+
+			const Bonus * bonus = caster->getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, spellID));
+			si32 power;
 			for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
 			{
 				if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
 					continue;
 				sse.stacks.push_back((*it)->ID);
+				
+				//Apply hero specials - peculiar enchants
+				ui8 tier = (*it)->base->type->level;
+				if (bonus)
+ 				{
+ 	 				switch(bonus->additionalInfo)
+ 	 				{
+ 	 					case 0: //normal
+						{
+ 	 						switch(tier)
+ 	 						{
+ 	 							case 1: case 2:
+ 	 								power = 3; 
+ 	 							break;
+ 	 							case 3: case 4:
+ 	 								power = 2;
+ 	 							break;
+ 	 							case 5: case 6:
+ 	 								power = 1;
+ 	 							break;
+ 	 						}
+							Bonus specialBonus(sse.effect.back());
+							specialBonus.val = power; //it doesn't necessarily make sense for some spells, use it wisely
+							sse.uniqueBonuses.push_back (std::pair<ui32,Bonus> ((*it)->ID, specialBonus)); //additional premy to given effect
+						}
+ 	 					break;
+ 	 					case 1: //only Coronius as yet
+						{
+ 	 						power = std::max(5 - tier, 0);
+							Bonus specialBonus = CStack::featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, pseudoBonus.turnsRemain);
+							specialBonus.sid = spellID;
+				 	 		sse.uniqueBonuses.push_back (std::pair<ui32,Bonus> ((*it)->ID, specialBonus)); //additional attack to Slayer effect
+						}
+ 	 					break;
+ 	 				}
+ 				}
+				if (caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
+ 	 			{
+ 	 				int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / tier;
+					Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
+					specialBonus.valType = Bonus::PERCENT_TO_ALL;
+					specialBonus.sid = spellID;
+ 	 				sse.uniqueBonuses.push_back (std::pair<ui32,Bonus> ((*it)->ID, specialBonus));
+ 	 			}
 			}
-			Bonus pseudoBonus;
-			pseudoBonus.sid = spellID;
-			pseudoBonus.val = spellLvl;
-			pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower);
-			CStack::stackEffectToFeature(sse.effect, pseudoBonus);
+
 			if(!sse.stacks.empty())
 				sendAndApply(&sse);
 			break;