mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
parent
b36be10e30
commit
5f310aa20f
@ -1750,25 +1750,14 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
|
|||||||
for (Bonus * spellBonus : spellBonuses)
|
for (Bonus * spellBonus : spellBonuses)
|
||||||
{
|
{
|
||||||
spell = CGI->spellh->spells[spellBonus->subtype];
|
spell = CGI->spellh->spells[spellBonus->subtype];
|
||||||
if (spell->isRisingSpell())
|
switch (spellBonus->subtype)
|
||||||
{
|
{
|
||||||
possibleActions.push_back (RISING_SPELL);
|
case SpellID::REMOVE_OBSTACLE:
|
||||||
}
|
possibleActions.push_back (OBSTACLE);
|
||||||
//possibleActions.push_back (NO_LOCATION);
|
break;
|
||||||
//possibleActions.push_back (ANY_LOCATION);
|
default:
|
||||||
//TODO: allow stacks cast aimed spells
|
possibleActions.push_back (selectionTypeByPositiveness (*spell));
|
||||||
//possibleActions.push_back (OTHER_SPELL);
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (spellBonus->subtype)
|
|
||||||
{
|
|
||||||
case SpellID::REMOVE_OBSTACLE:
|
|
||||||
possibleActions.push_back (OBSTACLE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
possibleActions.push_back (selectionTypeByPositiveness (*spell));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2194,13 +2183,18 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
legalAction = true;
|
legalAction = true;
|
||||||
break;
|
break;
|
||||||
case FRIENDLY_CREATURE_SPELL:
|
case FRIENDLY_CREATURE_SPELL:
|
||||||
if (shere && shere->alive() && ourStack && isCastingPossibleHere (sactive, shere, myNumber))
|
{
|
||||||
legalAction = true;
|
if (isCastingPossibleHere (sactive, shere, myNumber)); //need to be called before sp is determined
|
||||||
break;
|
{
|
||||||
case RISING_SPELL:
|
bool rise = false; //TODO: can you imagine rising hostile creatures?
|
||||||
if (shere && shere->canBeHealed() && ourStack && isCastingPossibleHere (sactive, shere, myNumber)) //TODO: at least one stack has to be raised by resurrection / animate dead
|
sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo];
|
||||||
legalAction = true;
|
if (sp && sp->isRisingSpell())
|
||||||
|
rise = true;
|
||||||
|
if (shere && (shere->alive() || rise) && ourStack)
|
||||||
|
legalAction = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case RANDOM_GENIE_SPELL:
|
case RANDOM_GENIE_SPELL:
|
||||||
{
|
{
|
||||||
if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures
|
if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures
|
||||||
@ -2379,7 +2373,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
break;
|
break;
|
||||||
case HOSTILE_CREATURE_SPELL:
|
case HOSTILE_CREATURE_SPELL:
|
||||||
case FRIENDLY_CREATURE_SPELL:
|
case FRIENDLY_CREATURE_SPELL:
|
||||||
case RISING_SPELL:
|
|
||||||
sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo]; //necessary if creature has random Genie spell at same time
|
sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo]; //necessary if creature has random Genie spell at same time
|
||||||
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s
|
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s
|
||||||
switch (sp->id)
|
switch (sp->id)
|
||||||
@ -2452,7 +2445,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
{
|
{
|
||||||
case HOSTILE_CREATURE_SPELL:
|
case HOSTILE_CREATURE_SPELL:
|
||||||
case FRIENDLY_CREATURE_SPELL:
|
case FRIENDLY_CREATURE_SPELL:
|
||||||
case RISING_SPELL:
|
|
||||||
case RANDOM_GENIE_SPELL:
|
case RANDOM_GENIE_SPELL:
|
||||||
cursorFrame = ECursor::COMBAT_BLOCKED;
|
cursorFrame = ECursor::COMBAT_BLOCKED;
|
||||||
consoleMsg = CGI->generaltexth->allTexts[23];
|
consoleMsg = CGI->generaltexth->allTexts[23];
|
||||||
|
@ -112,7 +112,7 @@ void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const
|
|||||||
for(auto & elem : stacks)//setting casualties
|
for(auto & elem : stacks)//setting casualties
|
||||||
{
|
{
|
||||||
const CStack * const st = elem;
|
const CStack * const st = elem;
|
||||||
si32 killed = (st->alive() ? st->baseAmount - st->count : st->baseAmount);
|
si32 killed = (st->alive() ? (st->baseAmount - st->count + st->resurrected) : st->baseAmount);
|
||||||
vstd::amax(killed, 0);
|
vstd::amax(killed, 0);
|
||||||
if(killed)
|
if(killed)
|
||||||
casualties[!st->attackerOwned][st->getCreature()->idNumber] += killed;
|
casualties[!st->attackerOwned][st->getCreature()->idNumber] += killed;
|
||||||
@ -161,9 +161,9 @@ CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool at
|
|||||||
}
|
}
|
||||||
|
|
||||||
//All spells casted by hero 9resurrection, cure, sacrifice)
|
//All spells casted by hero 9resurrection, cure, sacrifice)
|
||||||
ui32 BattleInfo::calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack) const
|
ui32 CBattleInfoCallback::calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack) const
|
||||||
{
|
{
|
||||||
bool resurrect = resurrects(spell->id);
|
bool resurrect = spell->isRisingSpell();
|
||||||
int healedHealth;
|
int healedHealth;
|
||||||
if (spell->id == SpellID::SACRIFICE && sacrificedStack)
|
if (spell->id == SpellID::SACRIFICE && sacrificedStack)
|
||||||
healedHealth = (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + sacrificedStack->MaxHealth() + spell->powers[caster->getSpellSchoolLevel(spell)]) * sacrificedStack->count;
|
healedHealth = (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + sacrificedStack->MaxHealth() + spell->powers[caster->getSpellSchoolLevel(spell)]) * sacrificedStack->count;
|
||||||
@ -173,15 +173,15 @@ ui32 BattleInfo::calculateHealedHP(const CGHeroInstance * caster, const CSpell *
|
|||||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
||||||
}
|
}
|
||||||
//Archangel
|
//Archangel
|
||||||
ui32 BattleInfo::calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const
|
ui32 CBattleInfoCallback::calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const
|
||||||
{
|
{
|
||||||
bool resurrect = resurrects(spell->id);
|
bool resurrect = spell->isRisingSpell();
|
||||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
||||||
}
|
}
|
||||||
//Casted by stack, no hero bonus applied
|
//Casted by stack, no hero bonus applied
|
||||||
ui32 BattleInfo::calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const
|
ui32 CBattleInfoCallback::calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const
|
||||||
{
|
{
|
||||||
bool resurrect = resurrects(spell->id);
|
bool resurrect = spell->isRisingSpell();
|
||||||
int healedHealth = usedSpellPower * spell->power + spell->powers[spellSchoolLevel];
|
int healedHealth = usedSpellPower * spell->power + spell->powers[spellSchoolLevel];
|
||||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
||||||
}
|
}
|
||||||
@ -893,6 +893,7 @@ void CStack::postInit()
|
|||||||
shots = getCreature()->valOfBonuses(Bonus::SHOTS);
|
shots = getCreature()->valOfBonuses(Bonus::SHOTS);
|
||||||
counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
||||||
casts = valOfBonuses(Bonus::CASTS);
|
casts = valOfBonuses(Bonus::CASTS);
|
||||||
|
resurrected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui32 CStack::level() const
|
ui32 CStack::level() const
|
||||||
|
@ -125,14 +125,10 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
|
|||||||
CStack * generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
CStack * generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||||
int getIdForNewStack() const; //suggest a currently unused ID that'd suitable for generating a new stack
|
int getIdForNewStack() const; //suggest a currently unused ID that'd suitable for generating a new stack
|
||||||
//std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
//std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
||||||
ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack = nullptr) const; //Sacrifice
|
|
||||||
ui32 calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const; //for Archangel
|
|
||||||
ui32 calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const; //healing spells casted by stacks
|
|
||||||
bool resurrects(SpellID spellid) const; //TODO: move it to spellHandler?
|
bool resurrects(SpellID spellid) const; //TODO: move it to spellHandler?
|
||||||
|
|
||||||
const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player
|
const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player
|
||||||
|
|
||||||
|
|
||||||
std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::vector<const CStack*> affectedCreatures, PlayerColor casterSideOwner, ECastingMode::ECastingMode mode, int usedSpellPower, int spellLevel) const;
|
std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::vector<const CStack*> affectedCreatures, PlayerColor casterSideOwner, ECastingMode::ECastingMode mode, int usedSpellPower, int spellLevel) const;
|
||||||
|
|
||||||
const CStack * battleGetStack(BattleHex pos, bool onlyAlive); //returns stack at given tile
|
const CStack * battleGetStack(BattleHex pos, bool onlyAlive); //returns stack at given tile
|
||||||
@ -165,6 +161,7 @@ public:
|
|||||||
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
||||||
si16 shots; //how many shots left
|
si16 shots; //how many shots left
|
||||||
ui8 casts; //how many casts left
|
ui8 casts; //how many casts left
|
||||||
|
TQuantity resurrected; // these units will be taken back after battle is over
|
||||||
|
|
||||||
std::set<EBattleStackState::EBattleStackState> state;
|
std::set<EBattleStackState::EBattleStackState> state;
|
||||||
//overrides
|
//overrides
|
||||||
@ -218,7 +215,7 @@ public:
|
|||||||
h & static_cast<CBonusSystemNode&>(*this);
|
h & static_cast<CBonusSystemNode&>(*this);
|
||||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
h & static_cast<CStackBasicDescriptor&>(*this);
|
||||||
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
||||||
& shots & casts & count;
|
& shots & casts & count & resurrected;
|
||||||
|
|
||||||
const CArmedInstance *army = (base ? base->armyObj : nullptr);
|
const CArmedInstance *army = (base ? base->armyObj : nullptr);
|
||||||
SlotID slot = (base ? base->armyObj->findStack(base) : SlotID());
|
SlotID slot = (base ? base->armyObj->findStack(base) : SlotID());
|
||||||
|
@ -503,8 +503,8 @@ const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyA
|
|||||||
{
|
{
|
||||||
RETURN_IF_NOT_BATTLE(nullptr);
|
RETURN_IF_NOT_BATTLE(nullptr);
|
||||||
for(auto s : battleGetAllStacks())
|
for(auto s : battleGetAllStacks())
|
||||||
if(vstd::contains(s->getHexes(), pos) && (!onlyAlive || s->alive()))
|
if(vstd::contains(s->getHexes(), pos) && (!onlyAlive || s->alive()))
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1562,7 +1562,8 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C
|
|||||||
|
|
||||||
if (spell->isRisingSpell())
|
if (spell->isRisingSpell())
|
||||||
{
|
{
|
||||||
if (subject->count >= subject->baseAmount) //TODO: calculate potential hp raised
|
auto maxHealth = calculateHealedHP (caster, spell, subject);
|
||||||
|
if (subject->count >= subject->baseAmount || maxHealth < subject->MaxHealth()) //must be able to rise at least one full creature
|
||||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1663,7 +1664,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
|||||||
{
|
{
|
||||||
const CGHeroInstance * caster = battleGetFightingHero(side);
|
const CGHeroInstance * caster = battleGetFightingHero(side);
|
||||||
bool targetExists = false;
|
bool targetExists = false;
|
||||||
for(const CStack * stack : battleAliveStacks())
|
for(const CStack * stack : battleGetAllStacks()) //dead stacks will be immune anyway
|
||||||
{
|
{
|
||||||
switch (spell->positiveness)
|
switch (spell->positiveness)
|
||||||
{
|
{
|
||||||
@ -1941,8 +1942,9 @@ std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell *
|
|||||||
|
|
||||||
const ui8 attackerSide = playerToSide(attackerOwner) == 1;
|
const ui8 attackerSide = playerToSide(attackerOwner) == 1;
|
||||||
const auto attackedHexes = spell->rangeInHexes(destinationTile, skillLevel, attackerSide);
|
const auto attackedHexes = spell->rangeInHexes(destinationTile, skillLevel, attackerSide);
|
||||||
const bool onlyAlive = spell->id != SpellID::RESURRECTION && spell->id != SpellID::ANIMATE_DEAD; //when casting resurrection or animate dead we should be allow to select dead stack
|
const bool onlyAlive = !spell->isRisingSpell(); //when casting resurrection or animate dead we should be allow to select dead stack
|
||||||
//fixme: what about other rising spells (Sacrifice) ?
|
|
||||||
|
//TODO: more generic solution for mass spells
|
||||||
if(spell->id == SpellID::DEATH_RIPPLE || spell->id == SpellID::DESTROY_UNDEAD || spell->id == SpellID::ARMAGEDDON)
|
if(spell->id == SpellID::DEATH_RIPPLE || spell->id == SpellID::DESTROY_UNDEAD || spell->id == SpellID::ARMAGEDDON)
|
||||||
{
|
{
|
||||||
for(const CStack *stack : battleGetAllStacks())
|
for(const CStack *stack : battleGetAllStacks())
|
||||||
|
@ -260,6 +260,9 @@ public:
|
|||||||
std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const;
|
std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const;
|
||||||
ui32 calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const;
|
ui32 calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const;
|
||||||
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
|
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
|
||||||
|
ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack = nullptr) const; //Sacrifice
|
||||||
|
ui32 calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const; //for Archangel
|
||||||
|
ui32 calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const; //healing spells casted by stacks
|
||||||
std::set<const CStack*> getAffectedCreatures(const CSpell * s, int skillLevel, PlayerColor attackerOwner, BattleHex destinationTile); //calculates stack affected by given spell
|
std::set<const CStack*> getAffectedCreatures(const CSpell * s, int skillLevel, PlayerColor attackerOwner, BattleHex destinationTile); //calculates stack affected by given spell
|
||||||
|
|
||||||
SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
|
SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
|
||||||
|
@ -1403,12 +1403,12 @@ DLL_LINKAGE void StacksHealedOrResurrected::applyGs( CGameState *gs )
|
|||||||
if(resurrected)
|
if(resurrected)
|
||||||
{
|
{
|
||||||
changedStack->state.insert(EBattleStackState::ALIVE);
|
changedStack->state.insert(EBattleStackState::ALIVE);
|
||||||
if(elem.lowLevelResurrection)
|
|
||||||
changedStack->state.insert(EBattleStackState::SUMMONED); //TODO: different counter for rised units
|
|
||||||
}
|
}
|
||||||
//int missingHPfirst = changedStack->MaxHealth() - changedStack->firstHPleft;
|
//int missingHPfirst = changedStack->MaxHealth() - changedStack->firstHPleft;
|
||||||
int res = std::min( elem.healedHP / changedStack->MaxHealth() , changedStack->baseAmount - changedStack->count );
|
int res = std::min( elem.healedHP / changedStack->MaxHealth() , changedStack->baseAmount - changedStack->count );
|
||||||
changedStack->count += res;
|
changedStack->count += res;
|
||||||
|
if(elem.lowLevelResurrection)
|
||||||
|
changedStack->resurrected += res;
|
||||||
changedStack->firstHPleft += elem.healedHP - res * changedStack->MaxHealth();
|
changedStack->firstHPleft += elem.healedHP - res * changedStack->MaxHealth();
|
||||||
if(changedStack->firstHPleft > changedStack->MaxHealth())
|
if(changedStack->firstHPleft > changedStack->MaxHealth())
|
||||||
{
|
{
|
||||||
|
@ -6266,6 +6266,9 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
|
|||||||
if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks
|
if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor
|
||||||
|
st->count = std::max (0, st->count - st->resurrected);
|
||||||
|
|
||||||
if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
|
if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
|
||||||
{
|
{
|
||||||
StackLocation sl(army, st->slot);
|
StackLocation sl(army, st->slot);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user