1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-13 13:18:43 +02:00

Update army in case of summoned creatures

This commit is contained in:
AlexVinS 2015-10-15 17:03:22 +03:00
parent b024237e8a
commit c94bea51e3
2 changed files with 60 additions and 26 deletions

View File

@ -651,8 +651,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)
@ -5805,7 +5805,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();
@ -5813,6 +5814,21 @@ 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. //1. Find removed stacks.
for(const auto & slotInfo : army->stacks) for(const auto & slotInfo : army->stacks)
{ {
@ -5832,10 +5848,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
} }
//stack in this slot was removed == it is dead //stack in this slot was removed == it is dead
if(!found) if(!found)
{ killStack(slot, instance);
StackLocation sl(army, slot);
newStackCounts.push_back(TStackAndItsNewCount(sl, 0));
}
} }
} }
@ -5860,28 +5873,31 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
} }
} }
if(!army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) if(army->slotEmpty(st->slot))
{
if(st->slot == SlotID(255) && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive())
{
//this stack was permanently summoned
const CreatureID summonedType = st->type->idNumber;
summoned[summonedType] += st->count;
}
}
else
{
if(st->count == 0 || !st->alive())
{
killStack(st->slot, st->base);
}
else if(st->count < army->getStackCount(st->slot))
{ {
StackLocation sl(army, st->slot); StackLocation sl(army, st->slot);
if(st->alive()) newStackCounts.push_back(TStackAndItsNewCount(sl, st->count));
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);
if (h && h->commander == c)
heroWithDeadCommander = army->id; //TODO: unify commander handling
} }
} }
} }
} }
void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh) void CasualtiesAfterBattle::updateArmy(CGameHandler *gh)
{ {
for(TStackAndItsNewCount &ncount : newStackCounts) for(TStackAndItsNewCount &ncount : newStackCounts)
{ {
@ -5890,6 +5906,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);

View File

@ -71,13 +71,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