Browse Source

* new spells:
- precision
- slayer
* refactoring

mateuszb 16 years ago
parent
commit
b0e2d13b4e
5 changed files with 130 additions and 56 deletions
  1. 1 1
      AI/GeniusAI/CGeniusAI.cpp
  2. 109 45
      CGameState.cpp
  3. 12 8
      CGameState.h
  4. 2 2
      config/spell_info.txt
  5. 6 0
      server/CGameHandler.cpp

+ 1 - 1
AI/GeniusAI/CGeniusAI.cpp

@@ -476,7 +476,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
 			CGHeroInstance *attackerHero = (m_side)? m_hero1 : m_hero2;
 			CGHeroInstance *attackerHero = (m_side)? m_hero1 : m_hero2;
 			CGHeroInstance *defendingHero = (m_side)? m_hero2 : m_hero1;
 			CGHeroInstance *defendingHero = (m_side)? m_hero2 : m_hero1;
 
 
-			int attackDefenseBonus = currentStack->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0) - (st->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0));
+			int attackDefenseBonus = currentStack->Attack() - st->Defense();
 			float damageFactor = 1.0f;
 			float damageFactor = 1.0f;
 			if(attackDefenseBonus < 0) //decreasing dmg
 			if(attackDefenseBonus < 0) //decreasing dmg
 			{
 			{

+ 109 - 45
CGameState.cpp

@@ -445,10 +445,8 @@ std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool
 
 
 CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
 CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
 	:ID(I), creature(C), amount(A), baseAmount(A), firstHPleft(C->hitPoints), owner(O), slot(S), attackerOwned(AO), position(-1),   
 	:ID(I), creature(C), amount(A), baseAmount(A), firstHPleft(C->hitPoints), owner(O), slot(S), attackerOwned(AO), position(-1),   
-	 counterAttacks(1), shots(C->shots), state(), effects()
+	counterAttacks(1), shots(C->shots), state(), effects(), speed(creature->speed), abilities(C->abilities), attack(C->attack), defense(C->defence)
 {
 {
-	speed = creature->speed;
-	abilities = C->abilities;
 	state.insert(ALIVE);
 	state.insert(ALIVE);
 }
 }
 
 
@@ -529,6 +527,54 @@ si8 CStack::Luck() const
 	return ret;
 	return ret;
 }
 }
 
 
