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

Block spellcasting if 0 creatures will be raised

This commit is contained in:
Ivan Savenko 2024-04-07 18:37:17 +03:00
parent 0a80c6c27b
commit 5dcef193a3
4 changed files with 66 additions and 35 deletions

View File

@ -25,6 +25,30 @@ namespace spells
namespace effects
{
int DemonSummon::raisedCreatureAmount(const Mechanics * m, const battle::Unit * unit) const
{
if(!unit || unit->alive() || unit->isGhost())
return 0;
const auto *creatureType = creature.toEntity(m->creatures());
int32_t deadCount = unit->unitBaseAmount();
int32_t deadTotalHealth = unit->getTotalHealth();
int32_t raisedMaxHealth = creatureType->getMaxHealth();
int32_t raisedTotalHealth = m->applySpellBonus(m->getEffectValue(), unit);
// Can't raise stack with more HP than original stack
int32_t maxAmountFromHealth = deadTotalHealth / raisedMaxHealth;
// Can't raise stack with more creatures than original stack
int32_t maxAmountFromAmount = deadCount;
// Can't raise stack with more HP than our spellpower
int32_t maxAmountFromSpellpower = raisedTotalHealth / raisedMaxHealth;
int32_t finalAmount = std::min( { maxAmountFromHealth, maxAmountFromAmount, maxAmountFromSpellpower } );
return finalAmount;
}
void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
{
BattleUnitsChanged pack;
@ -49,21 +73,7 @@ void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const Effe
break;
}
const auto *creatureType = creature.toEntity(m->creatures());
int32_t deadCount = targetStack->unitBaseAmount();
int32_t deadTotalHealth = targetStack->getTotalHealth();
int32_t raisedMaxHealth = creatureType->getMaxHealth();
int32_t raisedTotalHealth = m->applySpellBonus(m->getEffectValue(), targetStack);
// Can't raise stack with more HP than original stack
int32_t maxAmountFromHealth = deadTotalHealth / raisedMaxHealth;
// Can't raise stack with more creatures than original stack
int32_t maxAmountFromAmount = deadCount;
// Can't raise stack with more HP than our spellpower
int32_t maxAmountFromSpellpower = raisedTotalHealth / raisedMaxHealth;
int32_t finalAmount = std::min( { maxAmountFromHealth, maxAmountFromAmount, maxAmountFromSpellpower } );
int32_t finalAmount = raisedCreatureAmount(m, targetStack);
if(finalAmount < 1)
{
@ -111,9 +121,7 @@ bool DemonSummon::isValidTarget(const Mechanics * m, const battle::Unit * unit)
if (unit->isGhost())
return false;
const auto *creatureType = creature.toEntity(m->creatures());
if (unit->getTotalHealth() < creatureType->getMaxHealth())
if (raisedCreatureAmount(m, unit) == 0)
return false;
return m->isReceptive(unit);

View File

@ -30,7 +30,9 @@ protected:
void serializeJsonUnitEffect(JsonSerializeFormat & handler) override final;
private:
CreatureID creature = CreatureID(0);
int32_t raisedCreatureAmount(const Mechanics * m, const battle::Unit * unit) const;
CreatureID creature;
bool permanent = false;
};

View File

@ -48,6 +48,12 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const
return m->adaptGenericProblem(problem);
}
if (summonedCreatureAmount(m) == 0)
{
logMod->debug("Attempt to summon zero creatures!");
return m->adaptGenericProblem(problem);
}
if(exclusive)
{
//check if there are summoned creatures of other type
@ -88,11 +94,34 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const
return true;
}
int32_t Summon::summonedCreatureHealth(const Mechanics * m, const battle::Unit * unit) const
{
auto valueWithBonus = m->applySpecificSpellBonus(m->calculateRawEffectValue(0, m->getEffectPower()));
if(summonByHealth)
return valueWithBonus;
else
return valueWithBonus * unit->getMaxHealth();
}
int32_t Summon::summonedCreatureAmount(const Mechanics * m) const
{
auto valueWithBonus = m->applySpecificSpellBonus(m->calculateRawEffectValue(0, m->getEffectPower()));
if(summonByHealth)
{
const auto *creatureType = creature.toEntity(m->creatures());
auto creatureMaxHealth = creatureType->getMaxHealth();
return valueWithBonus / creatureMaxHealth;
}
else
{
return valueWithBonus;
}
}
void Summon::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
{
//new feature - percentage bonus
auto valueWithBonus = m->applySpecificSpellBonus(m->calculateRawEffectValue(0, m->getEffectPower()));//TODO: consider use base power too
BattleUnitsChanged pack;
pack.battleID = m->battle()->getBattle()->getBattleID();
@ -102,25 +131,14 @@ void Summon::apply(ServerCallback * server, const Mechanics * m, const EffectTar
{
const battle::Unit * summoned = dest.unitValue;
std::shared_ptr<battle::Unit> state = summoned->acquire();
int64_t healthValue = (summonByHealth ? valueWithBonus : (valueWithBonus * summoned->getMaxHealth()));
int64_t healthValue = summonedCreatureHealth(m, summoned);
state->heal(healthValue, EHealLevel::OVERHEAL, (permanent ? EHealPower::PERMANENT : EHealPower::ONE_BATTLE));
pack.changedStacks.emplace_back(summoned->unitId(), UnitChanges::EOperation::RESET_STATE);
state->save(pack.changedStacks.back().data);
}
else
{
int32_t amount = 0;
if(summonByHealth)
{
const auto *creatureType = creature.toEntity(m->creatures());
auto creatureMaxHealth = creatureType->getMaxHealth();
amount = static_cast<int32_t>(valueWithBonus / creatureMaxHealth);
}
else
{
amount = static_cast<int32_t>(valueWithBonus);
}
int32_t amount = summonedCreatureAmount(m);
if(amount < 1)
{

View File

@ -38,6 +38,9 @@ protected:
void serializeJsonEffect(JsonSerializeFormat & handler) override final;
private:
int32_t summonedCreatureAmount(const Mechanics * m) const;
int32_t summonedCreatureHealth(const Mechanics * m, const battle::Unit * unit) const;
CreatureID creature;
bool permanent = false;