1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

vcmi: skill-agnostic artillery

Now it should work for any creature and with any damage percentage.
This commit is contained in:
Konstantin 2023-02-26 01:19:39 +03:00
parent 9205ef2c91
commit 64ad7558c6
4 changed files with 39 additions and 29 deletions

View File

@ -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"
}
}
},

View File

@ -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 */

View File

@ -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;
}

View File

@ -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,26 +4830,18 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
{
makeAttack(destinationStack, stack, 0, stack->getPosition(), true, true, true);
}
//TODO: move to CUnitState
//extra shot(s) for ballista, based on artillery skill
if(stack->creatureIndex() == CreatureID::BALLISTA)
{
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);
}
}
}
//allow more than one additional attack
int totalRangedAttacks = stack->totalAttacks.getRangedValue();
//TODO: move to CUnitState
const auto * attackingHero = gs->curB->battleGetFightingHero(ba.side);
if(attackingHero)
{
totalRangedAttacks += attackingHero->valOfBonuses(Bonus::HERO_GRANTS_ATTACKS, stack->creatureIndex());
}
for(int i = 1; i < totalRangedAttacks; ++i)
{
if(