+si32 CStack::Attack() const
+{
+	si32 ret = attack; //value to be returned
+
+	if(getEffect(56)) //frenzy for attacker
+	{
+		ret += (VLC->spellh->spells[56].powers[getEffect(56)->level]/100.0) * defense;
+	}
+
+	if(getEffect(48)) //attacker's prayer handling
+	{
+		ret += VLC->spellh->spells[48].powers[getEffect(48)->level];
+	}
+
+	if(getEffect(45)) //weakness handling
+	{
+		ret -= VLC->spellh->spells[45].powers[getEffect(45)->level];
+	}
+
+	return ret;
+}
+
+si32 CStack::Defense() const
+{
+	si32 ret = defense;
+
+	if(getEffect(56)) //frenzy for defender
+	{
+		return 0;
+	}
+
+	if(getEffect(48)) //defender's prayer handling
+	{
+		ret += VLC->spellh->spells[48].powers[getEffect(48)->level];
+	}
+	if(getEffect(47)) //defender's disrupting ray handling
+	{
+		int howMany = howManyEffectsSet(47);
+		ret -=  VLC->spellh->spells[47].powers[getEffect(47)->level] * howMany;
+	}
+	if(getEffect(46)) //stone skin handling
+	{
+		ret += VLC->spellh->spells[46].powers[getEffect(46)->level];
+	}
+
+	return ret;
+}
+
 bool CStack::willMove()
 bool CStack::willMove()
 {
 {
 	return !vstd::contains(state,DEFENDING)
 	return !vstd::contains(state,DEFENDING)
@@ -1699,46 +1745,72 @@ bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const
 
 
 int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
 int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
 {
 {
-	int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0),
-		defenderDefenseBonus = defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0),
-		attackDefenseBonus = 0,
+	int attackDefenseBonus = attacker->Attack() - defender->Defense(),
 		minDmg = attacker->creature->damageMin * attacker->amount, 
 		minDmg = attacker->creature->damageMin * attacker->amount, 
 		maxDmg = attacker->creature->damageMax * attacker->amount;
 		maxDmg = attacker->creature->damageMax * attacker->amount;
 
 
 	//calculating total attack/defense skills modifier
 	//calculating total attack/defense skills modifier
-	if(attacker->getEffect(56)) //frenzy for attacker
-	{
-		attackerAttackBonus += (VLC->spellh->spells[56].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0));
-	}
-	if(defender->getEffect(56)) //frenzy for defender
-	{
-		defenderDefenseBonus = 0;
-	}
-	attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus;
-	if(defender->getEffect(48)) //defender's prayer handling
-	{
-		attackDefenseBonus -= VLC->spellh->spells[48].powers[defender->getEffect(48)->level];
-	}
-	if(attacker->getEffect(48)) //attacker's prayer handling
-	{
-		attackDefenseBonus += VLC->spellh->spells[48].powers[attacker->getEffect(48)->level];
-	}
-	if(defender->getEffect(47)) //defender's disrupting ray handling
-	{
-		int howMany = defender->howManyEffectsSet(47);
-		attackDefenseBonus +=  VLC->spellh->spells[47].powers[attacker->getEffect(47)->level] * howMany;
-	}
-	if(defender->getEffect(46)) //stone skin handling
+
+	if(!shooting && attacker->getEffect(43)) //bloodlust handling
 	{
 	{
-		attackDefenseBonus -= VLC->spellh->spells[46].powers[defender->getEffect(46)->level];
+		attackDefenseBonus += VLC->spellh->spells[43].powers[attacker->getEffect(43)->level];
 	}
 	}
-	if(attacker->getEffect(45)) //weakness handling
+
+	if(shooting && attacker->getEffect(44)) //precision handling
 	{
 	{
-		attackDefenseBonus -= VLC->spellh->spells[45].powers[attacker->getEffect(45)->level];
+		attackDefenseBonus += VLC->spellh->spells[44].powers[attacker->getEffect(44)->level];
 	}
 	}
-	if(!shooting && attacker->getEffect(43)) //bloodlust handling
+
+	if(attacker->getEffect(55)) //slayer handling
 	{
 	{
-		attackDefenseBonus += VLC->spellh->spells[43].powers[attacker->getEffect(43)->level];
+		std::vector<int> affectedIds;
+		switch(attacker->getEffect(55)->level)
+		{
+		case 3: //expert
+			{
+				affectedIds.push_back(40); //giant
+				affectedIds.push_back(41); //titan
+				affectedIds.push_back(152); //lord of thunder
+			} //continue adding ...
+		case 2: //advanced
+			{
+				affectedIds.push_back(12); //angel
+				affectedIds.push_back(13); //archangel
+				affectedIds.push_back(54); //devil
+				affectedIds.push_back(55); //arch devil
+				affectedIds.push_back(150); //supreme archangel
+				affectedIds.push_back(153); //antichrist
+			} //continue adding ...
+		case 0: case 1: //none and basic
+			{
+				affectedIds.push_back(26); //green dragon
+				affectedIds.push_back(27); //gold dragon
+				affectedIds.push_back(82); //red dragon
+				affectedIds.push_back(83); //black dragon
+				affectedIds.push_back(96); //behemot
+				affectedIds.push_back(97); //ancient behemot
+				affectedIds.push_back(110); //hydra
+				affectedIds.push_back(111); //chaos hydra
+				affectedIds.push_back(132); //azure dragon
+				affectedIds.push_back(133); //crystal dragon
+				affectedIds.push_back(134); //faerie dragon
+				affectedIds.push_back(135); //rust dragon
+				affectedIds.push_back(151); //diamond dragon
+				affectedIds.push_back(154); //blood dragon
+				affectedIds.push_back(155); //darkness dragon
+				affectedIds.push_back(156); //ghost behemot
+				affectedIds.push_back(157); //hell hydra
+				break;
+			}
+		}
+		for(int g=0; g<affectedIds.size(); ++g)
+		{
+			if(defender->creature->idNumber == affectedIds[g])
+			{
+				attackDefenseBonus += VLC->spellh->spells[55].powers[attacker->getEffect(55)->level];
+				break;
+			}
+		}
 	}
 	}
 
 
 	float dmgBonusMultiplier = 1.0f;
 	float dmgBonusMultiplier = 1.0f;
@@ -1819,26 +1891,18 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
 	//handling spell effects
 	//handling spell effects
 	if(!shooting && defender->getEffect(27)) //shield
 	if(!shooting && defender->getEffect(27)) //shield
 	{
 	{
-		if(defender->getEffect(27)->level<=1) //none or basic
-			dmgBonusMultiplier *= 0.85f;
-		else //adv or expert
-			dmgBonusMultiplier *= 0.7f;
+		dmgBonusMultiplier *= float(VLC->spellh->spells[27].powers[attacker->getEffect(27)->level]) / 100.0f;
 	}
 	}
 	else if(shooting && defender->getEffect(28)) //air shield
 	else if(shooting && defender->getEffect(28)) //air shield
 	{
 	{
-		if(defender->getEffect(28)->level<=1) //none or basic
-			dmgBonusMultiplier *= 0.75f;
-		else //adv or expert
-			dmgBonusMultiplier *= 0.5f;
+		dmgBonusMultiplier *= float(VLC->spellh->spells[28].powers[attacker->getEffect(28)->level]) / 100.0f;
 	}
 	}
 	if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
 	if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
 	{
 	{
-		if(attacker->getEffect(42)->level>=2) //adv or expert
-			dmgBonusMultiplier *= 0.8f;
+		dmgBonusMultiplier *= 0.8f * float(VLC->spellh->spells[42].powers[attacker->getEffect(42)->level]); //the second factor is 1 or 0
 	}
 	}
 
 
 
 
-
 	minDmg *= dmgBonusMultiplier;
 	minDmg *= dmgBonusMultiplier;
 	maxDmg *= dmgBonusMultiplier;
 	maxDmg *= dmgBonusMultiplier;
 
 

+ 12 - 8
CGameState.h

@@ -151,7 +151,9 @@ public:
 	ui16 position; //position on battlefield
 	ui16 position; //position on battlefield
 	ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
 	ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
 	si16 shots; //how many shots left
 	si16 shots; //how many shots left
-	ui8 speed;
+	ui8 speed; //speed of stack with hero bonus
+	si32 attack; //attack of stack with hero bonus
+	si32 defense; //defense of stack with hero bonus
 	si8 morale, luck; //base stack luck/morale
 	si8 morale, luck; //base stack luck/morale
 
 
 	std::set<EAbilities> abilities;
 	std::set<EAbilities> abilities;
@@ -168,14 +170,16 @@ public:
 	};
 	};
 	std::vector<StackEffect> effects;
 	std::vector<StackEffect> effects;
 
 
