1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00
This commit is contained in:
FeniksFire 2017-07-01 17:59:53 +02:00 committed by Arseniy Shestakov
parent 01a1353fe1
commit 8577445b10
4 changed files with 61 additions and 48 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;
}