Sfoglia il codice sorgente

* support for increasing / decreasing luck / morale for allies / enemies
* support for spell 77 (thunder-sth)

mateuszb 15 anni fa
parent
commit
3a76d72b69

+ 11 - 1
CCallback.cpp

@@ -132,7 +132,7 @@ int CCallback::estimateSpellDamage(const CSpell * sp) const
 		return 0;
 
 	const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
-	return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp));
+	return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(2));
 }
 
 void CCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
@@ -943,6 +943,16 @@ void CCallback::dig( const CGObjectInstance *hero )
 	sendRequest(&dwh);
 }
 
+si8 CCallback::battleGetStackMorale( int stackID )
+{
+	return gs->curB->Morale( gs->curB->getStack(stackID) );
+}
+
+si8 CCallback::battleGetStackLuck( int stackID )
+{
+	return gs->curB->Luck( gs->curB->getStack(stackID) );
+}
+
 InfoAboutTown::InfoAboutTown()
 {
 	tType = NULL;

+ 4 - 0
CCallback.h

@@ -175,6 +175,8 @@ public:
 	virtual std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
 	virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
 	virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
+	virtual si8 battleGetStackMorale(int stackID) =0; //returns morale of given stack
+	virtual si8 battleGetStackLuck(int stackID) =0; //returns luck of given stack
 };
 
 struct HeroMoveDetails
@@ -293,6 +295,8 @@ public:
 	std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID); //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
 	ui8 battleGetSiegeLevel(); //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
 	const CGHeroInstance * battleGetFightingHero(ui8 side) const; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
+	si8 battleGetStackMorale(int stackID); //returns morale of given stack
+	si8 battleGetStackLuck(int stackID); //returns luck of given stack
 
 //XXX hmmm _tmain on _GNUC_ wtf?
 //friends

+ 2 - 2
client/CBattleInterface.cpp

@@ -3467,8 +3467,8 @@ void CBattleHex::clickRight(tribool down, bool previousState)
 
 			pom->attackBonus = myst.Attack() - myst.creature->attack;
 			pom->defenseBonus = myst.Defense() - myst.creature->defence;
-			pom->luck = myst.Luck();
-			pom->morale = myst.Morale();
+			pom->luck = myInterface->curInt->cb->battleGetStackLuck(myst.ID);
+			pom->morale = myInterface->curInt->cb->battleGetStackMorale(myst.ID);
 			pom->speedBonus = myst.Speed() - myst.creature->speed;
 			pom->healthBonus = myst.MaxHealth() - myst.creature->hitPoints;
 			if(myst.hasFeatureOfType(StackFeature::SIEGE_WEAPON))

+ 2 - 2
config/cr_abils.txt

@@ -69,11 +69,11 @@
 +  53 HATE 0 36 0					//efreet sultans hate genies
 +  53 HATE 0 37 0					//efreet sultans hate master genies
 +  54 BLOCKS_RETALIATION 0 0 0 	 	//devils
-+  54 ENEMY_LUCK_DECREASING -1 0 0	//devils
++  54 ENEMY_LUCK_DECREASING 1 0 0	//devils
 +  54 HATE 0 12 0		   	 		//devils hate angels
 +  54 HATE 0 13 0					//devils hate archangles
 +  55 BLOCKS_RETALIATION 0 0 0 	 	//archdevils
-+  55 ENEMY_LUCK_DECREASING -1 0 0 	//archdevils
++  55 ENEMY_LUCK_DECREASING 1 0 0 	//archdevils
 +  55 HATE 0 12 0		   	 		//archdevils hate angels
 +  55 HATE 0 13 0					//archdevils hate archangles
 +  60 FULL_HP_REGENERATION 0 1 0			//wight

+ 73 - 43
lib/CGameState.cpp

@@ -772,44 +772,6 @@ ui8 CStack::howManyEffectsSet(ui16 id) const
 	return ret;
 }
 
-si8 CStack::Morale() const
-{
-	si8 ret = morale;
-
-	if(hasFeatureOfType(StackFeature::NON_LIVING) || hasFeatureOfType(StackFeature::UNDEAD) || hasFeatureOfType(StackFeature::NO_MORALE))
-		return 0;
-	
-	ret += valOfFeatures(StackFeature::MORALE_BONUS); //mirth & sorrow & other
-
-	if(hasFeatureOfType(StackFeature::SELF_MORALE)) //eg. minotaur
-	{
-		ret = std::max<si8>(ret, +1);
-	}
-
-	if(ret > 3) ret = 3;
-	if(ret < -3) ret = -3;
-	return ret;
-}
-
-si8 CStack::Luck() const
-{
-	si8 ret = luck;
-
-	if(hasFeatureOfType(StackFeature::NO_LUCK))
-		return 0;
-	
-	ret += valOfFeatures(StackFeature::LUCK_BONUS); //fortune & misfortune & other
-
-	if(hasFeatureOfType(StackFeature::SELF_LUCK)) //eg. halfling
-	{
-		ret = std::max<si8>(ret, +1);
-	}
-
-	if(ret > 3) ret = 3;
-	if(ret < -3) ret = -3;
-	return ret;
-}
-
 si32 CStack::Attack() const
 {
 	si32 ret = creature->attack; //value to be returned
@@ -2884,7 +2846,7 @@ std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closes
 	return std::make_pair<const CStack * , int>(NULL, -1);
 }
 
-ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel ) const
+ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower ) const
 {
 	ui32 ret = 0; //value to return
 
@@ -2896,10 +2858,8 @@ ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * ca
 	if(dmgMultipliers.find(sp->id) == dmgMultipliers.end())
 		return 0;
 
-	if (caster)
-	{
-		ret = caster->getPrimSkillLevel(2) * dmgMultipliers[sp->id];
-	} 
+
+	ret = usedSpellPower * dmgMultipliers[sp->id];
 	ret += sp->powers[spellSchoolLevel];
 	
 	//applying sorcerery secondary skill
@@ -3539,6 +3499,76 @@ void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, i
 	}
 }
 
+si8 BattleInfo::Morale( const CStack * st ) const
+{
+	si8 ret = st->morale;
+
+	if(st->hasFeatureOfType(StackFeature::NON_LIVING) || st->hasFeatureOfType(StackFeature::UNDEAD) || st->hasFeatureOfType(StackFeature::NO_MORALE))
+		return 0;
+
+	ret += st->valOfFeatures(StackFeature::MORALE_BONUS); //mirth & sorrow & other
+
+	//decreasing / increasing morale from  other stacks
+	for (int g=0; g<stacks.size(); ++g)
+	{
+		if (stacks[g]->owner == st->owner) //ally
+		{
+			if (stacks[g]->hasFeatureOfType(StackFeature::RAISING_MORALE))
+			{
+				ret += stacks[g]->valOfFeatures(StackFeature::RAISING_MORALE);
+			}
+		}
+		else //enemy
+		{
+			if (stacks[g]->hasFeatureOfType(StackFeature::ENEMY_MORALE_DECREASING))
+			{
+				ret -= stacks[g]->valOfFeatures(StackFeature::ENEMY_MORALE_DECREASING);
+			}
+		}
+	}
+
+	if(st->hasFeatureOfType(StackFeature::SELF_MORALE)) //eg. minotaur
+	{
+		ret = std::max<si8>(ret, +1);
+	}
+
+	if(ret > 3) ret = 3;
+	if(ret < -3) ret = -3;
+	return ret;
+}
+
+si8 BattleInfo::Luck( const CStack * st ) const
+{
+	si8 ret = st->luck;
+
+	if(st->hasFeatureOfType(StackFeature::NO_LUCK))
+		return 0;
+
+	ret += st->valOfFeatures(StackFeature::LUCK_BONUS); //fortune & misfortune & other
+
+	//decreasing / increasing morale from  other stacks
+	for (int g=0; g<stacks.size(); ++g)
+	{
+		if (stacks[g]->owner == st->owner) //ally
+		{
+			//no such feature (yet)
+		}
+		else //enemy
+		{
+			ret -= stacks[g]->valOfFeatures(StackFeature::ENEMY_LUCK_DECREASING);
+		}
+	}
+
+	if(st->hasFeatureOfType(StackFeature::SELF_LUCK)) //eg. halfling
+	{
+		ret = std::max<si8>(ret, +1);
+	}
+
+	if(ret > 3) ret = 3;
+	if(ret < -3) ret = -3;
+	return ret;
+}
+
 int3 CPath::startPos() const
 {
 	return nodes[nodes.size()-1].coord;

+ 4 - 3
lib/CGameState.h

@@ -217,6 +217,9 @@ struct DLL_EXPORT BattleInfo
 	std::pair< std::vector<int>, int > getPath(int start, int dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
 	std::vector<int> getAccessibility(int stackID, bool addOccupiable) const; //returns vector of accessible tiles (taking into account the creature range)
 
+	si8 Morale(const CStack * st) const; //get morale of stack with all modificators
+	si8 Luck(const CStack * st) const; //get luck of stack with all modificators
+
 	bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack
 	static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
 	static std::vector<int> neighbouringTiles(int hex);
@@ -229,7 +232,7 @@ struct DLL_EXPORT BattleInfo
 	ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
 	int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
 	std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
-	ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel) const; //calculates damage inflicted by spell
+	ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
 };
 
 class DLL_EXPORT CStack
@@ -271,8 +274,6 @@ public:
 	bool moved(int turn = 0) const; //if stack was already moved this turn
 	bool canMove(int turn = 0) const; //if stack can move
 	ui32 Speed(int turn = 0) 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(bool withFrenzy = true) const; //get defense of stack with all modificators
 	ui16 MaxHealth() const; //get max HP of stack with all modifiers

+ 2 - 2
lib/NetPacksLib.cpp