-	CStack(CCreature * C, int A, int O, int I, bool AO, int S);
-	CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {}
+	CStack(CCreature * C, int A, int O, int I, bool AO, int S); //c-tor
+	CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {} //c-tor
 	const StackEffect * getEffect(ui16 id) const; //effect id (SP)
 	const StackEffect * getEffect(ui16 id) const; //effect id (SP)
 	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 	bool willMove(); //if stack has remaining move this turn
 	bool willMove(); //if stack has remaining move this turn
-	ui32 Speed() const;
-	si8 Morale() const;
-	si8 Luck() const;
+	ui32 Speed() const; //get speed of creature with all modificators
+	si8 Morale() const; //get morale of stack with all modificators
+	si8 Luck() const; //get luck of stack with all modificators
+	si32 Attack() const; //get attack of stack with all modificators
+	si32 Defense() const; //get defense of stack with all modificators
 	template <typename Handler> void save(Handler &h, const int version)
 	template <typename Handler> void save(Handler &h, const int version)
 	{
 	{
 		h & creature->idNumber;
 		h & creature->idNumber;
@@ -190,13 +194,13 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
 		h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
 		h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
-			& shots & morale & luck & speed;
+			& shots & morale & luck & speed & attack & defense;
 		if(h.saving)
 		if(h.saving)
 			save(h,version);
 			save(h,version);
 		else
 		else
 			load(h,version);
 			load(h,version);
 	}
 	}
