1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Cleared up gate blocking, Force Field can now block gates

This commit is contained in:
Ivan Savenko 2023-01-13 15:44:42 +02:00
parent 526de47ca4
commit ccc6ebee0d
3 changed files with 38 additions and 19 deletions

View File

@ -635,7 +635,7 @@ enum class EGateState : uint8_t
{
NONE,
CLOSED,
BLOCKED, //dead or alive stack blocking from outside
BLOCKED, // gate is blocked in closed state, e.g. by creature
OPENED,
DESTROYED
};

View File

@ -261,7 +261,7 @@ bool Obstacle::isHexAvailable(const CBattleInfoCallback * cb, const BattleHex &
if(part == EWallPart::INVALID)
return true;//no fortification here
else if(part == EWallPart::INDESTRUCTIBLE_PART_OF_GATE)
return false; // location accessible to units, but not targetable by spells
return true; // location accessible
else if(part == EWallPart::INDESTRUCTIBLE_PART)
return false;//indestructible part (cant be checked by battleGetWallState)
else if(part == EWallPart::BOTTOM_TOWER || part == EWallPart::UPPER_TOWER)

View File

@ -4426,6 +4426,26 @@ static EndAction end_action;
void CGameHandler::updateGateState()
{
// GATE_BRIDGE - leftmost tile, located over moat
// GATE_OUTER - central tile, mostly covered by gate image
// GATE_INNER - rightmost tile, inside the walls
// GATE_OUTER or GATE_INNER:
// - if defender moves unit on these tiles, bridge will open
// - if there is a creature (dead or alive) on these tiles, bridge will always remain open
// - blocked to attacker if bridge is closed
// GATE_BRIDGE
// - if there is a unit or corpse here, bridge can't open (and can't close in fortress)
// - if Force Field is cast here, bridge can't open (but can close, in any town)
// - deals moat damage to attacker if bridge is closed (fortress only)
bool hasForceFieldOnBridge = !battleGetAllObstaclesOnPos(BattleHex(ESiegeHex::GATE_BRIDGE), true).empty();
bool hasStackAtGateInner = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_INNER), false) != nullptr;
bool hasStackAtGateOuter = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_OUTER), false) != nullptr;
bool hasStackAtGateBridge = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_OUTER), false) != nullptr;
bool hasLongBridge = gs->curB->town->subID == ETownType::FORTRESS;
BattleUpdateGateState db;
db.state = gs->curB->si.gateState;
if (gs->curB->si.wallState[EWallPart::GATE] == EWallState::DESTROYED)
@ -4434,24 +4454,23 @@ void CGameHandler::updateGateState()
}
else if (db.state == EGateState::OPENED)
{
if (!gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_OUTER), false) &&
!gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_INNER), false))
{
if (gs->curB->town->subID == ETownType::FORTRESS)
{
if (!gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_BRIDGE), false))
db.state = EGateState::CLOSED;
}
else if (gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_BRIDGE)))
db.state = EGateState::BLOCKED;
else
db.state = EGateState::CLOSED;
}
bool hasStackOnLongBridge = hasStackAtGateBridge && hasLongBridge;
bool gateCanClose = !hasStackAtGateInner && !hasStackAtGateOuter && !hasStackOnLongBridge;
if (gateCanClose)
db.state = EGateState::CLOSED;
else
db.state = EGateState::OPENED;
}
else // CLOSED or BLOCKED
{
bool gateBlocked = hasForceFieldOnBridge || hasStackAtGateBridge;
if (gateBlocked)
db.state = EGateState::BLOCKED;
else
db.state = EGateState::CLOSED;
}
else if (gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_BRIDGE), false))
db.state = EGateState::BLOCKED;
else
db.state = EGateState::CLOSED;
if (db.state != gs->curB->si.gateState)
sendAndApply(&db);