1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

Merge pull request #4623 from Laserlicht/invincible_bonus

INVINCIBLE bonus
This commit is contained in:
Ivan Savenko
2024-09-20 11:50:29 +03:00
committed by GitHub
11 changed files with 51 additions and 4 deletions

View File

@@ -337,7 +337,10 @@ BattleAction BattleEvaluator::moveOrAttack(const CStack * stack, BattleHex hex,
}
else
{
return BattleAction::makeMove(stack, hex);
if(stack->position == hex)
return BattleAction::makeDefend(stack);
else
return BattleAction::makeMove(stack, hex);
}
}

View File

@@ -296,7 +296,11 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
for(auto hex : hexes)
{
if(vstd::contains(avHexes, hex))
{
if(stack->position == hex)
return BattleAction::makeDefend(stack);
return BattleAction::makeMove(stack, hex);
}
if(stack->coversPos(hex))
{
@@ -336,7 +340,11 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
}
if(vstd::contains(avHexes, currentDest))
{
if(stack->position == currentDest)
return BattleAction::makeDefend(stack);
return BattleAction::makeMove(stack, currentDest);
}
currentDest = reachability.predecessors[currentDest];
}

View File

@@ -665,5 +665,7 @@
"core.bonus.WIDE_BREATH.name": "Wide breath",
"core.bonus.WIDE_BREATH.description": "Wide breath attack (multiple hexes)",
"core.bonus.DISINTEGRATE.name": "Disintegrate",
"core.bonus.DISINTEGRATE.description": "No corpse remains after death"
"core.bonus.DISINTEGRATE.description": "No corpse remains after death",
"core.bonus.INVINCIBLE.name": "Invincible",
"core.bonus.INVINCIBLE.description": "Cannot be affected by anything"
}

View File

@@ -600,6 +600,15 @@
"icon": "zvs/Lib1.res/DISINTEGRATE"
}
},
"INVINCIBLE":
{
"graphics":
{
"icon": "zvs/Lib1.res/INVINCIBLE"
}
}
}

View File

@@ -10,6 +10,10 @@
"cavalryChargeImmunity" :
{
"type" : "CHARGE_IMMUNITY"
},
"invincible" :
{
"type" : "INVINCIBLE"
}
},
"graphics" :

View File

@@ -1022,4 +1022,8 @@ Internal bonus, do not use
### DISINTEGRATE
After death of unit no corpse remains
When a unit affected by this bonus dies, no corpse is left behind
### INVINCIBLE
The unit affected by this bonus cannot be target of attacks or spells

View File

@@ -296,6 +296,9 @@ std::vector<BattleHex> CStack::meleeAttackHexes(const battle::Unit * attacker, c
bool CStack::isMeleeAttackPossible(const battle::Unit * attacker, const battle::Unit * defender, BattleHex attackerPos, BattleHex defenderPos)
{
if(defender->hasBonusOfType(BonusType::INVINCIBLE))
return false;
return !meleeAttackHexes(attacker, defender, attackerPos, defenderPos).empty();
}

View File

@@ -685,6 +685,9 @@ bool CBattleInfoCallback::battleCanAttack(const battle::Unit * stack, const batt
if (!stack || !target)
return false;
if(target->hasBonusOfType(BonusType::INVINCIBLE))
return false;
if(!battleMatchOwner(stack, target))
return false;
@@ -730,6 +733,9 @@ bool CBattleInfoCallback::battleCanShoot(const battle::Unit * attacker, BattleHe
if(!attacker || !defender)
return false;
if(defender->hasBonusOfType(BonusType::INVINCIBLE))
return false;
if(battleMatchOwner(attacker, defender) && defender->alive())
{
if(battleCanShoot(attacker))

View File

@@ -179,6 +179,7 @@ class JsonNode;
BONUS_NAME(RESOURCES_CONSTANT_BOOST) /*Bonus that does not account for propagation and gives extra resources per day. val - resource amount, subtype - resource type*/ \
BONUS_NAME(RESOURCES_TOWN_MULTIPLYING_BOOST) /*Bonus that does not account for propagation and gives extra resources per day with amount multiplied by number of owned towns. val - base resource amount to be multiplied times number of owned towns, subtype - resource type*/ \
BONUS_NAME(DISINTEGRATE) /* after death no corpse remains */ \
BONUS_NAME(INVINCIBLE) /* cannot be target of attacks or spells */ \
/* end of list */

View File

@@ -228,8 +228,11 @@ bool BattleSpellMechanics::canBeCastAt(const Target & target, Problem & problem)
mainTarget = battle()->battleGetUnitByPos(target.front().hexValue, true);
}
if (mainTarget && mainTarget == caster)
if(mainTarget && mainTarget == caster)
return false; // can't cast on self
if(mainTarget && mainTarget->hasBonusOfType(BonusType::INVINCIBLE))
return false;
}
return effects->applicable(problem, this, target, spellTarget);

View File

@@ -425,6 +425,10 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni
ret *= 100 + bearer->valOfBonuses(BonusType::MORE_DAMAGE_FROM_SPELL, BonusSubtypeID(id));
ret /= 100;
}
//invincible
if(bearer->hasBonusOfType(BonusType::INVINCIBLE))
ret = 0;
}
ret = caster->getSpellBonus(this, ret, affectedCreature);
return ret;