diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index c1ea5ec45..452b41d76 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -2163,15 +2163,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) break; case RISE_DEMONS: if (shere && ourStack && !shere->alive()) - { - 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; - } + legalAction = true; break; } if (legalAction) @@ -2328,10 +2320,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) break; case RISE_DEMONS: cursorType = ECursor::SPELLBOOK; - realizeAction = [=] - { - giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); - }; + realizeAction = [=]{ giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); }; break; case CATAPULT: cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT; diff --git a/lib/GameConstants.cpp b/lib/GameConstants.cpp index 3b5acc577..9a48b476f 100644 --- a/lib/GameConstants.cpp +++ b/lib/GameConstants.cpp @@ -19,7 +19,6 @@ #include "spells/CSpellHandler.h" const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2); -const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255); const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253); const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254); const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255); diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 98e344d6b..05d3128eb 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -216,7 +216,6 @@ class SlotID : public BaseForID friend class CNonConstInfoCallback; DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER; - DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///curB->generateNewStack(csbd, attacker, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks? + CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID(255), pos); //TODO: netpacks? if (summoned) addedStack->state.insert(EBattleStackState::SUMMONED); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ba81d0f77..88f43533e 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -651,8 +651,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer sendAndApply(&cs); } - cab1.updateArmy(this); - cab2.updateArmy(this); //take casualties after battle is deleted + cab1.takeFromArmy(this); + cab2.takeFromArmy(this); //take casualties after battle is deleted //if one hero has lost we will erase him if(battleResult.data->winner!=0 && hero1) @@ -3848,16 +3848,18 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) //TODO: From Strategija: //Summon Demon is a level 2 spell. { + StartAction start_action(ba); + sendAndApply(&start_action); + const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber), *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; bsa.attacker = summoner->attackerOwned; - bsa.creID = summonedType; + bsa.creID = CreatureID(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype); //in case summoner can summon more than one type of monsters... scream! ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum()); - ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect + ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount; ui64 canRiseHp = std::min(targetHealth, risedHp); ui32 canRiseAmount = canRiseHp / VLC->creh->creatures.at(bsa.creID)->MaxHealth(); @@ -3869,9 +3871,6 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) if (bsa.amount) //there's rare possibility single creature cannot rise desired type { - StartAction start_action(ba); - sendAndApply(&start_action); - BattleStacksRemoved bsr; //remove body bsr.stackIDs.insert(destStack->ID); sendAndApply(&bsr); @@ -3883,9 +3882,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) ssp.val = -1; ssp.absolute = false; sendAndApply(&ssp); - - sendAndApply(&end_action); } + + sendAndApply(&end_action); break; } case Battle::MONSTER_SPELL: @@ -5805,52 +5804,13 @@ void CGameHandler::duelFinished() return; } -CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat): - army(_army) +CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat) { heroWithDeadCommander = ObjectInstanceID(); PlayerColor color = army->tempOwner; if(color == PlayerColor::UNFLAGGABLE) 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 (instance); - if (c) //switch commander status to dead - { - auto h = dynamic_cast (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) { @@ -5862,7 +5822,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl //FIXME: this info is also used in BattleInfo::calculateCasualties, refactor st->count = std::max (0, st->count - st->resurrected); - if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts? + if (!st->count && !st->base) //we can imagine stacks of war mahcines that are not spawned by artifacts? { auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber); if (warMachine != ArtifactID::NONE) @@ -5872,32 +5832,29 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); } } - - if(army->slotEmpty(st->slot)) + + if(!army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) { - if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0) - { - //this stack was permanently summoned - const CreatureID summonedType = st->type->idNumber; - summoned[summonedType] += st->count; - } + StackLocation sl(army, st->slot); + if(st->alive()) + newStackCounts.push_back(std::pair(sl, st->count)); + else + newStackCounts.push_back(std::pair(sl, 0)); } - else + if (st->base && !st->count) { - if(st->count == 0 || !st->alive()) + auto c = dynamic_cast (st->base); + if (c) //switch commander status to dead { - killStack(st->slot, st->base); - } - else if(st->count < army->getStackCount(st->slot)) - { - StackLocation sl(army, st->slot); - newStackCounts.push_back(TStackAndItsNewCount(sl, st->count)); + auto h = dynamic_cast (army); + if (h && h->commander == c) + heroWithDeadCommander = army->id; //TODO: unify commander handling } } } } -void CasualtiesAfterBattle::updateArmy(CGameHandler *gh) +void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh) { for(TStackAndItsNewCount &ncount : newStackCounts) { @@ -5906,21 +5863,6 @@ void CasualtiesAfterBattle::updateArmy(CGameHandler *gh) else 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) { gh->removeArtifact(al); diff --git a/server/CGameHandler.h b/server/CGameHandler.h index bc2a336a7..acf1698a2 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -71,16 +71,13 @@ public: struct CasualtiesAfterBattle { typedef std::pair TStackAndItsNewCount; - typedef std::map TSummoned; enum {ERASE = -1}; - const CArmedInstance * army; std::vector newStackCounts; std::vector removedWarMachines; - TSummoned summoned; - ObjectInstanceID heroWithDeadCommander; //TODO: unify stack locations + ObjectInstanceID heroWithDeadCommander; //TODO: unify stack loactions - CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat); - void updateArmy(CGameHandler *gh); + CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat); + void takeFromArmy(CGameHandler *gh); }; class CGameHandler : public IGameCallback, CBattleInfoCallback