mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Simple fix: http://bugs.vcmi.eu/view.php?id=2366
This commit is contained in:
parent
01a1353fe1
commit
8577445b10
@ -828,20 +828,19 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(CRandomGenerator
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking /*= true*/) const
|
||||
std::vector<std::shared_ptr<const CObstacleInstance>> CBattleInfoCallback::battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(std::shared_ptr<const CObstacleInstance>());
|
||||
|
||||
for(auto &obs : battleGetAllObstacles())
|
||||
std::vector<std::shared_ptr<const CObstacleInstance>> obstacles = std::vector<std::shared_ptr<const CObstacleInstance>>();
|
||||
RETURN_IF_NOT_BATTLE(obstacles);
|
||||
for(auto & obs : battleGetAllObstacles())
|
||||
{
|
||||
if(vstd::contains(obs->getBlockedTiles(), tile)
|
||||
|| (!onlyBlocking && vstd::contains(obs->getAffectedTiles(), tile)))
|
||||
|| (!onlyBlocking && vstd::contains(obs->getAffectedTiles(), tile)))
|
||||
{
|
||||
return obs;
|
||||
obstacles.push_back(obs);
|
||||
}
|
||||
}
|
||||
|
||||
return std::shared_ptr<const CObstacleInstance>();
|
||||
return obstacles;
|
||||
}
|
||||
|
||||
AccessibilityInfo CBattleInfoCallback::getAccesibility() const
|
||||
|
@ -40,7 +40,8 @@ public:
|
||||
//battle
|
||||
boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
|
||||
|
||||
std::shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
|
||||
std::vector<std::shared_ptr<const CObstacleInstance>> battleGetAllObstaclesOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
|
||||
|
||||
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const; //returns stack info by given pos
|
||||
void battleGetStackQueue(std::vector<const CStack *> &out, const int howMany, const int turn = 0, int lastMoved = -1) const;
|
||||
void battleGetStackCountOutsideHexes(bool *ac) const; // returns hexes which when in front of a stack cause us to move the amount box back
|
||||
|
@ -438,15 +438,17 @@ bool ObstacleMechanics::isHexAviable(const CBattleInfoCallback * cb, const Battl
|
||||
if(cb->battleGetStackByPos(hex, true))
|
||||
return false;
|
||||
|
||||
auto obst = cb->battleGetObstacleOnPos(hex, false);
|
||||
if(obst /*&& obst->type != CObstacleInstance::MOAT*/)//todo: issue 2366, uncomment once obstacle tile sharing implemented
|
||||
return false;
|
||||
auto obst = cb->battleGetAllObstaclesOnPos(hex, false);
|
||||
|
||||
if(nullptr != cb->battleGetDefendedTown() && CGTownInstance::NONE != cb->battleGetDefendedTown()->fortLevel())
|
||||
for(auto & i : obst)
|
||||
if(i->obstacleType != CObstacleInstance::MOAT)
|
||||
return false;
|
||||
|
||||
if(cb->battleGetDefendedTown() != nullptr && cb->battleGetDefendedTown()->fortLevel() != CGTownInstance::NONE)
|
||||
{
|
||||
EWallPart::EWallPart part = cb->battleHexToWallPart(hex);
|
||||
|
||||
if(part == EWallPart::INVALID)
|
||||
if(part == EWallPart::INVALID || part == EWallPart::INDESTRUCTIBLE_PART_OF_GATE)
|
||||
return true;//no fortification here
|
||||
else if(static_cast<int>(part) < 0)
|
||||
return false;//indestuctible part (cant be checked by battleGetWallState)
|
||||
@ -631,18 +633,23 @@ void ForceFieldMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||
///RemoveObstacleMechanics
|
||||
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
if(auto obstacleToRemove = parameters.cb->battleGetObstacleOnPos(parameters.getFirstDestinationHex(), false))
|
||||
auto obstacleToRemove = parameters.cb->battleGetAllObstaclesOnPos(parameters.getFirstDestinationHex(), false);
|
||||
if(!obstacleToRemove.empty())
|
||||
{
|
||||
if(canRemove(obstacleToRemove.get(), parameters.spellLvl))
|
||||
ObstaclesRemoved obr;
|
||||
bool complain = true;
|
||||
for(auto & i : obstacleToRemove)
|
||||
{
|
||||
ObstaclesRemoved obr;
|
||||
obr.obstacles.insert(obstacleToRemove->uniqueID);
|
||||
if(canRemove(i.get(), parameters.spellLvl))
|
||||
{
|
||||
obr.obstacles.insert(i->uniqueID);
|
||||
complain = false;
|
||||
}
|
||||
}
|
||||
if(!complain)
|
||||
env->sendAndApply(&obr);
|
||||
}
|
||||
else
|
||||
{
|
||||
else if(complain || obr.obstacles.empty())
|
||||
env->complain("Cant remove this obstacle!");
|
||||
}
|
||||
}
|
||||
else
|
||||
env->complain("There's no obstacle to remove!");
|
||||
@ -667,9 +674,11 @@ ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCast(const CB
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
|
||||
{
|
||||
if(auto obstacle = cb->battleGetObstacleOnPos(ctx.destination, false))
|
||||
if(canRemove(obstacle.get(), ctx.schoolLvl))
|
||||
return ESpellCastProblem::OK;
|
||||
auto obstacles = cb->battleGetAllObstaclesOnPos(ctx.destination, false);
|
||||
if(!obstacles.empty())
|
||||
for(auto & i : obstacles)
|
||||
if(canRemove(i.get(), ctx.schoolLvl))
|
||||
return ESpellCastProblem::OK;
|
||||
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
@ -734,7 +743,7 @@ ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCast(const CBattle
|
||||
//therefore we do not need to check caster and casting mode
|
||||
//TODO: check that we really should check immunity for both stacks
|
||||
ESpellCastProblem::ESpellCastProblem res = owner->internalIsImmune(caster, stack);
|
||||
const bool immune = ESpellCastProblem::OK != res && ESpellCastProblem::NOT_DECIDED != res;
|
||||
const bool immune = ESpellCastProblem::OK != res && ESpellCastProblem::NOT_DECIDED != res;
|
||||
const bool casterStack = stack->owner == caster->getOwner();
|
||||
|
||||
if(!immune && casterStack)
|
||||
|
@ -1231,7 +1231,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
}
|
||||
else //for non-flying creatures
|
||||
{
|
||||
std::shared_ptr<const CObstacleInstance> obstacle, obstacle2; //obstacle that interrupted movement
|
||||
std::vector<std::shared_ptr<const CObstacleInstance>> obstacle, obstacle2; //obstacle that interrupted movement
|
||||
std::vector<BattleHex> tiles;
|
||||
const int tilesToMove = std::max((int)(path.first.size() - creSpeed), 0);
|
||||
int v = path.first.size()-1;
|
||||
@ -1330,7 +1330,8 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
}
|
||||
|
||||
//if we walked onto something, finalize this portion of stack movement check into obstacle
|
||||
if ((obstacle = battleGetObstacleOnPos(hex, false)))
|
||||
obstacle = battleGetAllObstaclesOnPos(hex, false);
|
||||
if(!obstacle.empty())
|
||||
obstacleHit = true;
|
||||
|
||||
if (curStack->doubleWide())
|
||||
@ -1338,7 +1339,8 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
BattleHex otherHex = curStack->occupiedHex(hex);
|
||||
|
||||
//two hex creature hit obstacle by backside
|
||||
if (otherHex.isValid() && ((obstacle2 = battleGetObstacleOnPos(otherHex, false))))
|
||||
obstacle2 = battleGetAllObstaclesOnPos(otherHex, false);
|
||||
if(otherHex.isValid() && !obstacle2.empty())
|
||||
obstacleHit = true;
|
||||
}
|
||||
}
|
||||
@ -1359,17 +1361,18 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
//we don't handle obstacle at the destination tile -> it's handled separately in the if at the end
|
||||
if (curStack->position != dest)
|
||||
{
|
||||
auto processObstacle = [&](std::shared_ptr<const CObstacleInstance> & obs)
|
||||
auto processObstacle = [&](std::vector<std::shared_ptr<const CObstacleInstance>> & obs)
|
||||
{
|
||||
if (obs)
|
||||
if(!obs.empty())
|
||||
{
|
||||
handleDamageFromObstacle(*obs, curStack);
|
||||
|
||||
//if stack die in explosion or interrupted by obstacle, abort movement
|
||||
if (obs->stopsMovement() || !curStack->alive())
|
||||
stackIsMoving = false;
|
||||
|
||||
obs.reset();
|
||||
for(auto & i : obs)
|
||||
{
|
||||
handleDamageFromObstacle(*i, curStack);
|
||||
//if stack die in explosion or interrupted by obstacle, abort movement
|
||||
if(i->stopsMovement() || !curStack->alive())
|
||||
stackIsMoving = false;
|
||||
i.reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1406,22 +1409,23 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
//handling obstacle on the final field (separate, because it affects both flying and walking stacks)
|
||||
if (curStack->alive())
|
||||
{
|
||||
if (auto theLastObstacle = battleGetObstacleOnPos(curStack->position, false))
|
||||
{
|
||||
handleDamageFromObstacle(*theLastObstacle, curStack);
|
||||
}
|
||||
auto theLastObstacle = battleGetAllObstaclesOnPos(curStack->position, false);
|
||||
for(auto & i : theLastObstacle)
|
||||
if(curStack->alive())
|
||||
handleDamageFromObstacle(*i, curStack);
|
||||
}
|
||||
|
||||
if (curStack->alive() && curStack->doubleWide())
|
||||
{
|
||||
BattleHex otherHex = curStack->occupiedHex(curStack->position);
|
||||
|
||||
if (otherHex.isValid())
|
||||
if (auto theLastObstacle = battleGetObstacleOnPos(otherHex, false))
|
||||
{
|
||||
//two hex creature hit obstacle by backside
|
||||
handleDamageFromObstacle(*theLastObstacle, curStack);
|
||||
}
|
||||
{
|
||||
//two hex creature hit obstacle by backside
|
||||
auto theLastObstacle = battleGetAllObstaclesOnPos(otherHex, false);
|
||||
for(auto & i : theLastObstacle)
|
||||
if(curStack->alive())
|
||||
handleDamageFromObstacle(*i, curStack);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user