Răsfoiți Sursa

vcmi: skill-agnostic artillery

Now it should work for any creature and with any damage percentage.
Konstantin 2 ani în urmă
părinte
comite
64ad7558c6
4 a modificat fișierele cu 37 adăugiri și 27 ștergeri
  1. 10 4
      config/skills.json
  2. 5 2
      lib/HeroBonus.h
  3. 5 2
      lib/battle/DamageCalculator.cpp
  4. 17 19
      server/CGameHandler.cpp

+ 10 - 4
config/skills.json

@@ -581,13 +581,13 @@
 		"base" : {
 			"effects" : {
 				"main" : {
-					"subtype" : "skill.artillery",
-					"type" : "SECONDARY_SKILL_PREMY",
+					"subtype" : "creature.ballista",
+					"type" : "BONUS_DAMAGE_CHANCE",
 					"valueType" : "BASE_NUMBER"
 				},
 				"val2" : {
-					"subtype" : "skill.artillery",
-					"type" : "SECONDARY_SKILL_VAL2",
+					"subtype" : "creature.ballista",
+					"type" : "HERO_GRANTS_ATTACKS",
 					"valueType" : "BASE_NUMBER"
 				},
 				"ctrl" : {
@@ -601,6 +601,12 @@
 					"type" : "MANUAL_CONTROL",
 					"val" : 100,
 					"valueType" : "BASE_NUMBER"
+				},
+				"damagePower" : {
+					"subtype" : "creature.ballista",
+					"type" : "BONUS_DAMAGE_PERCENTAGE",
+					"val" : 100,
+					"valueType" : "BASE_NUMBER"
 				}
 			}
 		},

+ 5 - 2
lib/HeroBonus.h

@@ -317,7 +317,7 @@ public:
 	BONUS_NAME(CATAPULT_EXTRA_SHOTS) /*val - power of catapult effect, requires CATAPULT bonus to work*/\
 	BONUS_NAME(RANGED_RETALIATION) /*allows shooters to perform ranged retaliation*/\
 	BONUS_NAME(BLOCKS_RANGED_RETALIATION) /*disallows ranged retaliation for shooter unit, BLOCKS_RETALIATION bonus is for melee retaliation only*/\
-  	BONUS_NAME(SECONDARY_SKILL_VAL2) /*for secondary skills that have multiple effects, like eagle eye (max level and chance)*/  \
+	BONUS_NAME(SECONDARY_SKILL_VAL2) /*deprecated. has no effect, will be converted to actual bonus*/  \
 	BONUS_NAME(MANUAL_CONTROL) /* manually control warmachine with id = subtype, chance = val */  \
 	BONUS_NAME(WIDE_BREATH) /* initial desigh: dragon breath affecting multiple nearby hexes */\
 	BONUS_NAME(FIRST_STRIKE) /* first counterattack, then attack if possible */\
@@ -342,7 +342,10 @@ public:
 	BONUS_NAME(BEFORE_BATTLE_REPOSITION_BLOCK) /*skill-agnostic tactics, bonus for blocking opposite tactics. For now donble side tactics is TODO.*/\
 	BONUS_NAME(HERO_EXPERIENCE_GAIN_PERCENT) /*skill-agnostic learning, and we can use it as a global effect also*/\
 	BONUS_NAME(UNDEAD_RAISE_PERCENTAGE) /*Percentage of killed enemy creatures to be raised after battle as undead*/\
-	BONUS_NAME(MANA_PER_KNOWLEDGE) /*Rate of translating hero knowledge to mana, used for intelligence and as a global bonus*/\
+	BONUS_NAME(MANA_PER_KNOWLEDGE) /*Percentage rate of translating 10 hero knowledge to mana, used to intelligence and global bonus*/\
+	BONUS_NAME(HERO_GRANTS_ATTACKS) /*If hero can grant additional attacks to creature, value is number of attacks, subtype is creatureID*/\
+	BONUS_NAME(BONUS_DAMAGE_PERCENTAGE) /*If hero can grant conditional damage to creature, value is percentage, subtype is creatureID*/\
+	BONUS_NAME(BONUS_DAMAGE_CHANCE) /*If hero can grant additional damage to creature, value is chance, subtype is creatureID*/\
 	/* end of list */
 
 