-	bool alive() const
+	bool alive() const //determines if stack is alive
 	{
 	{
 		return vstd::contains(state,ALIVE);
 		return vstd::contains(state,ALIVE);
 	}
 	}

+ 2 - 2
config/spell_info.txt

@@ -44,7 +44,7 @@
 41 1 36 0 0 0 X
 41 1 36 0 0 0 X
 42 -1 40 0 0 0 X
 42 -1 40 0 0 0 X
 43 1 4 0 0 0 X
 43 1 4 0 0 0 X
-44 1 -1 0 0 0 X
+44 1 25 0 0 0 X
 45 -1 56 0 0 0 X
 45 -1 56 0 0 0 X
 46 1 54 0 0 0 X
 46 1 54 0 0 0 X
 47 -1 14 0 0 0 X
 47 -1 14 0 0 0 X
@@ -55,7 +55,7 @@
 52 -1 48 0 0 0 X
 52 -1 48 0 0 0 X
 53 1 31 0 0 0 X
 53 1 31 0 0 0 X
 54 -1 19 0 0 0 X
 54 -1 19 0 0 0 X
-55 1 -1 0 0 0 0
+55 1 28 0 0 0 0
 56 1 17 0 0 0 0
 56 1 17 0 0 0 0
 57 -1 -1 0 0 0 0
 57 -1 -1 0 0 0 0
 58 1 -1 0 0 0 X
 58 1 -1 0 0 0 X

+ 6 - 0
server/CGameHandler.cpp

@@ -835,6 +835,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
 			//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
 			//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
 			stacks.back()->morale = hero1->getCurrentMorale(i->first,false);
 			stacks.back()->morale = hero1->getCurrentMorale(i->first,false);
 			stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
 			stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
+			stacks.back()->attack += hero1->getPrimSkillLevel(0);
+			stacks.back()->defense += hero1->getPrimSkillLevel(1);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -884,6 +886,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
 			stacks.back()->speed += hero2->valOfBonuses(HeroBonus::STACKS_SPEED);
 			stacks.back()->speed += hero2->valOfBonuses(HeroBonus::STACKS_SPEED);
 			stacks.back()->morale = hero2->getCurrentMorale(i->first,false);
 			stacks.back()->morale = hero2->getCurrentMorale(i->first,false);
 			stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
 			stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
+			stacks.back()->attack += hero2->getPrimSkillLevel(0);
+			stacks.back()->defense += hero2->getPrimSkillLevel(1);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -2455,6 +2459,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			case 41: //bless
 			case 41: //bless
 			case 42: //curse
 			case 42: //curse
 			case 43: //bloodlust
 			case 43: //bloodlust
+			case 44: //precision
 			case 45: //weakness
 			case 45: //weakness
 			case 46: //stone skin
 			case 46: //stone skin
 			case 47: //disrupting ray
 			case 47: //disrupting ray
@@ -2465,6 +2470,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			case 52: //misfortune
 			case 52: //misfortune
 			case 53: //haste
 			case 53: //haste
 			case 54: //slow
 			case 54: //slow
+			case 55: //slayer
 			case 61: //forgetfulness
 			case 61: //forgetfulness
 				{
 				{
 					SetStackEffect sse;
 					SetStackEffect sse;