mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
vcmi: really correct obstacle trigger
Now obstacle trigger really matches H3
This commit is contained in:
@@ -798,17 +798,18 @@ std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::battl
|
|||||||
return obstacles;
|
return obstacles;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::getAllAffectedObstaclesByStack(const battle::Unit * unit) const
|
std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::getAllAffectedObstaclesByStack(const battle::Unit * unit, const std::set<BattleHex> & passed) const
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<const CObstacleInstance>> affectedObstacles = std::vector<std::shared_ptr<const CObstacleInstance>>();
|
auto affectedObstacles = std::vector<std::shared_ptr<const CObstacleInstance>>();
|
||||||
RETURN_IF_NOT_BATTLE(affectedObstacles);
|
RETURN_IF_NOT_BATTLE(affectedObstacles);
|
||||||
if(unit->alive())
|
if(unit->alive())
|
||||||
{
|
{
|
||||||
|
if(!passed.count(unit->getPosition()))
|
||||||
affectedObstacles = battleGetAllObstaclesOnPos(unit->getPosition(), false);
|
affectedObstacles = battleGetAllObstaclesOnPos(unit->getPosition(), false);
|
||||||
if(unit->doubleWide())
|
if(unit->doubleWide())
|
||||||
{
|
{
|
||||||
BattleHex otherHex = unit->occupiedHex(unit->getPosition());
|
BattleHex otherHex = unit->occupiedHex();
|
||||||
if(otherHex.isValid())
|
if(otherHex.isValid() && !passed.count(otherHex))
|
||||||
for(auto & i : battleGetAllObstaclesOnPos(otherHex, false))
|
for(auto & i : battleGetAllObstaclesOnPos(otherHex, false))
|
||||||
if(!vstd::contains(affectedObstacles, i))
|
if(!vstd::contains(affectedObstacles, i))
|
||||||
affectedObstacles.push_back(i);
|
affectedObstacles.push_back(i);
|
||||||
|
@@ -60,7 +60,7 @@ public:
|
|||||||
boost::optional<int> battleIsFinished() const override; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
|
boost::optional<int> battleIsFinished() const override; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
|
||||||
|
|
||||||
std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const override;
|
std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const override;
|
||||||
std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit) const override;
|
std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit, const std::set<BattleHex> & passed) const override;
|
||||||
|
|
||||||
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const;
|
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const;
|
||||||
|
|
||||||
|
@@ -72,7 +72,7 @@ public:
|
|||||||
|
|
||||||
//blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
|
//blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
|
||||||
virtual std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const = 0;
|
virtual std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const = 0;
|
||||||
virtual std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit) const = 0;
|
virtual std::vector<std::shared_ptr<const CObstacleInstance>> getAllAffectedObstaclesByStack(const battle::Unit * unit, const std::set<BattleHex> & passed) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1398,6 +1398,11 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
|||||||
|
|
||||||
//initing necessary tables
|
//initing necessary tables
|
||||||
auto accessibility = getAccesibility(curStack);
|
auto accessibility = getAccesibility(curStack);
|
||||||
|
std::set<BattleHex> passed;
|
||||||
|
//Ignore obstacles on starting position
|
||||||
|
passed.insert(curStack->getPosition());
|
||||||
|
if(curStack->doubleWide())
|
||||||
|
passed.insert(curStack->occupiedHex());
|
||||||
|
|
||||||
//shifting destination (if we have double wide stack and we can occupy dest but not be exactly there)
|
//shifting destination (if we have double wide stack and we can occupy dest but not be exactly there)
|
||||||
if(!stackAtEnd && curStack->doubleWide() && !accessibility.accessible(dest, curStack))
|
if(!stackAtEnd && curStack->doubleWide() && !accessibility.accessible(dest, curStack))
|
||||||
@@ -1590,10 +1595,12 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
|||||||
if(otherHex.isValid() && !obstacle2.empty())
|
if(otherHex.isValid() && !obstacle2.empty())
|
||||||
obstacleHit = true;
|
obstacleHit = true;
|
||||||
}
|
}
|
||||||
|
if(!obstacleHit)
|
||||||
|
passed.insert(hex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tiles.size() > 0)
|
if (!tiles.empty())
|
||||||
{
|
{
|
||||||
//commit movement
|
//commit movement
|
||||||
BattleStackMoved sm;
|
BattleStackMoved sm;
|
||||||
@@ -1609,7 +1616,12 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
|||||||
if (curStack->getPosition() != dest)
|
if (curStack->getPosition() != dest)
|
||||||
{
|
{
|
||||||
if(stackIsMoving && start != curStack->getPosition())
|
if(stackIsMoving && start != curStack->getPosition())
|
||||||
stackIsMoving = handleDamageFromObstacle(curStack, stackIsMoving);
|
{
|
||||||
|
stackIsMoving = handleDamageFromObstacle(curStack, stackIsMoving, passed);
|
||||||
|
passed.insert(curStack->getPosition());
|
||||||
|
if(curStack->doubleWide())
|
||||||
|
passed.insert(curStack->occupiedHex());
|
||||||
|
}
|
||||||
if (gateStateChanging)
|
if (gateStateChanging)
|
||||||
{
|
{
|
||||||
if (curStack->getPosition() == openGateAtHex)
|
if (curStack->getPosition() == openGateAtHex)
|
||||||
@@ -1637,7 +1649,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//handling obstacle on the final field (separate, because it affects both flying and walking stacks)
|
//handling obstacle on the final field (separate, because it affects both flying and walking stacks)
|
||||||
handleDamageFromObstacle(curStack);
|
handleDamageFromObstacle(curStack, false, passed);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -5288,13 +5300,13 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackIsMoving)
|
bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackIsMoving, const std::set<BattleHex> & passed)
|
||||||
{
|
{
|
||||||
if(!curStack->alive())
|
if(!curStack->alive())
|
||||||
return false;
|
return false;
|
||||||
bool containDamageFromMoat = false;
|
bool containDamageFromMoat = false;
|
||||||
bool movementStoped = false;
|
bool movementStopped = false;
|
||||||
for(auto & obstacle : getAllAffectedObstaclesByStack(curStack))
|
for(auto & obstacle : getAllAffectedObstaclesByStack(curStack, passed))
|
||||||
{
|
{
|
||||||
if(obstacle->obstacleType == CObstacleInstance::SPELL_CREATED)
|
if(obstacle->obstacleType == CObstacleInstance::SPELL_CREATED)
|
||||||
{
|
{
|
||||||
@@ -5305,7 +5317,7 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI
|
|||||||
if(!spellObstacle)
|
if(!spellObstacle)
|
||||||
COMPLAIN_RET("Invalid obstacle instance");
|
COMPLAIN_RET("Invalid obstacle instance");
|
||||||
|
|
||||||
if(spellObstacle->trigger)
|
if(spellObstacle->triggersEffects())
|
||||||
{
|
{
|
||||||
const bool oneTimeObstacle = spellObstacle->removeOnTrigger;
|
const bool oneTimeObstacle = spellObstacle->removeOnTrigger;
|
||||||
|
|
||||||
@@ -5369,12 +5381,12 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if((obstacle->stopsMovement() && stackIsMoving))
|
if((obstacle->stopsMovement() && stackIsMoving))
|
||||||
movementStoped = true;
|
movementStopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(stackIsMoving)
|
if(stackIsMoving)
|
||||||
return curStack->alive() && !movementStoped;
|
return curStack->alive() && !movementStopped;
|
||||||
else
|
|
||||||
return curStack->alive();
|
return curStack->alive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -232,7 +232,7 @@ public:
|
|||||||
bool makeCustomAction(BattleAction &ba);
|
bool makeCustomAction(BattleAction &ba);
|
||||||
void stackEnchantedTrigger(const CStack * stack);
|
void stackEnchantedTrigger(const CStack * stack);
|
||||||
void stackTurnTrigger(const CStack *stack);
|
void stackTurnTrigger(const CStack *stack);
|
||||||
bool handleDamageFromObstacle(const CStack * curStack, bool stackIsMoving = false); //checks if obstacle is land mine and handles possible consequences
|
bool handleDamageFromObstacle(const CStack * curStack, bool stackIsMoving = false, const std::set<BattleHex> & passed = {}); //checks if obstacle is land mine and handles possible consequences
|
||||||
|
|
||||||
void removeObstacle(const CObstacleInstance &obstacle);
|
void removeObstacle(const CObstacleInstance &obstacle);
|
||||||
bool queryReply( QueryID qid, const JsonNode & answer, PlayerColor player );
|
bool queryReply( QueryID qid, const JsonNode & answer, PlayerColor player );
|
||||||
|
Reference in New Issue
Block a user