1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-17 01:32:21 +02:00

Fix regressions in combat

This commit is contained in:
Ivan Savenko
2025-04-19 11:25:18 +03:00
parent a89cf280e3
commit ce436bd63e
7 changed files with 22 additions and 14 deletions

View File

@ -405,9 +405,9 @@ void CStack::spendMana(ServerCallback * server, const int spellCost) const
server->apply(ssp);
}
void CStack::postDeserialize(const CArmedInstance * army, const SlotID & extSlot)
void CStack::postDeserialize(const CArmedInstance * army)
{
if(extSlot == SlotID::COMMANDER_SLOT_PLACEHOLDER)
if(slot == SlotID::COMMANDER_SLOT_PLACEHOLDER)
{
const auto * hero = dynamic_cast<const CGHeroInstance *>(army);
assert(hero);
@ -418,14 +418,13 @@ void CStack::postDeserialize(const CArmedInstance * army, const SlotID & extSlot
//no external slot possible, so no base stack
base = nullptr;
}
else if(!army || extSlot == SlotID() || !army->hasStackAtSlot(extSlot))
else if(!army || slot == SlotID() || !army->hasStackAtSlot(slot))
{
base = nullptr;
logGlobal->warn("%s doesn't have a base stack!", typeID.toEntity(LIBRARY)->getNameSingularTranslated());
throw std::runtime_error(typeID.toEntity(LIBRARY)->getNameSingularTranslated() + " doesn't have a base stack!");
}
else
{
base = &army->getStack(extSlot);
base = &army->getStack(slot);
}
doubleWideCached = battle::CUnitState::doubleWide();

View File

@ -37,8 +37,9 @@ private:
bool doubleWideCached = false;
void postDeserialize(const CArmedInstance * army, const SlotID & extSlot);
public:
void postDeserialize(const CArmedInstance * army);
const CStackInstance * base = nullptr; //garrison slot from which stack originates (nullptr for war machines, summoned cres, etc)
BattleHex initialPosition; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower

View File

@ -959,6 +959,12 @@ CGHeroInstance * BattleInfo::battleGetFightingHero(BattleSide side) const
return const_cast<CGHeroInstance*>(CBattleInfoEssentials::battleGetFightingHero(side));
}
void BattleInfo::postDeserialize()
{
for (auto & unit : stacks)
unit->postDeserialize(getSideArmy(unit->unitSide()));
}
#if SCRIPTING_ENABLED
scripting::Pool * BattleInfo::getContextPool() const
{

View File

@ -31,6 +31,8 @@ class DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallba
{
BattleSideArray<SideInBattle> sides; //sides[0] - attacker, sides[1] - defender
std::unique_ptr<BattleLayout> layout;
void postDeserialize();
public:
BattleID battleID = BattleID(0);
@ -66,6 +68,9 @@ public:
h & tacticDistance;
h & static_cast<CBonusSystemNode&>(*this);
h & replayAllowed;
if(!h.saving)
postDeserialize();
}
//////////////////////////////////////////////////////////////////////////

View File

@ -3439,12 +3439,10 @@ void CGameHandler::objectVisited(const CGObjectInstance * obj, const CGHeroInsta
queries->popIfTop(visitQuery); //visit ends here if no queries were created
}
void CGameHandler::objectVisitEnded(const CGHeroInstance *h, PlayerColor player)
void CGameHandler::objectVisitEnded(const ObjectInstanceID & heroObjectID, PlayerColor player)
{
using events::ObjectVisitEnded;
logGlobal->debug("%s visit ends.\n", h->nodeName());
auto endVisit = [&](ObjectVisitEnded & event)
{
HeroVisit hv;
@ -3456,7 +3454,7 @@ void CGameHandler::objectVisitEnded(const CGHeroInstance *h, PlayerColor player)
//TODO: ObjectVisitEnded should also have id of visited object,
//but this requires object being deleted only by `removeAfterVisit()` but not `removeObject()`
ObjectVisitEnded::defaultExecute(serverEventBus.get(), endVisit, player, h->id);
ObjectVisitEnded::defaultExecute(serverEventBus.get(), endVisit, player, heroObjectID);
}
bool CGameHandler::buildBoat(ObjectInstanceID objid, PlayerColor playerID)

View File

@ -238,7 +238,7 @@ public:
bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
void objectVisitEnded(const CGHeroInstance *h, PlayerColor player);
void objectVisitEnded(const ObjectInstanceID & heroObjectID, PlayerColor player);
bool dig(const CGHeroInstance *h);
void moveArmy(const CArmedInstance *src, const CArmedInstance *dst, bool allowMerging);

View File

@ -53,9 +53,8 @@ MapObjectVisitQuery::MapObjectVisitQuery(CGameHandler * owner, const CGObjectIns
void MapObjectVisitQuery::onRemoval(PlayerColor color)
{
auto object = gh->gameState()->getObjInstance(visitedObject);
auto hero = gh->gameState()->getHero(visitingHero);
gh->objectVisitEnded(hero, players.front());
gh->objectVisitEnded(visitingHero, players.front());
//Can object visit affect 2 players and what would be desired behavior?
if(removeObjectAfterVisit)