+ 5 - 2
lib/battle/DamageCalculator.cpp

@@ -229,8 +229,11 @@ double DamageCalculator::getAttackDeathBlowFactor() const
 
 double DamageCalculator::getAttackDoubleDamageFactor() const
 {
-	if(info.doubleDamage)
-		return 1.0;
+	if(info.doubleDamage) {
+		const auto cachingStr = "type_BONUS_DAMAGE_PERCENTAGEs_" + std::to_string(info.attacker->creatureIndex());
+		const auto selector = Selector::typeSubtype(Bonus::BONUS_DAMAGE_PERCENTAGE, info.attacker->creatureIndex());
+		return info.attacker->valOfBonuses(selector, cachingStr) / 100.0;
+	}
 	return 0.0;
 }
 

+ 17 - 19
server/CGameHandler.cpp

@@ -1050,14 +1050,12 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
 		bat.flags |= BattleAttack::DEATH_BLOW;
 	}
 
-	if (attacker->getCreature()->idNumber == CreatureID::BALLISTA)
+	const auto * owner = gs->curB->getHero(attacker->owner);
+	if(owner)
 	{
-		const CGHeroInstance * owner = gs->curB->getHero(attacker->owner);
-		int chance = owner->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::ARTILLERY);
+		int chance = owner->valOfBonuses(Bonus::BONUS_DAMAGE_CHANCE, attacker->creatureIndex());
 		if (chance > getRandomGenerator().nextInt(99))
-		{
 			bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
-		}
 	}
 
 	int64_t drainedLife = 0;
@@ -4748,6 +4746,14 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 			//attack
 			int totalAttacks = stack->totalAttacks.getMeleeValue();
 
+			//TODO: move to CUnitState
+			const auto * attackingHero = gs->curB->battleGetFightingHero(ba.side);
+			if(attackingHero)
+			{
+				totalAttacks += attackingHero->valOfBonuses(Bonus::HERO_GRANTS_ATTACKS, stack->creatureIndex());
+			}
+
+
 			const bool firstStrike = destinationStack->hasBonusOfType(Bonus::FIRST_STRIKE);
 			const bool retaliation = destinationStack->ableToRetaliate();
 			for (int i = 0; i < totalAttacks; ++i)
@@ -4824,25 +4830,17 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 			{
 				makeAttack(destinationStack, stack, 0, stack->getPosition(), true, true, true);
 			}
+			//allow more than one additional attack
+
+			int totalRangedAttacks = stack->totalAttacks.getRangedValue();
 
 			//TODO: move to CUnitState
-			//extra shot(s) for ballista, based on artillery skill
-			if(stack->creatureIndex() == CreatureID::BALLISTA)
+			const auto * attackingHero = gs->curB->battleGetFightingHero(ba.side);
+			if(attackingHero)
 			{
-				const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
-
-				if(attackingHero)
-				{
-					int ballistaBonusAttacks = attackingHero->valOfBonuses(Bonus::SECONDARY_SKILL_VAL2, SecondarySkill::ARTILLERY);
-					while(destinationStack->alive() && ballistaBonusAttacks-- > 0)
-					{
-						makeAttack(stack, destinationStack, 0, destination, false, true, false);
-					}
-				}
+				totalRangedAttacks += attackingHero->valOfBonuses(Bonus::HERO_GRANTS_ATTACKS, stack->creatureIndex());
 			}
-			//allow more than one additional attack
 
-			int totalRangedAttacks = stack->totalAttacks.getRangedValue();
 
 			for(int i = 1; i < totalRangedAttacks; ++i)
 			{