@@ -990,7 +990,7 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
 		sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
 		break;
 	case 56: //frenzy
-		sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
+		sf.push_back(featureGenerator(StackFeature::IN_FRENZY, 0, sse.level, sse.turnsRemain));
 		break;
 	case 58: //counterstrike
 		sf.push_back(featureGenerator(StackFeature::ADDITIONAL_RETALIATION, 0, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
@@ -1002,7 +1002,7 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
 		sf.push_back(featureGenerator(StackFeature::HYPNOTIZED, 0, sse.level, sse.turnsRemain));
 		break;
 	case 61: //forgetfulness
-		sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
+		sf.push_back(featureGenerator(StackFeature::FORGETFULL, 0, sse.level, sse.turnsRemain));
 		break;
 	case 62: //blind
 		sf.push_back(makeFeature(StackFeature::NOT_ACTIVE, StackFeature::UNITL_BEING_ATTACKED | StackFeature::N_TURNS, 0, 0, StackFeature::SPELL_EFFECT, sse.turnsRemain, 0));

+ 11 - 10
server/CGameHandler.cpp

@@ -359,11 +359,11 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
 		{
 
 			//check for bad morale => freeze
-			if(next->Morale() < 0 &&
+			if( curB.Morale(next) < 0 &&
 				!((hero1->hasBonusOfType(HeroBonus::BLOCK_MORALE)) || (hero2->hasBonusOfType(HeroBonus::BLOCK_MORALE))) //checking if heroes have (or don't have) morale blocking bonuses)
 				)
 			{
-				if( rand()%24   <   (-next->Morale())*2 )
+				if( rand()%24   <   (-curB.Morale(next))*2 )
 				{
 					//unit loses its turn - empty freeze action
 					BattleAction ba;
@@ -462,10 +462,10 @@ askInterfaceForMove:
 				&& !vstd::contains(next->state,DEFENDING)
 				&& !vstd::contains(next->state,WAITING)
 				&&  next->alive()
-				&&  next->Morale() > 0
+				&&  curB.Morale(next) > 0
 				&& !((hero1->hasBonusOfType(HeroBonus::BLOCK_MORALE)) || (hero2->hasBonusOfType(HeroBonus::BLOCK_MORALE)) ) //checking if heroes have (or don't have) morale blocking bonuses
 			)
-				if(rand()%24 < next->Morale()) //this stack hasn't got morale this turn
+				if(rand()%24 < curB.Morale(next)) //this stack hasn't got morale this turn
 					goto askInterfaceForMove; //move this stack once more
 		}
 	}
@@ -593,7 +593,8 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
 	bsa->stackAttacked = def->ID;
 	bsa->attackerID = att->ID;
 	bsa->damageAmount = BattleInfo::calculateDmg(att, def, gs->battleGetOwner(att->ID), gs->battleGetOwner(def->ID), bat.shot(), distance);//counting dealt damage
-	if(att->Luck() > 0  &&  rand()%24 < att->Luck())
+	
+	if(gs->curB->Luck(att) > 0  &&  rand()%24 < gs->curB->Luck(att))
 	{
 		bsa->damageAmount *= 2;
 		bat.flags |= 4;
@@ -3324,7 +3325,7 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
 }
 
 void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor,
-	const CGHeroInstance * caster, const CGHeroInstance * secHero )
+	const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower )
 {
 	CSpell *spell = &VLC->spellh->spells[spellID];
 
@@ -3351,7 +3352,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 	{
 		if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
 			continue;
-		sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl);
+		sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
 	}
 
 	sendAndApply(&sc);
@@ -3381,7 +3382,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 				BattleStackAttacked bsa;
 				bsa.flags |= 2;
 				bsa.effect = spell->mainEffectAnim;
-				bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl);
+				bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
 				bsa.stackAttacked = (*it)->ID;
 				bsa.attackerID = -1;
 				prepareAttacked(bsa,*it);
@@ -3512,7 +3513,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 
 			sendAndApply(&StartAction(ba)); //start spell casting
 
-			handleSpellCasting(ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner, h, secondHero);
+			handleSpellCasting(ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner, h, secondHero, h->getPrimSkillLevel(2));
 
 			sendAndApply(&EndAction());
 			if( !gs->curB->getStack(gs->curB->activeStack, false)->alive() )
@@ -3994,7 +3995,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
 					continue;
 
 				//casting
-				handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL);
+				handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL, attacker->amount);
 			}
 		}
 	}

+ 1 - 1
server/CGameHandler.h

@@ -157,7 +157,7 @@ public:
 
 	void playerMessage( ui8 player, const std::string &message);
 	bool makeBattleAction(BattleAction &ba);
-	void handleSpellCasting(int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero);
+	void handleSpellCasting(int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower);
 	bool makeCustomAction(BattleAction &ba);
 	bool queryReply( ui32 qid, ui32 answer );
 	bool hireHero( ui32 tid, ui8 hid );