mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
@@ -2163,7 +2163,15 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
break;
|
break;
|
||||||
case RISE_DEMONS:
|
case RISE_DEMONS:
|
||||||
if (shere && ourStack && !shere->alive())
|
if (shere && ourStack && !shere->alive())
|
||||||
legalAction = true;
|
{
|
||||||
|
if(!(shere->hasBonusOfType(Bonus::UNDEAD)
|
||||||
|
|| shere->hasBonusOfType(Bonus::NON_LIVING)
|
||||||
|
|| vstd::contains(shere->state, EBattleStackState::SUMMONED)
|
||||||
|
|| vstd::contains(shere->state, EBattleStackState::CLONED)
|
||||||
|
|| shere->hasBonusOfType(Bonus::SIEGE_WEAPON)
|
||||||
|
))
|
||||||
|
legalAction = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (legalAction)
|
if (legalAction)
|
||||||
@@ -2320,7 +2328,10 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
break;
|
break;
|
||||||
case RISE_DEMONS:
|
case RISE_DEMONS:
|
||||||
cursorType = ECursor::SPELLBOOK;
|
cursorType = ECursor::SPELLBOOK;
|
||||||
realizeAction = [=]{ giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); };
|
realizeAction = [=]
|
||||||
|
{
|
||||||
|
giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID);
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case CATAPULT:
|
case CATAPULT:
|
||||||
cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT;
|
cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT;
|
||||||
|
@@ -469,7 +469,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
|||||||
auto handleWarMachine= [&](int side, ArtifactPosition artslot, CreatureID cretype, BattleHex hex)
|
auto handleWarMachine= [&](int side, ArtifactPosition artslot, CreatureID cretype, BattleHex hex)
|
||||||
{
|
{
|
||||||
if(heroes[side] && heroes[side]->getArt(artslot))
|
if(heroes[side] && heroes[side]->getArt(artslot))
|
||||||
stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID(255), hex));
|
stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID::WAR_MACHINES_SLOT, hex));
|
||||||
};
|
};
|
||||||
|
|
||||||
handleWarMachine(0, ArtifactPosition::MACH1, CreatureID::BALLISTA, 52);
|
handleWarMachine(0, ArtifactPosition::MACH1, CreatureID::BALLISTA, 52);
|
||||||
@@ -526,15 +526,15 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
|||||||
if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL)
|
if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL)
|
||||||
{
|
{
|
||||||
// keep tower
|
// keep tower
|
||||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -2);
|
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -2);
|
||||||
stacks.push_back(stack);
|
stacks.push_back(stack);
|
||||||
|
|
||||||
if (curB->town->fortLevel() >= CGTownInstance::CASTLE)
|
if (curB->town->fortLevel() >= CGTownInstance::CASTLE)
|
||||||
{
|
{
|
||||||
// lower tower + upper tower
|
// lower tower + upper tower
|
||||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -4);
|
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -4);
|
||||||
stacks.push_back(stack);
|
stacks.push_back(stack);
|
||||||
stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -3);
|
stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -3);
|
||||||
stacks.push_back(stack);
|
stacks.push_back(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,7 +712,7 @@ std::shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile)
|
|||||||
|
|
||||||
BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType)
|
BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType)
|
||||||
{
|
{
|
||||||
static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap =
|
static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap =
|
||||||
{
|
{
|
||||||
{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD},
|
{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD},
|
||||||
{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND},
|
{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND},
|
||||||
@@ -1141,7 +1141,7 @@ bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed
|
|||||||
|
|
||||||
ui8 CStack::counterAttacksTotal() const
|
ui8 CStack::counterAttacksTotal() const
|
||||||
{
|
{
|
||||||
//after dispell bonus should remain during current round
|
//after dispell bonus should remain during current round
|
||||||
ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
||||||
vstd::amax(counterAttacksTotalCache, val);
|
vstd::amax(counterAttacksTotalCache, val);
|
||||||
return counterAttacksTotalCache;
|
return counterAttacksTotalCache;
|
||||||
@@ -1183,9 +1183,9 @@ ui32 CStack::calculateHealedHealthPoints(ui32 toHeal, const bool resurrect) cons
|
|||||||
ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) const
|
ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) const
|
||||||
{
|
{
|
||||||
int skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id));
|
int skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id));
|
||||||
|
|
||||||
vstd::abetween(skill, 0, 3);
|
vstd::abetween(skill, 0, 3);
|
||||||
|
|
||||||
return skill;
|
return skill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,10 @@
|
|||||||
#include "spells/CSpellHandler.h"
|
#include "spells/CSpellHandler.h"
|
||||||
|
|
||||||
const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
|
const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
|
||||||
|
const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3);
|
||||||
|
const SlotID SlotID::WAR_MACHINES_SLOT = SlotID(-4);
|
||||||
|
const SlotID SlotID::ARROW_TOWERS_SLOT = SlotID(-5);
|
||||||
|
|
||||||
const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253);
|
const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253);
|
||||||
const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254);
|
const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254);
|
||||||
const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255);
|
const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255);
|
||||||
|
@@ -236,6 +236,9 @@ class SlotID : public BaseForID<SlotID, si32>
|
|||||||
friend class CNonConstInfoCallback;
|
friend class CNonConstInfoCallback;
|
||||||
|
|
||||||
DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER;
|
DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER;
|
||||||
|
DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///<for all summoned creatures, only during battle
|
||||||
|
DLL_LINKAGE static const SlotID WAR_MACHINES_SLOT; ///<for all war machines during battle
|
||||||
|
DLL_LINKAGE static const SlotID ARROW_TOWERS_SLOT; ///<for all arrow towers during battle
|
||||||
|
|
||||||
bool validSlot() const
|
bool validSlot() const
|
||||||
{
|
{
|
||||||
@@ -443,11 +446,11 @@ namespace ESpellCastProblem
|
|||||||
|
|
||||||
namespace ECastingMode
|
namespace ECastingMode
|
||||||
{
|
{
|
||||||
enum ECastingMode
|
enum ECastingMode
|
||||||
{
|
{
|
||||||
HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
|
HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
|
||||||
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING,
|
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING,
|
||||||
SPELL_LIKE_ATTACK,
|
SPELL_LIKE_ATTACK,
|
||||||
PASSIVE_CASTING//f.e. opening battle spells
|
PASSIVE_CASTING//f.e. opening battle spells
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1633,7 +1633,7 @@ DLL_LINKAGE void BattleStackAdded::applyGs(CGameState *gs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CStackBasicDescriptor csbd(creID, amount);
|
CStackBasicDescriptor csbd(creID, amount);
|
||||||
CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID(255), pos); //TODO: netpacks?
|
CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks?
|
||||||
if (summoned)
|
if (summoned)
|
||||||
addedStack->state.insert(EBattleStackState::SUMMONED);
|
addedStack->state.insert(EBattleStackState::SUMMONED);
|
||||||
|
|
||||||
|
@@ -662,8 +662,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
|||||||
sendAndApply(&cs);
|
sendAndApply(&cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
cab1.takeFromArmy(this);
|
cab1.updateArmy(this);
|
||||||
cab2.takeFromArmy(this); //take casualties after battle is deleted
|
cab2.updateArmy(this); //take casualties after battle is deleted
|
||||||
|
|
||||||
//if one hero has lost we will erase him
|
//if one hero has lost we will erase him
|
||||||
if(battleResult.data->winner!=0 && hero1)
|
if(battleResult.data->winner!=0 && hero1)
|
||||||
@@ -3924,18 +3924,16 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
//TODO: From Strategija:
|
//TODO: From Strategija:
|
||||||
//Summon Demon is a level 2 spell.
|
//Summon Demon is a level 2 spell.
|
||||||
{
|
{
|
||||||
StartAction start_action(ba);
|
|
||||||
sendAndApply(&start_action);
|
|
||||||
|
|
||||||
const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber),
|
const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber),
|
||||||
*destStack = gs->curB->battleGetStackByPos(ba.destinationTile, false);
|
*destStack = gs->curB->battleGetStackByPos(ba.destinationTile, false);
|
||||||
|
|
||||||
|
CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
|
||||||
BattleStackAdded bsa;
|
BattleStackAdded bsa;
|
||||||
bsa.attacker = summoner->attackerOwned;
|
bsa.attacker = summoner->attackerOwned;
|
||||||
|
|
||||||
bsa.creID = CreatureID(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype); //in case summoner can summon more than one type of monsters... scream!
|
bsa.creID = summonedType;
|
||||||
ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum());
|
ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum());
|
||||||
ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;
|
ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect
|
||||||
|
|
||||||
ui64 canRiseHp = std::min(targetHealth, risedHp);
|
ui64 canRiseHp = std::min(targetHealth, risedHp);
|
||||||
ui32 canRiseAmount = canRiseHp / VLC->creh->creatures.at(bsa.creID)->MaxHealth();
|
ui32 canRiseAmount = canRiseHp / VLC->creh->creatures.at(bsa.creID)->MaxHealth();
|
||||||
@@ -3947,6 +3945,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
|
|
||||||
if (bsa.amount) //there's rare possibility single creature cannot rise desired type
|
if (bsa.amount) //there's rare possibility single creature cannot rise desired type
|
||||||
{
|
{
|
||||||
|
StartAction start_action(ba);
|
||||||
|
sendAndApply(&start_action);
|
||||||
|
|
||||||
BattleStacksRemoved bsr; //remove body
|
BattleStacksRemoved bsr; //remove body
|
||||||
bsr.stackIDs.insert(destStack->ID);
|
bsr.stackIDs.insert(destStack->ID);
|
||||||
sendAndApply(&bsr);
|
sendAndApply(&bsr);
|
||||||
@@ -3958,9 +3959,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
ssp.val = -1;
|
ssp.val = -1;
|
||||||
ssp.absolute = false;
|
ssp.absolute = false;
|
||||||
sendAndApply(&ssp);
|
sendAndApply(&ssp);
|
||||||
}
|
|
||||||
|
|
||||||
sendAndApply(&end_action);
|
sendAndApply(&end_action);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Battle::MONSTER_SPELL:
|
case Battle::MONSTER_SPELL:
|
||||||
@@ -5895,7 +5896,8 @@ void CGameHandler::duelFinished()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
|
CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat):
|
||||||
|
army(_army)
|
||||||
{
|
{
|
||||||
heroWithDeadCommander = ObjectInstanceID();
|
heroWithDeadCommander = ObjectInstanceID();
|
||||||
|
|
||||||
@@ -5903,50 +5905,111 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
|
|||||||
if(color == PlayerColor::UNFLAGGABLE)
|
if(color == PlayerColor::UNFLAGGABLE)
|
||||||
color = PlayerColor::NEUTRAL;
|
color = PlayerColor::NEUTRAL;
|
||||||
|
|
||||||
|
auto killStack = [&, this](const SlotID slot, const CStackInstance * instance)
|
||||||
|
{
|
||||||
|
StackLocation sl(army, slot);
|
||||||
|
newStackCounts.push_back(TStackAndItsNewCount(sl, 0));
|
||||||
|
if(nullptr == instance)
|
||||||
|
return;
|
||||||
|
auto c = dynamic_cast <const CCommanderInstance *>(instance);
|
||||||
|
if (c) //switch commander status to dead
|
||||||
|
{
|
||||||
|
auto h = dynamic_cast <const CGHeroInstance *>(army);
|
||||||
|
if (h && h->commander == c)
|
||||||
|
heroWithDeadCommander = army->id; //TODO: unify commander handling
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//1. Find removed stacks.
|
||||||
|
for(const auto & slotInfo : army->stacks)
|
||||||
|
{
|
||||||
|
const SlotID slot = slotInfo.first;
|
||||||
|
const CStackInstance * instance = slotInfo.second;
|
||||||
|
|
||||||
|
if(nullptr != instance)//just in case
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for(const CStack * sta : bat->stacks)
|
||||||
|
{
|
||||||
|
if(sta->base == instance)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//stack in this slot was removed == it is dead
|
||||||
|
if(!found)
|
||||||
|
killStack(slot, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(CStack *st : bat->stacks)
|
for(CStack *st : bat->stacks)
|
||||||
{
|
{
|
||||||
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 temporary summoned stacks
|
||||||
continue;
|
continue;
|
||||||
if (st->owner != color) //remove only our stacks
|
if (st->owner != color) //remove only our stacks
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
logGlobal->debugStream() << "Calculating casualties for " << st->nodeName();
|
||||||
|
|
||||||
//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor
|
//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor
|
||||||
st->count = std::max (0, st->count - st->resurrected);
|
st->count = std::max (0, st->count - st->resurrected);
|
||||||
|
|
||||||
if (!st->count && !st->base) //we can imagine stacks of war mahcines that are not spawned by artifacts?
|
if(st->slot == SlotID::ARROW_TOWERS_SLOT)
|
||||||
|
{
|
||||||
|
//do nothing
|
||||||
|
logGlobal->debugStream() << "Ignored arrow towers stack";
|
||||||
|
}
|
||||||
|
else if(st->slot == SlotID::WAR_MACHINES_SLOT)
|
||||||
{
|
{
|
||||||
auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber);
|
auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber);
|
||||||
//catapult artifact remain even if "creature" killed in siege
|
|
||||||
if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT)
|
if(warMachine == ArtifactID::NONE)
|
||||||
{
|
{
|
||||||
|
logGlobal->errorStream() << "Invalid creature in war machine virtual slot: " << st->nodeName();
|
||||||
|
}
|
||||||
|
//catapult artifact remain even if "creature" killed in siege
|
||||||
|
else if(warMachine != ArtifactID::CATAPULT && !st->count)
|
||||||
|
{
|
||||||
|
logGlobal->debugStream() << "War machine has been destroyed";
|
||||||
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
|
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
|
||||||
if (hero)
|
if (hero)
|
||||||
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
|
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
|
||||||
|
else
|
||||||
|
logGlobal->errorStream() << "War machine in army without hero";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER)
|
||||||
if(!army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
|
|
||||||
{
|
{
|
||||||
StackLocation sl(army, st->slot);
|
if(st->alive() && st->count > 0)
|
||||||
if(st->alive())
|
|
||||||
newStackCounts.push_back(std::pair<StackLocation, int>(sl, st->count));
|
|
||||||
else
|
|
||||||
newStackCounts.push_back(std::pair<StackLocation, int>(sl, 0));
|
|
||||||
}
|
|
||||||
if (st->base && !st->count)
|
|
||||||
{
|
|
||||||
auto c = dynamic_cast <const CCommanderInstance *>(st->base);
|
|
||||||
if (c) //switch commander status to dead
|
|
||||||
{
|
{
|
||||||
auto h = dynamic_cast <const CGHeroInstance *>(army);
|
logGlobal->debugStream() << "Stack has been permanently summoned";
|
||||||
if (h && h->commander == c)
|
//this stack was permanently summoned
|
||||||
heroWithDeadCommander = army->id; //TODO: unify commander handling
|
const CreatureID summonedType = st->type->idNumber;
|
||||||
|
summoned[summonedType] += st->count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(st->base && !army->slotEmpty(st->slot))
|
||||||
|
{
|
||||||
|
if(st->count == 0 || !st->alive())
|
||||||
|
{
|
||||||
|
killStack(st->slot, st->base);
|
||||||
|
logGlobal->debugStream() << "Stack has been destroyed";
|
||||||
|
}
|
||||||
|
else if(st->count < army->getStackCount(st->slot))
|
||||||
|
{
|
||||||
|
StackLocation sl(army, st->slot);
|
||||||
|
newStackCounts.push_back(TStackAndItsNewCount(sl, st->count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logGlobal->warnStream() << "Unhandled stack " << st->nodeName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh)
|
void CasualtiesAfterBattle::updateArmy(CGameHandler *gh)
|
||||||
{
|
{
|
||||||
for(TStackAndItsNewCount &ncount : newStackCounts)
|
for(TStackAndItsNewCount &ncount : newStackCounts)
|
||||||
{
|
{
|
||||||
@@ -5955,6 +6018,21 @@ void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh)
|
|||||||
else
|
else
|
||||||
gh->eraseStack(ncount.first, true);
|
gh->eraseStack(ncount.first, true);
|
||||||
}
|
}
|
||||||
|
for(auto summoned_iter : summoned)
|
||||||
|
{
|
||||||
|
SlotID slot = army->getSlotFor(summoned_iter.first);
|
||||||
|
if(slot.validSlot())
|
||||||
|
{
|
||||||
|
StackLocation location(army, slot);
|
||||||
|
gh->addToSlot(location, summoned_iter.first.toCreature(), summoned_iter.second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//even if it will be possible to summon anything permanently it should be checked for free slot
|
||||||
|
//necromancy is handled separately
|
||||||
|
gh->complain("No free slot to put summoned creature");
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto al : removedWarMachines)
|
for (auto al : removedWarMachines)
|
||||||
{
|
{
|
||||||
gh->removeArtifact(al);
|
gh->removeArtifact(al);
|
||||||
|
@@ -69,13 +69,16 @@ public:
|
|||||||
struct CasualtiesAfterBattle
|
struct CasualtiesAfterBattle
|
||||||
{
|
{
|
||||||
typedef std::pair<StackLocation, int> TStackAndItsNewCount;
|
typedef std::pair<StackLocation, int> TStackAndItsNewCount;
|
||||||
|
typedef std::map<CreatureID, TQuantity> TSummoned;
|
||||||
enum {ERASE = -1};
|
enum {ERASE = -1};
|
||||||
|
const CArmedInstance * army;
|
||||||
std::vector<TStackAndItsNewCount> newStackCounts;
|
std::vector<TStackAndItsNewCount> newStackCounts;
|
||||||
std::vector<ArtifactLocation> removedWarMachines;
|
std::vector<ArtifactLocation> removedWarMachines;
|
||||||
ObjectInstanceID heroWithDeadCommander; //TODO: unify stack loactions
|
TSummoned summoned;
|
||||||
|
ObjectInstanceID heroWithDeadCommander; //TODO: unify stack locations
|
||||||
|
|
||||||
CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat);
|
CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat);
|
||||||
void takeFromArmy(CGameHandler *gh);
|
void updateArmy(CGameHandler *gh);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CGameHandler : public IGameCallback, CBattleInfoCallback
|
class CGameHandler : public IGameCallback, CBattleInfoCallback
|
||||||
|
Reference in New Issue
Block a user