1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Battles: handle drawbridge lowering from stack start position

This commit is contained in:
Arseniy Shestakov
2016-02-09 10:45:59 +03:00
parent 6e5f5a6800
commit 47433919ab

View File

@@ -1005,7 +1005,8 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
assert(gs->curB->isInTacticRange(dest)); assert(gs->curB->isInTacticRange(dest));
} }
if(curStack->position == dest) auto start = curStack->position;
if(start == dest)
return 0; return 0;
//initing necessary tables //initing necessary tables
@@ -1032,7 +1033,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
return 0; return 0;
} }
std::pair< std::vector<BattleHex>, int > path = gs->curB->getPath(curStack->position, dest, curStack); std::pair< std::vector<BattleHex>, int > path = gs->curB->getPath(start, dest, curStack);
ret = path.second; ret = path.second;
@@ -1059,11 +1060,13 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
std::vector<BattleHex> tiles; std::vector<BattleHex> tiles;
const int tilesToMove = std::max((int)(path.first.size() - creSpeed), 0); const int tilesToMove = std::max((int)(path.first.size() - creSpeed), 0);
int v = path.first.size()-1; int v = path.first.size()-1;
path.first.push_back(start);
// check if gate need to be open or closed at some point // check if gate need to be open or closed at some point
BattleHex openGateAtHex, gateMayCloseAtHex; BattleHex openGateAtHex, gateMayCloseAtHex;
auto dbState = gs->curB->si.drawbridgeState; auto dbState = gs->curB->si.drawbridgeState;
if(battleGetSiegeLevel() > 0 && dbState != EDrawbridgeState::LOWERED_BORKED && if(battleGetSiegeLevel() > 0 && !curStack->attackerOwned &&
dbState != EDrawbridgeState::LOWERED_BORKED &&
dbState != EDrawbridgeState::RAISED_BLOCKED) dbState != EDrawbridgeState::RAISED_BLOCKED)
{ {
for(int i = path.first.size()-1; i >= 0; i--) for(int i = path.first.size()-1; i >= 0; i--)
@@ -1071,13 +1074,9 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
auto hex = path.first[i]; auto hex = path.first[i];
if(!openGateAtHex.isValid() && dbState != EDrawbridgeState::LOWERED) if(!openGateAtHex.isValid() && dbState != EDrawbridgeState::LOWERED)
{ {
if(gs->curB->town->subID == ETownType::FORTRESS) if(gs->curB->town->subID == ETownType::FORTRESS && hex == BattleHex(94))
{ {
if(hex == BattleHex(93) && openGateAtHex = path.first[i+1];
i-1 >= 0 && path.first[i-1] == BattleHex(94))
{
openGateAtHex = path.first[i+1];
}
} }
if(hex == BattleHex(94) && i-1 >= 0 && path.first[i-1] == BattleHex(95)) if(hex == BattleHex(94) && i-1 >= 0 && path.first[i-1] == BattleHex(95))
{ {
@@ -1088,6 +1087,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
openGateAtHex = path.first[i+1]; openGateAtHex = path.first[i+1];
} }
//gate may be opened and then closed during stack movement, but not other way around
if(openGateAtHex.isValid()) if(openGateAtHex.isValid())
dbState = EDrawbridgeState::LOWERED; dbState = EDrawbridgeState::LOWERED;
} }
@@ -1130,28 +1130,34 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
} }
bool gateStateChanging = false; bool gateStateChanging = false;
for(bool obstacleHit = false; (!obstacleHit) && (!gateStateChanging) && (v >= tilesToMove); --v) //special handling for opening gate on from starting hex
if(openGateAtHex.isValid() && openGateAtHex == start)
gateStateChanging = true;
else
{ {
BattleHex hex = path.first[v]; for(bool obstacleHit = false; (!obstacleHit) && (!gateStateChanging) && (v >= tilesToMove); --v)
tiles.push_back(hex);
if((openGateAtHex.isValid() && openGateAtHex == hex) ||
(gateMayCloseAtHex.isValid() && gateMayCloseAtHex == hex))
{ {
gateStateChanging = true; BattleHex hex = path.first[v];
} tiles.push_back(hex);
//if we walked onto something, finalize this portion of stack movement check into obstacle if((openGateAtHex.isValid() && openGateAtHex == hex) ||
if((obstacle = battleGetObstacleOnPos(hex, false))) (gateMayCloseAtHex.isValid() && gateMayCloseAtHex == hex))
obstacleHit = true; {
gateStateChanging = true;
}
if(curStack->doubleWide()) //if we walked onto something, finalize this portion of stack movement check into obstacle
{ if((obstacle = battleGetObstacleOnPos(hex, false)))
BattleHex otherHex = curStack->occupiedHex(hex);
//two hex creature hit obstacle by backside
if(otherHex.isValid() && ((obstacle2 = battleGetObstacleOnPos(otherHex, false))))
obstacleHit = true; obstacleHit = true;
if(curStack->doubleWide())
{
BattleHex otherHex = curStack->occupiedHex(hex);
//two hex creature hit obstacle by backside
if(otherHex.isValid() && ((obstacle2 = battleGetObstacleOnPos(otherHex, false))))
obstacleHit = true;
}
} }
} }
@@ -1188,16 +1194,24 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
if(curStack->alive()) if(curStack->alive())
processObstacle(obstacle2); processObstacle(obstacle2);
if(curStack->alive() && gateStateChanging) if(gateStateChanging)
{ {
if(curStack->position == openGateAtHex) if(curStack->position == openGateAtHex)
{ {
BattleDrawbridgeStateChanged db; openGateAtHex = BattleHex();
db.state = EDrawbridgeState::LOWERED; //only open gate if stack is still alive
sendAndApply(&db); if(curStack->alive())
{
BattleDrawbridgeStateChanged db;
db.state = EDrawbridgeState::LOWERED;
sendAndApply(&db);
}
} }
else else if(curStack->position == gateMayCloseAtHex)
{
openGateAtHex = BattleHex();
updateDrawbridgeState(); updateDrawbridgeState();
}
} }
} }
else else
@@ -3538,11 +3552,18 @@ void CGameHandler::updateDrawbridgeState()
} }
else if(db.state == EDrawbridgeState::LOWERED) else if(db.state == EDrawbridgeState::LOWERED)
{ {
if((gs->curB->town->subID != ETownType::FORTRESS || !gs->curB->battleGetStackByPos(BattleHex(94), false)) && if(!gs->curB->battleGetStackByPos(BattleHex(95), false) &&
!gs->curB->battleGetStackByPos(BattleHex(95), false) &&
!gs->curB->battleGetStackByPos(BattleHex(96), false)) !gs->curB->battleGetStackByPos(BattleHex(96), false))
{ {
db.state = EDrawbridgeState::RAISED; if(gs->curB->town->subID == ETownType::FORTRESS)
{
if(!gs->curB->battleGetStackByPos(BattleHex(94), false))
db.state = EDrawbridgeState::RAISED;
}
else if(gs->curB->battleGetStackByPos(BattleHex(94)))
db.state = EDrawbridgeState::RAISED_BLOCKED;
else
db.state = EDrawbridgeState::RAISED;
} }
} }
else if(gs->curB->battleGetStackByPos(BattleHex(94), false)) else if(gs->curB->battleGetStackByPos(BattleHex(94), false))