mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Merge remote-tracking branch 'upstream/develop' into town-buildings
# Conflicts: # lib/CTownHandler.cpp # lib/rewardable/Interface.cpp
This commit is contained in:
@@ -136,7 +136,7 @@ static void giveExp(BattleResult &r)
|
||||
r.exp[1] = 0;
|
||||
for (auto i = r.casualties[!r.winner].begin(); i!=r.casualties[!r.winner].end(); i++)
|
||||
{
|
||||
r.exp[r.winner] += VLC->creh->objects.at(i->first)->valOfBonuses(Bonus::STACK_HEALTH) * i->second;
|
||||
r.exp[r.winner] += VLC->creh->objects.at(i->first)->valOfBonuses(BonusType::STACK_HEALTH) * i->second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,10 +361,10 @@ void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
|
||||
|
||||
scp.accumulatedBonus.subtype = 0;
|
||||
scp.accumulatedBonus.additionalInfo = 0;
|
||||
scp.accumulatedBonus.duration = Bonus::PERMANENT;
|
||||
scp.accumulatedBonus.duration = BonusDuration::PERMANENT;
|
||||
scp.accumulatedBonus.turnsRemain = 0;
|
||||
scp.accumulatedBonus.source = Bonus::COMMANDER;
|
||||
scp.accumulatedBonus.valType = Bonus::BASE_NUMBER;
|
||||
scp.accumulatedBonus.source = BonusSource::COMMANDER;
|
||||
scp.accumulatedBonus.valType = BonusValueType::BASE_NUMBER;
|
||||
if (skill <= ECommander::SPELL_POWER)
|
||||
{
|
||||
scp.which = SetCommanderProperty::BONUS;
|
||||
@@ -378,36 +378,36 @@ void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
|
||||
switch (skill)
|
||||
{
|
||||
case ECommander::ATTACK:
|
||||
scp.accumulatedBonus.type = Bonus::PRIMARY_SKILL;
|
||||
scp.accumulatedBonus.type = BonusType::PRIMARY_SKILL;
|
||||
scp.accumulatedBonus.subtype = PrimarySkill::ATTACK;
|
||||
break;
|
||||
case ECommander::DEFENSE:
|
||||
scp.accumulatedBonus.type = Bonus::PRIMARY_SKILL;
|
||||
scp.accumulatedBonus.type = BonusType::PRIMARY_SKILL;
|
||||
scp.accumulatedBonus.subtype = PrimarySkill::DEFENSE;
|
||||
break;
|
||||
case ECommander::HEALTH:
|
||||
scp.accumulatedBonus.type = Bonus::STACK_HEALTH;
|
||||
scp.accumulatedBonus.valType = Bonus::PERCENT_TO_BASE;
|
||||
scp.accumulatedBonus.type = BonusType::STACK_HEALTH;
|
||||
scp.accumulatedBonus.valType = BonusValueType::PERCENT_TO_BASE;
|
||||
break;
|
||||
case ECommander::DAMAGE:
|
||||
scp.accumulatedBonus.type = Bonus::CREATURE_DAMAGE;
|
||||
scp.accumulatedBonus.type = BonusType::CREATURE_DAMAGE;
|
||||
scp.accumulatedBonus.subtype = 0;
|
||||
scp.accumulatedBonus.valType = Bonus::PERCENT_TO_BASE;
|
||||
scp.accumulatedBonus.valType = BonusValueType::PERCENT_TO_BASE;
|
||||
break;
|
||||
case ECommander::SPEED:
|
||||
scp.accumulatedBonus.type = Bonus::STACKS_SPEED;
|
||||
scp.accumulatedBonus.type = BonusType::STACKS_SPEED;
|
||||
break;
|
||||
case ECommander::SPELL_POWER:
|
||||
scp.accumulatedBonus.type = Bonus::MAGIC_RESISTANCE;
|
||||
scp.accumulatedBonus.type = BonusType::MAGIC_RESISTANCE;
|
||||
scp.accumulatedBonus.val = difference (VLC->creh->skillLevels, c->secondarySkills, ECommander::RESISTANCE);
|
||||
sendAndApply (&scp); //additional pack
|
||||
scp.accumulatedBonus.type = Bonus::CREATURE_SPELL_POWER;
|
||||
scp.accumulatedBonus.type = BonusType::CREATURE_SPELL_POWER;
|
||||
scp.accumulatedBonus.val = difference (VLC->creh->skillLevels, c->secondarySkills, ECommander::SPELL_POWER) * 100; //like hero with spellpower = ability level
|
||||
sendAndApply (&scp); //additional pack
|
||||
scp.accumulatedBonus.type = Bonus::CASTS;
|
||||
scp.accumulatedBonus.type = BonusType::CASTS;
|
||||
scp.accumulatedBonus.val = difference (VLC->creh->skillLevels, c->secondarySkills, ECommander::CASTS);
|
||||
sendAndApply (&scp); //additional pack
|
||||
scp.accumulatedBonus.type = Bonus::CREATURE_ENCHANT_POWER; //send normally
|
||||
scp.accumulatedBonus.type = BonusType::CREATURE_ENCHANT_POWER; //send normally
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -632,9 +632,9 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
|
||||
|
||||
if(!finishingBattle->isDraw() && finishingBattle->winnerHero)
|
||||
{
|
||||
if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(Bonus::LEARN_BATTLE_SPELL_LEVEL_LIMIT, -1))
|
||||
if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT, -1))
|
||||
{
|
||||
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::LEARN_BATTLE_SPELL_CHANCE, 0);
|
||||
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE, 0);
|
||||
for(auto & spellId : battleInfo->sides.at(!battleResult.data->winner).usedSpellsHistory)
|
||||
{
|
||||
auto spell = spellId.toSpell(VLC->spells());
|
||||
@@ -926,7 +926,7 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
if(counter)
|
||||
bat.flags |= BattleAttack::COUNTER;
|
||||
|
||||
const int attackerLuck = attacker->LuckVal();
|
||||
const int attackerLuck = attacker->luckVal();
|
||||
|
||||
if(attackerLuck > 0)
|
||||
{
|
||||
@@ -946,7 +946,7 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
bat.flags |= BattleAttack::UNLUCKY;
|
||||
}
|
||||
|
||||
if (getRandomGenerator().nextInt(99) < attacker->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
|
||||
if (getRandomGenerator().nextInt(99) < attacker->valOfBonuses(BonusType::DOUBLE_DAMAGE_CHANCE))
|
||||
{
|
||||
bat.flags |= BattleAttack::DEATH_BLOW;
|
||||
}
|
||||
@@ -954,7 +954,7 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
const auto * owner = gs->curB->getHero(attacker->unitOwner());
|
||||
if(owner)
|
||||
{
|
||||
int chance = owner->valOfBonuses(Bonus::BONUS_DAMAGE_CHANCE, attacker->creatureIndex());
|
||||
int chance = owner->valOfBonuses(BonusType::BONUS_DAMAGE_CHANCE, attacker->creatureIndex());
|
||||
if (chance > getRandomGenerator().nextInt(99))
|
||||
bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
|
||||
}
|
||||
@@ -973,7 +973,7 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
drainedLife += applyBattleEffects(bat, attackerState, fireShield, stack, distance, true);
|
||||
}
|
||||
|
||||
std::shared_ptr<const Bonus> bonus = attacker->getBonusLocalFirst(Selector::type()(Bonus::SPELL_LIKE_ATTACK));
|
||||
std::shared_ptr<const Bonus> bonus = attacker->getBonusLocalFirst(Selector::type()(BonusType::SPELL_LIKE_ATTACK));
|
||||
if(bonus && ranged) //TODO: make it work in melee?
|
||||
{
|
||||
//this is need for displaying hit animation
|
||||
@@ -1142,23 +1142,23 @@ int64_t CGameHandler::applyBattleEffects(BattleAttack & bat, std::shared_ptr<bat
|
||||
int64_t drainedLife = 0;
|
||||
|
||||
//life drain handling
|
||||
if(attackerState->hasBonusOfType(Bonus::LIFE_DRAIN) && def->isLiving())
|
||||
if(attackerState->hasBonusOfType(BonusType::LIFE_DRAIN) && def->isLiving())
|
||||
{
|
||||
int64_t toHeal = bsa.damageAmount * attackerState->valOfBonuses(Bonus::LIFE_DRAIN) / 100;
|
||||
int64_t toHeal = bsa.damageAmount * attackerState->valOfBonuses(BonusType::LIFE_DRAIN) / 100;
|
||||
attackerState->heal(toHeal, EHealLevel::RESURRECT, EHealPower::PERMANENT);
|
||||
drainedLife += toHeal;
|
||||
}
|
||||
|
||||
//soul steal handling
|
||||
if(attackerState->hasBonusOfType(Bonus::SOUL_STEAL) && def->isLiving())
|
||||
if(attackerState->hasBonusOfType(BonusType::SOUL_STEAL) && def->isLiving())
|
||||
{
|
||||
//we can have two bonuses - one with subtype 0 and another with subtype 1
|
||||
//try to use permanent first, use only one of two
|
||||
for(si32 subtype = 1; subtype >= 0; subtype--)
|
||||
{
|
||||
if(attackerState->hasBonusOfType(Bonus::SOUL_STEAL, subtype))
|
||||
if(attackerState->hasBonusOfType(BonusType::SOUL_STEAL, subtype))
|
||||
{
|
||||
int64_t toHeal = bsa.killedAmount * attackerState->valOfBonuses(Bonus::SOUL_STEAL, subtype) * attackerState->MaxHealth();
|
||||
int64_t toHeal = bsa.killedAmount * attackerState->valOfBonuses(BonusType::SOUL_STEAL, subtype) * attackerState->getMaxHealth();
|
||||
attackerState->heal(toHeal, EHealLevel::OVERHEAL, ((subtype == 0) ? EHealPower::ONE_BATTLE : EHealPower::PERMANENT));
|
||||
drainedLife += toHeal;
|
||||
break;
|
||||
@@ -1170,13 +1170,13 @@ int64_t CGameHandler::applyBattleEffects(BattleAttack & bat, std::shared_ptr<bat
|
||||
//fire shield handling
|
||||
if(!bat.shot() &&
|
||||
!def->isClone() &&
|
||||
def->hasBonusOfType(Bonus::FIRE_SHIELD) &&
|
||||
!attackerState->hasBonusOfType(Bonus::FIRE_IMMUNITY) &&
|
||||
def->hasBonusOfType(BonusType::FIRE_SHIELD) &&
|
||||
!attackerState->hasBonusOfType(BonusType::FIRE_IMMUNITY) &&
|
||||
CStack::isMeleeAttackPossible(attackerState.get(), def) // attacked needs to be adjacent to defender for fire shield to trigger (e.g. Dragon Breath attack)
|
||||
)
|
||||
{
|
||||
//TODO: use damage with bonus but without penalties
|
||||
auto fireShieldDamage = (std::min<int64_t>(def->getAvailableHealth(), bsa.damageAmount) * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100;
|
||||
auto fireShieldDamage = (std::min<int64_t>(def->getAvailableHealth(), bsa.damageAmount) * def->valOfBonuses(BonusType::FIRE_SHIELD)) / 100;
|
||||
fireShield.push_back(std::make_pair(def, fireShieldDamage));
|
||||
}
|
||||
|
||||
@@ -1334,7 +1334,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
|
||||
ret = path.second;
|
||||
|
||||
int creSpeed = curStack->Speed(0, true);
|
||||
int creSpeed = curStack->speed(0, true);
|
||||
|
||||
if (gs->curB->tacticDistance > 0 && creSpeed > 0)
|
||||
creSpeed = GameConstants::BFIELD_SIZE;
|
||||
@@ -1371,7 +1371,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
return false;
|
||||
};
|
||||
|
||||
if (curStack->hasBonusOfType(Bonus::FLYING))
|
||||
if (curStack->hasBonusOfType(BonusType::FLYING))
|
||||
{
|
||||
if (path.second <= creSpeed && path.first.size() > 0)
|
||||
{
|
||||
@@ -1825,7 +1825,7 @@ void CGameHandler::newTurn()
|
||||
{
|
||||
for(auto stack : hero->stacks)
|
||||
{
|
||||
if(stack.second->hasBonusOfType(Bonus::SPECIAL_CRYSTAL_GENERATION))
|
||||
if(stack.second->hasBonusOfType(BonusType::SPECIAL_CRYSTAL_GENERATION))
|
||||
{
|
||||
hasCrystalGenCreature = true;
|
||||
break;
|
||||
@@ -1838,7 +1838,7 @@ void CGameHandler::newTurn()
|
||||
{
|
||||
for(auto stack : town->stacks)
|
||||
{
|
||||
if(stack.second->hasBonusOfType(Bonus::SPECIAL_CRYSTAL_GENERATION))
|
||||
if(stack.second->hasBonusOfType(BonusType::SPECIAL_CRYSTAL_GENERATION))
|
||||
{
|
||||
hasCrystalGenCreature = true;
|
||||
break;
|
||||
@@ -1868,7 +1868,7 @@ void CGameHandler::newTurn()
|
||||
{
|
||||
for (int k = 0; k < GameConstants::RESOURCE_QUANTITY; k++)
|
||||
{
|
||||
n.res[elem.first][k] += h->valOfBonuses(Bonus::GENERATE_RESOURCE, k);
|
||||
n.res[elem.first][k] += h->valOfBonuses(BonusType::GENERATE_RESOURCE, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1951,13 +1951,13 @@ void CGameHandler::newTurn()
|
||||
sendAndApply (&fw);
|
||||
}
|
||||
}
|
||||
if (t->hasBonusOfType (Bonus::DARKNESS))
|
||||
if (t->hasBonusOfType (BonusType::DARKNESS))
|
||||
{
|
||||
for (auto & player : gs->players)
|
||||
{
|
||||
if (getPlayerStatus(player.first) == EPlayerStatus::INGAME &&
|
||||
getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES)
|
||||
changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type()(Bonus::DARKNESS))->val, player.first, true);
|
||||
changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type()(BonusType::DARKNESS))->val, player.first, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2281,8 +2281,8 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
|
||||
auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, h, PathfinderOptions());
|
||||
auto ti = pathfinderHelper->getTurnInfo();
|
||||
|
||||
const bool canFly = pathfinderHelper->hasBonusOfType(Bonus::FLYING_MOVEMENT) || (h->boat && h->boat->layer == EPathfindingLayer::AIR);
|
||||
const bool canWalkOnSea = pathfinderHelper->hasBonusOfType(Bonus::WATER_WALKING) || (h->boat && h->boat->layer == EPathfindingLayer::WATER);
|
||||
const bool canFly = pathfinderHelper->hasBonusOfType(BonusType::FLYING_MOVEMENT) || (h->boat && h->boat->layer == EPathfindingLayer::AIR);
|
||||
const bool canWalkOnSea = pathfinderHelper->hasBonusOfType(BonusType::WATER_WALKING) || (h->boat && h->boat->layer == EPathfindingLayer::WATER);
|
||||
const int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movement);
|
||||
|
||||
//it's a rock or blocked and not visitable tile
|
||||
@@ -2751,8 +2751,8 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
|
||||
{
|
||||
const CGHeroInstance * h1 = getHero(fromHero);
|
||||
const CGHeroInstance * h2 = getHero(toHero);
|
||||
int h1_scholarSpellLevel = h1->valOfBonuses(Bonus::LEARN_MEETING_SPELL_LIMIT, -1);
|
||||
int h2_scholarSpellLevel = h2->valOfBonuses(Bonus::LEARN_MEETING_SPELL_LIMIT, -1);
|
||||
int h1_scholarSpellLevel = h1->valOfBonuses(BonusType::LEARN_MEETING_SPELL_LIMIT, -1);
|
||||
int h2_scholarSpellLevel = h2->valOfBonuses(BonusType::LEARN_MEETING_SPELL_LIMIT, -1);
|
||||
|
||||
if (h1_scholarSpellLevel < h2_scholarSpellLevel)
|
||||
{
|
||||
@@ -3636,7 +3636,7 @@ bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
|
||||
// {
|
||||
// RemoveBonus rb(RemoveBonus::TOWN);
|
||||
// rb.whoID = t->id;
|
||||
// rb.source = Bonus::TOWN_STRUCTURE;
|
||||
// rb.source = BonusSource::TOWN_STRUCTURE;
|
||||
// rb.id = 17;
|
||||
// sendAndApply(&rb);
|
||||
// }
|
||||
@@ -4322,8 +4322,8 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
|
||||
//resulting creature - bone dragons or skeletons
|
||||
CreatureID resCreature = CreatureID::SKELETON;
|
||||
|
||||
if ((s.hasBonusOfType(Bonus::DRAGON_NATURE)
|
||||
&& !(s.hasBonusOfType(Bonus::UNDEAD)))
|
||||
if ((s.hasBonusOfType(BonusType::DRAGON_NATURE)
|
||||
&& !(s.hasBonusOfType(BonusType::UNDEAD)))
|
||||
|| (s.getCreatureID() == CreatureID::HYDRA)
|
||||
|| (s.getCreatureID() == CreatureID::CHAOS_HYDRA))
|
||||
resCreature = CreatureID::BONE_DRAGON;
|
||||
@@ -4618,12 +4618,12 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
{
|
||||
//defensive stance, TODO: filter out spell boosts from bonus (stone skin etc.)
|
||||
SetStackEffect sse;
|
||||
Bonus defenseBonusToAdd(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, 20, -1, PrimarySkill::DEFENSE, Bonus::PERCENT_TO_ALL);
|
||||
Bonus bonus2(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, stack->valOfBonuses(Bonus::DEFENSIVE_STANCE),
|
||||
-1, PrimarySkill::DEFENSE, Bonus::ADDITIVE_VALUE);
|
||||
Bonus alternativeWeakCreatureBonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, 1, -1, PrimarySkill::DEFENSE, Bonus::ADDITIVE_VALUE);
|
||||
Bonus defenseBonusToAdd(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 20, -1, PrimarySkill::DEFENSE, BonusValueType::PERCENT_TO_ALL);
|
||||
Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE),
|
||||
-1, PrimarySkill::DEFENSE, BonusValueType::ADDITIVE_VALUE);
|
||||
Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, -1, PrimarySkill::DEFENSE, BonusValueType::ADDITIVE_VALUE);
|
||||
|
||||
BonusList defence = *stack->getBonuses(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
|
||||
BonusList defence = *stack->getBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, PrimarySkill::DEFENSE));
|
||||
int oldDefenceValue = defence.totalValue();
|
||||
|
||||
defence.push_back(std::make_shared<Bonus>(defenseBonusToAdd));
|
||||
@@ -4756,11 +4756,11 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
const auto * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
||||
if(attackingHero)
|
||||
{
|
||||
totalAttacks += attackingHero->valOfBonuses(Bonus::HERO_GRANTS_ATTACKS, stack->creatureIndex());
|
||||
totalAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, stack->creatureIndex());
|
||||
}
|
||||
|
||||
|
||||
const bool firstStrike = destinationStack->hasBonusOfType(Bonus::FIRST_STRIKE);
|
||||
const bool firstStrike = destinationStack->hasBonusOfType(BonusType::FIRST_STRIKE);
|
||||
const bool retaliation = destinationStack->ableToRetaliate();
|
||||
for (int i = 0; i < totalAttacks; ++i)
|
||||
{
|
||||
@@ -4771,7 +4771,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
}
|
||||
|
||||
//move can cause death, eg. by walking into the moat, first strike can cause death or paralysis/petrification
|
||||
if(stack->alive() && !stack->hasBonusOfType(Bonus::NOT_ACTIVE) && destinationStack->alive())
|
||||
if(stack->alive() && !stack->hasBonusOfType(BonusType::NOT_ACTIVE) && destinationStack->alive())
|
||||
{
|
||||
makeAttack(stack, destinationStack, (i ? 0 : distance), destinationTile, i==0, false, false);//no distance travelled on second attack
|
||||
}
|
||||
@@ -4779,7 +4779,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
//counterattack
|
||||
//we check retaliation twice, so if it unblocked during attack it will work only on next attack
|
||||
if(stack->alive()
|
||||
&& !stack->hasBonusOfType(Bonus::BLOCKS_RETALIATION)
|
||||
&& !stack->hasBonusOfType(BonusType::BLOCKS_RETALIATION)
|
||||
&& (i == 0 && !firstStrike)
|
||||
&& retaliation && destinationStack->ableToRetaliate())
|
||||
{
|
||||
@@ -4788,7 +4788,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
}
|
||||
|
||||
//return
|
||||
if(stack->hasBonusOfType(Bonus::RETURN_AFTER_STRIKE)
|
||||
if(stack->hasBonusOfType(BonusType::RETURN_AFTER_STRIKE)
|
||||
&& target.size() == 3
|
||||
&& startingPos != stack->getPosition()
|
||||
&& startingPos == target.at(2).hexValue
|
||||
@@ -4828,8 +4828,8 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
makeAttack(stack, destinationStack, 0, destination, true, true, false);
|
||||
|
||||
//ranged counterattack
|
||||
if (destinationStack->hasBonusOfType(Bonus::RANGED_RETALIATION)
|
||||
&& !stack->hasBonusOfType(Bonus::BLOCKS_RANGED_RETALIATION)
|
||||
if (destinationStack->hasBonusOfType(BonusType::RANGED_RETALIATION)
|
||||
&& !stack->hasBonusOfType(BonusType::BLOCKS_RANGED_RETALIATION)
|
||||
&& destinationStack->ableToRetaliate()
|
||||
&& gs->curB->battleCanShoot(destinationStack, stack->getPosition())
|
||||
&& stack->alive()) //attacker may have died (fire shield)
|
||||
@@ -4844,7 +4844,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
const auto * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
||||
if(attackingHero)
|
||||
{
|
||||
totalRangedAttacks += attackingHero->valOfBonuses(Bonus::HERO_GRANTS_ATTACKS, stack->creatureIndex());
|
||||
totalRangedAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, stack->creatureIndex());
|
||||
}
|
||||
|
||||
|
||||
@@ -4865,7 +4865,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
{
|
||||
auto wrapper = wrapAction(ba);
|
||||
const CStack * shooter = gs->curB->battleGetStackByID(ba.stackNumber);
|
||||
std::shared_ptr<const Bonus> catapultAbility = stack->getBonusLocalFirst(Selector::type()(Bonus::CATAPULT));
|
||||
std::shared_ptr<const Bonus> catapultAbility = stack->getBonusLocalFirst(Selector::type()(BonusType::CATAPULT));
|
||||
if(!catapultAbility || catapultAbility->subtype < 0)
|
||||
{
|
||||
complain("We do not know how to shoot :P");
|
||||
@@ -4874,7 +4874,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
{
|
||||
const CSpell * spell = SpellID(catapultAbility->subtype).toSpell();
|
||||
spells::BattleCast parameters(gs->curB, shooter, spells::Mode::SPELL_LIKE_ATTACK, spell); //We can shot infinitely by catapult
|
||||
auto shotLevel = stack->valOfBonuses(Selector::typeSubtype(Bonus::CATAPULT_EXTRA_SHOTS, catapultAbility->subtype));
|
||||
auto shotLevel = stack->valOfBonuses(Selector::typeSubtype(BonusType::CATAPULT_EXTRA_SHOTS, catapultAbility->subtype));
|
||||
parameters.setSpellLevel(shotLevel);
|
||||
parameters.cast(spellEnv, target);
|
||||
}
|
||||
@@ -4894,7 +4894,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
}
|
||||
|
||||
const battle::Unit * destStack = nullptr;
|
||||
std::shared_ptr<const Bonus> healerAbility = stack->getBonusLocalFirst(Selector::type()(Bonus::HEALER));
|
||||
std::shared_ptr<const Bonus> healerAbility = stack->getBonusLocalFirst(Selector::type()(BonusType::HEALER));
|
||||
|
||||
if(target.at(0).unitValue)
|
||||
destStack = target.at(0).unitValue;
|
||||
@@ -4922,8 +4922,8 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
const CStack * stack = gs->curB->battleGetStackByID(ba.stackNumber);
|
||||
SpellID spellID = SpellID(ba.actionSubtype);
|
||||
|
||||
std::shared_ptr<const Bonus> randSpellcaster = stack->getBonus(Selector::type()(Bonus::RANDOM_SPELLCASTER));
|
||||
std::shared_ptr<const Bonus> spellcaster = stack->getBonus(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
|
||||
std::shared_ptr<const Bonus> randSpellcaster = stack->getBonus(Selector::type()(BonusType::RANDOM_SPELLCASTER));
|
||||
std::shared_ptr<const Bonus> spellcaster = stack->getBonus(Selector::typeSubtype(BonusType::SPELLCASTER, spellID));
|
||||
|
||||
//TODO special bonus for genies ability
|
||||
if (randSpellcaster && battleGetRandomStackSpell(getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_AIMED) < 0)
|
||||
@@ -5147,7 +5147,7 @@ bool CGameHandler::makeCustomAction(BattleAction & ba)
|
||||
|
||||
void CGameHandler::stackEnchantedTrigger(const CStack * st)
|
||||
{
|
||||
auto bl = *(st->getBonuses(Selector::type()(Bonus::ENCHANTED)));
|
||||
auto bl = *(st->getBonuses(Selector::type()(BonusType::ENCHANTED)));
|
||||
for(auto b : bl)
|
||||
{
|
||||
const CSpell * sp = SpellID(b->subtype).toSpell();
|
||||
@@ -5187,10 +5187,10 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
||||
if (st->alive())
|
||||
{
|
||||
//unbind
|
||||
if (st->hasBonus(Selector::type()(Bonus::BIND_EFFECT)))
|
||||
if (st->hasBonus(Selector::type()(BonusType::BIND_EFFECT)))
|
||||
{
|
||||
bool unbind = true;
|
||||
BonusList bl = *(st->getBonuses(Selector::type()(Bonus::BIND_EFFECT)));
|
||||
BonusList bl = *(st->getBonuses(Selector::type()(BonusType::BIND_EFFECT)));
|
||||
auto adjacent = gs->curB->battleAdjacentUnits(st);
|
||||
|
||||
for (auto b : bl)
|
||||
@@ -5218,42 +5218,42 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
||||
}
|
||||
}
|
||||
|
||||
if (st->hasBonusOfType(Bonus::POISON))
|
||||
if (st->hasBonusOfType(BonusType::POISON))
|
||||
{
|
||||
std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON).And(Selector::type()(Bonus::STACK_HEALTH)));
|
||||
std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, SpellID::POISON).And(Selector::type()(BonusType::STACK_HEALTH)));
|
||||
if (b) //TODO: what if not?...
|
||||
{
|
||||
bte.val = std::max (b->val - 10, -(st->valOfBonuses(Bonus::POISON)));
|
||||
bte.val = std::max (b->val - 10, -(st->valOfBonuses(BonusType::POISON)));
|
||||
if (bte.val < b->val) //(negative) poison effect increases - update it
|
||||
{
|
||||
bte.effect = Bonus::POISON;
|
||||
bte.effect = vstd::to_underlying(BonusType::POISON);
|
||||
sendAndApply(&bte);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(st->hasBonusOfType(Bonus::MANA_DRAIN) && !st->drainedMana)
|
||||
if(st->hasBonusOfType(BonusType::MANA_DRAIN) && !st->drainedMana)
|
||||
{
|
||||
const PlayerColor opponent = gs->curB->otherPlayer(gs->curB->battleGetOwner(st));
|
||||
const CGHeroInstance * opponentHero = gs->curB->getHero(opponent);
|
||||
if(opponentHero)
|
||||
{
|
||||
ui32 manaDrained = st->valOfBonuses(Bonus::MANA_DRAIN);
|
||||
ui32 manaDrained = st->valOfBonuses(BonusType::MANA_DRAIN);
|
||||
vstd::amin(manaDrained, opponentHero->mana);
|
||||
if(manaDrained)
|
||||
{
|
||||
bte.effect = Bonus::MANA_DRAIN;
|
||||
bte.effect = vstd::to_underlying(BonusType::MANA_DRAIN);
|
||||
bte.val = manaDrained;
|
||||
bte.additionalInfo = opponentHero->id.getNum(); //for sanity
|
||||
sendAndApply(&bte);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st->isLiving() && !st->hasBonusOfType(Bonus::FEARLESS))
|
||||
if (st->isLiving() && !st->hasBonusOfType(BonusType::FEARLESS))
|
||||
{
|
||||
bool fearsomeCreature = false;
|
||||
for (CStack * stack : gs->curB->stacks)
|
||||
{
|
||||
if (battleMatchOwner(st, stack) && stack->alive() && stack->hasBonusOfType(Bonus::FEAR))
|
||||
if (battleMatchOwner(st, stack) && stack->alive() && stack->hasBonusOfType(BonusType::FEAR))
|
||||
{
|
||||
fearsomeCreature = true;
|
||||
break;
|
||||
@@ -5263,12 +5263,12 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
||||
{
|
||||
if (getRandomGenerator().nextInt(99) < 10) //fixed 10%
|
||||
{
|
||||
bte.effect = Bonus::FEAR;
|
||||
bte.effect = vstd::to_underlying(BonusType::FEAR);
|
||||
sendAndApply(&bte);
|
||||
}
|
||||
}
|
||||
}
|
||||
BonusList bl = *(st->getBonuses(Selector::type()(Bonus::ENCHANTER)));
|
||||
BonusList bl = *(st->getBonuses(Selector::type()(BonusType::ENCHANTER)));
|
||||
int side = gs->curB->whatSide(st->unitOwner());
|
||||
if(st->canCast() && gs->curB->battleGetEnchanterCounter(side) == 0)
|
||||
{
|
||||
@@ -5828,7 +5828,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGameHandler::attackCasting(bool ranged, Bonus::BonusType attackMode, const battle::Unit * attacker, const battle::Unit * defender)
|
||||
void CGameHandler::attackCasting(bool ranged, BonusType attackMode, const battle::Unit * attacker, const battle::Unit * defender)
|
||||
{
|
||||
if(attacker->hasBonusOfType(attackMode))
|
||||
{
|
||||
@@ -5898,7 +5898,7 @@ void CGameHandler::attackCasting(bool ranged, Bonus::BonusType attackMode, const
|
||||
|
||||
void CGameHandler::handleAttackBeforeCasting(bool ranged, const CStack * attacker, const CStack * defender)
|
||||
{
|
||||
attackCasting(ranged, Bonus::SPELL_BEFORE_ATTACK, attacker, defender); //no death stare / acid breath needed?
|
||||
attackCasting(ranged, BonusType::SPELL_BEFORE_ATTACK, attacker, defender); //no death stare / acid breath needed?
|
||||
}
|
||||
|
||||
void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker, const CStack * defender)
|
||||
@@ -5906,7 +5906,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
if(!attacker->alive() || !defender->alive()) // can be already dead
|
||||
return;
|
||||
|
||||
attackCasting(ranged, Bonus::SPELL_AFTER_ATTACK, attacker, defender);
|
||||
attackCasting(ranged, BonusType::SPELL_AFTER_ATTACK, attacker, defender);
|
||||
|
||||
if(!defender->alive())
|
||||
{
|
||||
@@ -5914,13 +5914,13 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
return;
|
||||
}
|
||||
|
||||
if(attacker->hasBonusOfType(Bonus::DEATH_STARE))
|
||||
if(attacker->hasBonusOfType(BonusType::DEATH_STARE))
|
||||
{
|
||||
// mechanics of Death Stare as in H3:
|
||||
// each gorgon have 10% chance to kill (counted separately in H3) -> binomial distribution
|
||||
//original formula x = min(x, (gorgons_count + 9)/10);
|
||||
|
||||
double chanceToKill = attacker->valOfBonuses(Bonus::DEATH_STARE, 0) / 100.0f;
|
||||
double chanceToKill = attacker->valOfBonuses(BonusType::DEATH_STARE, 0) / 100.0f;
|
||||
vstd::amin(chanceToKill, 1); //cap at 100%
|
||||
|
||||
std::binomial_distribution<> distribution(attacker->getCount(), chanceToKill);
|
||||
@@ -5931,7 +5931,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
int maxToKill = static_cast<int>((attacker->getCount() + cap - 1) / cap); //not much more than chance * count
|
||||
vstd::amin(staredCreatures, maxToKill);
|
||||
|
||||
staredCreatures += (attacker->level() * attacker->valOfBonuses(Bonus::DEATH_STARE, 1)) / defender->level();
|
||||
staredCreatures += (attacker->level() * attacker->valOfBonuses(BonusType::DEATH_STARE, 1)) / defender->level();
|
||||
if(staredCreatures)
|
||||
{
|
||||
//TODO: death stare was not originally available for multiple-hex attacks, but...
|
||||
@@ -5951,7 +5951,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
return;
|
||||
|
||||
int64_t acidDamage = 0;
|
||||
TConstBonusListPtr acidBreath = attacker->getBonuses(Selector::type()(Bonus::ACID_BREATH));
|
||||
TConstBonusListPtr acidBreath = attacker->getBonuses(Selector::type()(BonusType::ACID_BREATH));
|
||||
for(const auto & b : *acidBreath)
|
||||
{
|
||||
if(b->additionalInfo[0] > getRandomGenerator().nextInt(99))
|
||||
@@ -5976,15 +5976,15 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
if(!defender->alive())
|
||||
return;
|
||||
|
||||
if(attacker->hasBonusOfType(Bonus::TRANSMUTATION) && defender->isLiving()) //transmutation mechanics, similar to WoG werewolf ability
|
||||
if(attacker->hasBonusOfType(BonusType::TRANSMUTATION) && defender->isLiving()) //transmutation mechanics, similar to WoG werewolf ability
|
||||
{
|
||||
double chanceToTrigger = attacker->valOfBonuses(Bonus::TRANSMUTATION) / 100.0f;
|
||||
double chanceToTrigger = attacker->valOfBonuses(BonusType::TRANSMUTATION) / 100.0f;
|
||||
vstd::amin(chanceToTrigger, 1); //cap at 100%
|
||||
|
||||
if(getRandomGenerator().getDoubleRange(0, 1)() > chanceToTrigger)
|
||||
return;
|
||||
|
||||
int bonusAdditionalInfo = attacker->getBonus(Selector::type()(Bonus::TRANSMUTATION))->additionalInfo[0];
|
||||
int bonusAdditionalInfo = attacker->getBonus(Selector::type()(BonusType::TRANSMUTATION))->additionalInfo[0];
|
||||
|
||||
if(defender->unitType()->getId() == bonusAdditionalInfo ||
|
||||
(bonusAdditionalInfo == CAddInfo::NONE && defender->unitType()->getId() == attacker->unitType()->getId()))
|
||||
@@ -6001,9 +6001,9 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
else
|
||||
resurrectInfo.type = attacker->creatureId();
|
||||
|
||||
if(attacker->hasBonusOfType((Bonus::TRANSMUTATION), 0))
|
||||
resurrectInfo.count = std::max((defender->getCount() * defender->MaxHealth()) / resurrectInfo.type.toCreature()->MaxHealth(), 1u);
|
||||
else if (attacker->hasBonusOfType((Bonus::TRANSMUTATION), 1))
|
||||
if(attacker->hasBonusOfType((BonusType::TRANSMUTATION), 0))
|
||||
resurrectInfo.count = std::max((defender->getCount() * defender->getMaxHealth()) / resurrectInfo.type.toCreature()->getMaxHealth(), 1u);
|
||||
else if (attacker->hasBonusOfType((BonusType::TRANSMUTATION), 1))
|
||||
resurrectInfo.count = defender->getCount();
|
||||
else
|
||||
return; //wrong subtype
|
||||
@@ -6018,21 +6018,21 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
sendAndApply(&addUnits);
|
||||
}
|
||||
|
||||
if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 0) || attacker->hasBonusOfType(Bonus::DESTRUCTION, 1))
|
||||
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, 0) || attacker->hasBonusOfType(BonusType::DESTRUCTION, 1))
|
||||
{
|
||||
double chanceToTrigger = 0;
|
||||
int amountToDie = 0;
|
||||
|
||||
if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 0)) //killing by percentage
|
||||
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, 0)) //killing by percentage
|
||||
{
|
||||
chanceToTrigger = attacker->valOfBonuses(Bonus::DESTRUCTION, 0) / 100.0f;
|
||||
int percentageToDie = attacker->getBonus(Selector::type()(Bonus::DESTRUCTION).And(Selector::subtype()(0)))->additionalInfo[0];
|
||||
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, 0) / 100.0f;
|
||||
int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(0)))->additionalInfo[0];
|
||||
amountToDie = static_cast<int>(defender->getCount() * percentageToDie * 0.01f);
|
||||
}
|
||||
else if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 1)) //killing by count
|
||||
else if(attacker->hasBonusOfType(BonusType::DESTRUCTION, 1)) //killing by count
|
||||
{
|
||||
chanceToTrigger = attacker->valOfBonuses(Bonus::DESTRUCTION, 1) / 100.0f;
|
||||
amountToDie = attacker->getBonus(Selector::type()(Bonus::DESTRUCTION).And(Selector::subtype()(1)))->additionalInfo[0];
|
||||
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, 1) / 100.0f;
|
||||
amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(1)))->additionalInfo[0];
|
||||
}
|
||||
|
||||
vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100%
|
||||
@@ -6043,7 +6043,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
BattleStackAttacked bsa;
|
||||
bsa.attackerID = -1;
|
||||
bsa.stackAttacked = defender->unitId();
|
||||
bsa.damageAmount = amountToDie * defender->MaxHealth();
|
||||
bsa.damageAmount = amountToDie * defender->getMaxHealth();
|
||||
bsa.flags = BattleStackAttacked::SPELL_EFFECT;
|
||||
bsa.spellID = SpellID::SLAYER;
|
||||
defender->prepareAttacked(bsa, getRandomGenerator());
|
||||
@@ -6370,9 +6370,9 @@ void CGameHandler::runBattle()
|
||||
|
||||
for (CStack * stack : initialStacks)
|
||||
{
|
||||
if (stack->hasBonusOfType(Bonus::SUMMON_GUARDIANS))
|
||||
if (stack->hasBonusOfType(BonusType::SUMMON_GUARDIANS))
|
||||
{
|
||||
std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type()(Bonus::SUMMON_GUARDIANS));
|
||||
std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type()(BonusType::SUMMON_GUARDIANS));
|
||||
auto accessibility = getAccesibility();
|
||||
CreatureID creatureData = CreatureID(summonInfo->subtype);
|
||||
std::vector<BattleHex> targetHexes;
|
||||
@@ -6417,7 +6417,7 @@ void CGameHandler::runBattle()
|
||||
auto h = gs->curB->battleGetFightingHero(i);
|
||||
if (h)
|
||||
{
|
||||
TConstBonusListPtr bl = h->getBonuses(Selector::type()(Bonus::OPENING_BATTLE_SPELL));
|
||||
TConstBonusListPtr bl = h->getBonuses(Selector::type()(BonusType::OPENING_BATTLE_SPELL));
|
||||
|
||||
for (auto b : *bl)
|
||||
{
|
||||
@@ -6485,11 +6485,11 @@ void CGameHandler::runBattle()
|
||||
{
|
||||
BattleTriggerEffect bte;
|
||||
bte.stackID = stack->unitId();
|
||||
bte.effect = Bonus::HP_REGENERATION;
|
||||
bte.effect = vstd::to_underlying(BonusType::HP_REGENERATION);
|
||||
|
||||
const int32_t lostHealth = stack->MaxHealth() - stack->getFirstHPleft();
|
||||
if(stack->hasBonusOfType(Bonus::HP_REGENERATION))
|
||||
bte.val = std::min(lostHealth, stack->valOfBonuses(Bonus::HP_REGENERATION));
|
||||
const int32_t lostHealth = stack->getMaxHealth() - stack->getFirstHPleft();
|
||||
if(stack->hasBonusOfType(BonusType::HP_REGENERATION))
|
||||
bte.val = std::min(lostHealth, stack->valOfBonuses(BonusType::HP_REGENERATION));
|
||||
|
||||
if(bte.val) // anything to heal
|
||||
sendAndApply(&bte);
|
||||
@@ -6517,7 +6517,7 @@ void CGameHandler::runBattle()
|
||||
sendAndApply(&removeGhosts);
|
||||
|
||||
// check for bad morale => freeze
|
||||
int nextStackMorale = next->MoraleVal();
|
||||
int nextStackMorale = next->moraleVal();
|
||||
if(!next->hadMorale && !next->waited() && nextStackMorale < 0)
|
||||
{
|
||||
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_BAD_MORALE_DICE);
|
||||
@@ -6536,7 +6536,7 @@ void CGameHandler::runBattle()
|
||||
}
|
||||
}
|
||||
|
||||
if (next->hasBonusOfType(Bonus::ATTACKS_NEAREST_CREATURE)) //while in berserk
|
||||
if (next->hasBonusOfType(BonusType::ATTACKS_NEAREST_CREATURE)) //while in berserk
|
||||
{
|
||||
logGlobal->trace("Handle Berserk effect");
|
||||
std::pair<const battle::Unit *, BattleHex> attackInfo = curB.getNearestStack(next);
|
||||
@@ -6564,7 +6564,7 @@ void CGameHandler::runBattle()
|
||||
const int stackCreatureId = next->unitType()->getId();
|
||||
|
||||
if ((stackCreatureId == CreatureID::ARROW_TOWERS || stackCreatureId == CreatureID::BALLISTA)
|
||||
&& (!curOwner || getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(Bonus::MANUAL_CONTROL, stackCreatureId)))
|
||||
&& (!curOwner || getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, stackCreatureId)))
|
||||
{
|
||||
BattleAction attack;
|
||||
attack.actionType = EActionType::SHOOT;
|
||||
@@ -6609,7 +6609,7 @@ void CGameHandler::runBattle()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!curOwner || getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(Bonus::MANUAL_CONTROL, CreatureID::CATAPULT))
|
||||
if (!curOwner || getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, CreatureID::CATAPULT))
|
||||
{
|
||||
BattleAction attack;
|
||||
attack.actionType = EActionType::CATAPULT;
|
||||
@@ -6634,7 +6634,7 @@ void CGameHandler::runBattle()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!curOwner || getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(Bonus::MANUAL_CONTROL, CreatureID::FIRST_AID_TENT))
|
||||
if (!curOwner || getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, CreatureID::FIRST_AID_TENT))
|
||||
{
|
||||
RandomGeneratorUtil::randomShuffle(possibleStacks, getRandomGenerator());
|
||||
const CStack * toBeHealed = possibleStacks.front();
|
||||
@@ -6703,7 +6703,7 @@ void CGameHandler::runBattle()
|
||||
if(next != nullptr)
|
||||
{
|
||||
//check for good morale
|
||||
nextStackMorale = next->MoraleVal();
|
||||
nextStackMorale = next->moraleVal();
|
||||
if( !battleResult.get()
|
||||
&& !next->hadMorale
|
||||
&& !next->defending
|
||||
@@ -6719,7 +6719,7 @@ void CGameHandler::runBattle()
|
||||
{
|
||||
BattleTriggerEffect bte;
|
||||
bte.stackID = next->unitId();
|
||||
bte.effect = Bonus::MORALE;
|
||||
bte.effect = vstd::to_underlying(BonusType::MORALE);
|
||||
bte.val = 1;
|
||||
bte.additionalInfo = 0;
|
||||
sendAndApply(&bte); //play animation
|
||||
@@ -6871,7 +6871,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
||||
///Give all spells with bonus (to allow banned spells)
|
||||
GiveBonus giveBonus(GiveBonus::ETarget::HERO);
|
||||
giveBonus.id = hero->id.getNum();
|
||||
giveBonus.bonus = Bonus(Bonus::PERMANENT, Bonus::SPELLS_OF_LEVEL, Bonus::OTHER, 0, 0);
|
||||
giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, 0);
|
||||
//start with level 0 to skip abilities
|
||||
for (int level = 1; level <= GameConstants::SPELL_LEVELS; level++)
|
||||
{
|
||||
@@ -7016,9 +7016,9 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
||||
sendAndApply(&smp);
|
||||
|
||||
GiveBonus gb(GiveBonus::ETarget::HERO);
|
||||
gb.bonus.type = Bonus::FREE_SHIP_BOARDING;
|
||||
gb.bonus.duration = Bonus::ONE_DAY;
|
||||
gb.bonus.source = Bonus::OTHER;
|
||||
gb.bonus.type = BonusType::FREE_SHIP_BOARDING;
|
||||
gb.bonus.duration = BonusDuration::ONE_DAY;
|
||||
gb.bonus.source = BonusSource::OTHER;
|
||||
gb.id = hero->id.getNum();
|
||||
giveHeroBonus(&gb);
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ public:
|
||||
void newTurn();
|
||||
void handleAttackBeforeCasting(bool ranged, const CStack * attacker, const CStack * defender);
|
||||
void handleAfterAttackCasting(bool ranged, const CStack * attacker, const CStack * defender);
|
||||
void attackCasting(bool ranged, Bonus::BonusType attackMode, const battle::Unit * attacker, const battle::Unit * defender);
|
||||
void attackCasting(bool ranged, BonusType attackMode, const battle::Unit * attacker, const battle::Unit * defender);
|
||||
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, const std::vector<ArtifactPosition> & slot);
|
||||
void spawnWanderingMonsters(CreatureID creatureID);
|
||||
void handleCheatCode(std::string & cheat, PlayerColor player, const CGHeroInstance * hero, const CGTownInstance * town, bool & cheated);
|
||||
|
||||
Reference in New Issue
Block a user