1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Fixed all issues with Resurrection: #123, #1358

This commit is contained in:
DjWarmonger 2013-07-27 19:01:31 +00:00
parent b36be10e30
commit 5f310aa20f
7 changed files with 44 additions and 46 deletions

View File

@ -1750,16 +1750,6 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
for (Bonus * spellBonus : spellBonuses)
{
spell = CGI->spellh->spells[spellBonus->subtype];
if (spell->isRisingSpell())
{
possibleActions.push_back (RISING_SPELL);
}
//possibleActions.push_back (NO_LOCATION);
//possibleActions.push_back (ANY_LOCATION);
//TODO: allow stacks cast aimed spells
//possibleActions.push_back (OTHER_SPELL);
else
{
switch (spellBonus->subtype)
{
case SpellID::REMOVE_OBSTACLE:
@ -1769,7 +1759,6 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
possibleActions.push_back (selectionTypeByPositiveness (*spell));
break;
}
}
}
std::sort(possibleActions.begin(), possibleActions.end());
@ -2194,13 +2183,18 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
legalAction = true;
break;
case FRIENDLY_CREATURE_SPELL:
if (shere && shere->alive() && ourStack && isCastingPossibleHere (sactive, shere, myNumber))
legalAction = true;
break;
case RISING_SPELL:
if (shere && shere->canBeHealed() && ourStack && isCastingPossibleHere (sactive, shere, myNumber)) //TODO: at least one stack has to be raised by resurrection / animate dead
{
if (isCastingPossibleHere (sactive, shere, myNumber)); //need to be called before sp is determined
{
bool rise = false; //TODO: can you imagine rising hostile creatures?
sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo];
if (sp && sp->isRisingSpell())
rise = true;
if (shere && (shere->alive() || rise) && ourStack)
legalAction = true;
}
break;
}
case RANDOM_GENIE_SPELL:
{
if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures
@ -2379,7 +2373,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
break;
case HOSTILE_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
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s
switch (sp->id)
@ -2452,7 +2445,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
{
case HOSTILE_CREATURE_SPELL:
case FRIENDLY_CREATURE_SPELL:
case RISING_SPELL:
case RANDOM_GENIE_SPELL:
cursorFrame = ECursor::COMBAT_BLOCKED;
consoleMsg = CGI->generaltexth->allTexts[23];

View File

@ -112,7 +112,7 @@ void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const
for(auto & elem : stacks)//setting casualties
{
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);
if(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)
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;
if (spell->id == SpellID::SACRIFICE && sacrificedStack)
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));
}
//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));
}
//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];
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);
counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
casts = valOfBonuses(Bonus::CASTS);
resurrected = 0;
}
ui32 CStack::level() const

View File

@ -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
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)
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?
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;
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)
si16 shots; //how many shots left
ui8 casts; //how many casts left
TQuantity resurrected; // these units will be taken back after battle is over
std::set<EBattleStackState::EBattleStackState> state;
//overrides
@ -218,7 +215,7 @@ public:
h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this);
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
& shots & casts & count;
& shots & casts & count & resurrected;
const CArmedInstance *army = (base ? base->armyObj : nullptr);
SlotID slot = (base ? base->armyObj->findStack(base) : SlotID());

View File

@ -1562,7 +1562,8 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C
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;
}
@ -1663,7 +1664,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
{
const CGHeroInstance * caster = battleGetFightingHero(side);
bool targetExists = false;
for(const CStack * stack : battleAliveStacks())
for(const CStack * stack : battleGetAllStacks()) //dead stacks will be immune anyway
{
switch (spell->positiveness)
{
@ -1941,8 +1942,9 @@ std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell *
const ui8 attackerSide = playerToSide(attackerOwner) == 1;
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
//fixme: what about other rising spells (Sacrifice) ?
const bool onlyAlive = !spell->isRisingSpell(); //when casting resurrection or animate dead we should be allow to select dead stack
//TODO: more generic solution for mass spells
if(spell->id == SpellID::DEATH_RIPPLE || spell->id == SpellID::DESTROY_UNDEAD || spell->id == SpellID::ARMAGEDDON)
{
for(const CStack *stack : battleGetAllStacks())

View File

@ -260,6 +260,9 @@ public:
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 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
SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;

View File

@ -1403,12 +1403,12 @@ DLL_LINKAGE void StacksHealedOrResurrected::applyGs( CGameState *gs )
if(resurrected)
{
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 res = std::min( elem.healedHP / changedStack->MaxHealth() , changedStack->baseAmount - changedStack->count );
changedStack->count += res;
if(elem.lowLevelResurrection)
changedStack->resurrected += res;
changedStack->firstHPleft += elem.healedHP - res * changedStack->MaxHealth();
if(changedStack->firstHPleft > changedStack->MaxHealth())
{

View File

@ -6266,6 +6266,9 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks
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))
{
StackLocation sl(army, st->slot);