1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

Correctly show results of CreatureTerrainLimiter outside of combat

This commit is contained in:
Ivan Savenko
2025-04-13 22:23:12 +03:00
parent 975d9aedc9
commit 2b812be9cd
7 changed files with 59 additions and 14 deletions

View File

@@ -858,6 +858,11 @@ TerrainId CStackInstance::getNativeTerrain() const
return getFactionID().toEntity(LIBRARY)->getNativeTerrain(); return getFactionID().toEntity(LIBRARY)->getNativeTerrain();
} }
TerrainId CStackInstance::getCurrentTerrain() const
{
return armyObj->getCurrentTerrain();
}
void CStackInstance::deserializationFix() void CStackInstance::deserializationFix()
{ {
const CArmedInstance *armyBackup = _armyObj; const CArmedInstance *armyBackup = _armyObj;

View File

@@ -141,6 +141,7 @@ public:
int32_t getInitiative(int turn = 0) const final; int32_t getInitiative(int turn = 0) const final;
TerrainId getNativeTerrain() const final; TerrainId getNativeTerrain() const final;
TerrainId getCurrentTerrain() const;
}; };
class DLL_LINKAGE CCommanderInstance : public CStackInstance class DLL_LINKAGE CCommanderInstance : public CStackInstance

View File

@@ -76,7 +76,6 @@ void CStack::localInit(BattleInfo * battleInfo)
attachTo(*army); attachTo(*army);
attachToSource(*typeID.toCreature()); attachToSource(*typeID.toCreature());
} }
nativeTerrain = getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock
CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered
position = initialPosition; position = initialPosition;
} }
@@ -316,14 +315,13 @@ bool CStack::canBeHealed() const
bool CStack::isOnNativeTerrain() const bool CStack::isOnNativeTerrain() const
{ {
//this code is called from CreatureTerrainLimiter::limit on battle start auto nativeTerrain = getNativeTerrain();
auto res = nativeTerrain == ETerrainId::ANY_TERRAIN || nativeTerrain == battle->getTerrainType(); return nativeTerrain == ETerrainId::ANY_TERRAIN || getCurrentTerrain() == nativeTerrain;
return res;
} }
bool CStack::isOnTerrain(TerrainId terrain) const TerrainId CStack::getCurrentTerrain() const
{ {
return battle->getTerrainType() == terrain; return battle->getTerrainType();
} }
const CCreature * CStack::unitType() const const CCreature * CStack::unitType() const

View File

@@ -28,7 +28,6 @@ class DLL_LINKAGE CStack final : public CBonusSystemNode, public battle::CUnitSt
private: private:
ui32 ID = -1; //unique ID of stack ui32 ID = -1; //unique ID of stack
CreatureID typeID; CreatureID typeID;
TerrainId nativeTerrain; //tmp variable to save native terrain value on battle init
ui32 baseAmount = -1; ui32 baseAmount = -1;
PlayerColor owner; //owner - player color (255 for neutrals) PlayerColor owner; //owner - player color (255 for neutrals)
@@ -56,7 +55,7 @@ public:
bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines
bool isOnNativeTerrain() const; bool isOnNativeTerrain() const;
bool isOnTerrain(TerrainId terrain) const; TerrainId getCurrentTerrain() const;
ui32 level() const; ui32 level() const;
si32 magicResistance() const override; //include aura of resistance si32 magicResistance() const override; //include aura of resistance

View File

@@ -280,18 +280,52 @@ CreatureTerrainLimiter::CreatureTerrainLimiter(TerrainId terrain):
ILimiter::EDecision CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const ILimiter::EDecision CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const
{ {
const CStack *stack = retrieveStackBattle(&context.node); if (context.node.getNodeType() != CBonusSystemNode::STACK_BATTLE && context.node.getNodeType() != CBonusSystemNode::STACK_INSTANCE)
if(stack) return ILimiter::EDecision::DISCARD;
if (terrainType == ETerrainId::NATIVE_TERRAIN)
{ {
if (terrainType == ETerrainId::NATIVE_TERRAIN && stack->isOnNativeTerrain())//terrainType not specified = native auto selector = Selector::type()(BonusType::TERRAIN_NATIVE);
if(context.alreadyAccepted.getFirst(selector))
return ILimiter::EDecision::ACCEPT; return ILimiter::EDecision::ACCEPT;
if(terrainType != ETerrainId::NATIVE_TERRAIN && stack->isOnTerrain(terrainType)) if(context.stillUndecided.getFirst(selector))
return ILimiter::EDecision::ACCEPT; return ILimiter::EDecision::NOT_SURE;
// TODO: CStack and CStackInstance need some common base type that represents any stack
// Closest existing class is ACreature, however it is also used as base for CCreature, which is not a stack
if (context.node.getNodeType() == CBonusSystemNode::STACK_BATTLE)
{
const auto * unit = dynamic_cast<const CStack *>(&context.node);
auto unitNativeTerrain = unit->getFactionID().toEntity(LIBRARY)->getNativeTerrain();
if (unit->getCurrentTerrain() == unitNativeTerrain)
return ILimiter::EDecision::ACCEPT;
}
else
{
const auto * unit = dynamic_cast<const CStackInstance *>(&context.node);
auto unitNativeTerrain = unit->getFactionID().toEntity(LIBRARY)->getNativeTerrain();
if (unit->getCurrentTerrain() == unitNativeTerrain)
return ILimiter::EDecision::ACCEPT;
}
}
else
{
if (context.node.getNodeType() == CBonusSystemNode::STACK_BATTLE)
{
const auto * unit = dynamic_cast<const CStack *>(&context.node);
if (unit->getCurrentTerrain() == terrainType)
return ILimiter::EDecision::ACCEPT;
}
else
{
const auto * unit = dynamic_cast<const CStackInstance*>(&context.node);
if (unit->getCurrentTerrain() == terrainType)
return ILimiter::EDecision::ACCEPT;
}
} }
return ILimiter::EDecision::DISCARD; return ILimiter::EDecision::DISCARD;
//TODO neutral creatues
} }
std::string CreatureTerrainLimiter::toString() const std::string CreatureTerrainLimiter::toString() const

View File

@@ -17,6 +17,7 @@
#include "../entities/faction/CTown.h" #include "../entities/faction/CTown.h"
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../gameState/CGameState.h" #include "../gameState/CGameState.h"
#include "../mapping/CMapDefines.h"
#include "../texts/CGeneralTextHandler.h" #include "../texts/CGeneralTextHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -163,4 +164,9 @@ void CArmedInstance::serializeJsonOptions(JsonSerializeFormat & handler)
CCreatureSet::serializeJson(handler, "army", 7); CCreatureSet::serializeJson(handler, "army", 7);
} }
TerrainId CArmedInstance::getCurrentTerrain() const
{
return cb->getTile(anchorPos())->getTerrainID();
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@@ -48,6 +48,8 @@ public:
{ {
return this->tempOwner; return this->tempOwner;
} }
TerrainId getCurrentTerrain() const;
void serializeJsonOptions(JsonSerializeFormat & handler) override; void serializeJsonOptions(JsonSerializeFormat & handler) override;