Pārlūkot izejas kodu

REVENGE bonus that matches HotA haspid ability

M 1 gadu atpakaļ
vecāks
revīzija
67f18729fa

+ 2 - 0
Mods/vcmi/config/vcmi/english.json

@@ -441,6 +441,8 @@
 	"core.bonus.REBIRTH.description": "${val}% of stack will rise after death",
 	"core.bonus.RETURN_AFTER_STRIKE.name": "Attack and Return",
 	"core.bonus.RETURN_AFTER_STRIKE.description": "Returns after melee attack",
+	"core.bonus.REVENGE.name": "Revenge",
+	"core.bonus.REVENGE.description": "Deals extra damage based on attacker's lost health in battle",
 	"core.bonus.SHOOTER.name": "Ranged",
 	"core.bonus.SHOOTER.description": "Creature can shoot",
 	"core.bonus.SHOOTS_ALL_ADJACENT.name": "Shoot all around",

+ 8 - 0
config/bonuses.json

@@ -451,6 +451,14 @@
 		}
 	},
 
+	"REVENGE":
+	{
+		"graphics":
+		{
+			"icon": ""
+		}
+	},
+
 	"SHOOTER":
 	{
 		"graphics":

+ 6 - 0
docs/modders/Bonus/Bonus_Types.md

@@ -621,6 +621,12 @@ Affected unit will ignore specified percentage of attacked unit attack (Nix)
 
 - val: amount of attack points to ignore, percentage
 
+### REVENGE
+
+Affected unit will deal more damage based on percentage of self health lost compared to amount on start of battle
+(formula: `square_root((total_unit_count + 1) * 1_creature_max_health / (current_whole_unit_health + 1_creature_max_health) - 1)`.
+Result is then multiplied separately by min and max base damage of unit and result is additive bonus to total damage at end of calculation)
+
 ## Special abilities
 
 ### CATAPULT

+ 15 - 3
lib/battle/DamageCalculator.cpp

@@ -526,11 +526,23 @@ DamageEstimation DamageCalculator::calculateDmgRange() const
 
 	double resultingFactor = std::min(8.0, attackFactorTotal) * std::max( 0.01, defenseFactorTotal);
 
-	info.defender->getTotalHealth();
+	double revengeAdditionalMinDamage = 0.0;
+	double revengeAdditionalMaxDamage = 0.0;
+	if(info.attacker->hasBonusOfType(BonusType::REVENGE)) //HotA Haspid ability
+	{
+		int totalStackCount = info.attacker->unitBaseAmount();
+		int currentStackHealth = info.attacker->getAvailableHealth();
+		int creatureHealth = info.attacker->getMaxHealth();
+
+		double revengeFactor = sqrt(static_cast<double>((totalStackCount + 1) * creatureHealth) / (currentStackHealth + creatureHealth) - 1);
+
+		revengeAdditionalMinDamage = std::round(damageBase.min * revengeFactor);
+		revengeAdditionalMaxDamage = std::round(damageBase.max * revengeFactor);
+	}
 
 	DamageRange damageDealt {
-		std::max<int64_t>( 1.0, std::floor(damageBase.min * resultingFactor)),
-		std::max<int64_t>( 1.0, std::floor(damageBase.max * resultingFactor))
+		std::max<int64_t>( 1.0, std::floor(damageBase.min * resultingFactor + revengeAdditionalMinDamage)),
+		std::max<int64_t>( 1.0, std::floor(damageBase.max * resultingFactor + revengeAdditionalMaxDamage))
 	};
 
 	DamageRange killsDealt = getCasualties(damageDealt);

+ 1 - 0
lib/bonuses/BonusEnum.h

@@ -176,6 +176,7 @@ class JsonNode;
 	BONUS_NAME(FEROCITY) /*extra attacks, only if at least some creatures killed while attacking target unit, val = amount of additional attacks, additional info = amount of creatures killed to trigger (default 1)*/ \
 	BONUS_NAME(ACCURATE_SHOT) /*HotA Sea Dog-like ability - ranged only, val = full arrow trigger percent, subtype = spell identifier that killed value goes through (death stare by default) - use 'accurateShot' as part of spell name for proper battle log description*/ \
 	BONUS_NAME(ENEMY_ATTACK_REDUCTION) /*in % (value) eg. Nix (HotA)*/ \
+	BONUS_NAME(REVENGE) /*additional damage based on how many units in stack died - formula: sqrt((number of creatures at battle start + 1) * creature health) / (total health now + 1 creature health) - 1) * 100% */ \
 	/* end of list */