Browse Source

Battles: implement basic drawbridge mechanics

Movement to blocking hex 94 not yet properly handled as stack movement code need to be rewritten first.
Also gate destruction not immidiately affect drawbridge state.
Arseniy Shestakov 9 years ago
parent
commit
57328bdc83
4 changed files with 59 additions and 2 deletions
  1. 22 2
      lib/CBattleCallback.cpp
  2. 1 0
      lib/CBattleCallback.h
  3. 35 0
      server/CGameHandler.cpp
  4. 1 0
      server/CGameHandler.h

+ 22 - 2
lib/CBattleCallback.cpp

@@ -442,6 +442,15 @@ si8 CBattleInfoEssentials::battleGetWallState(int partOfWall) const
 	return getBattle()->si.wallState[partOfWall];
 }
 
+EDrawbridgeState CBattleInfoEssentials::battleGetDrawbridgeState() const
+{
+	RETURN_IF_NOT_BATTLE(EDrawbridgeState::NONE);
+	if(getBattle()->town == nullptr || getBattle()->town->fortLevel() == CGTownInstance::NONE)
+		return EDrawbridgeState::NONE;
+
+	return getBattle()->si.drawbridgeState;
+}
+
 si8 CBattleInfoCallback::battleHasWallPenalty( const CStack * stack, BattleHex destHex ) const
 {
 	return battleHasWallPenalty(stack, stack->position, destHex);
@@ -1129,9 +1138,20 @@ AccessibilityInfo CBattleInfoCallback::getAccesibility() const
 	}
 
 	//gate -> should be before stacks
-	if(battleGetSiegeLevel() > 0 && battleGetWallState(EWallPart::GATE) != EWallState::DESTROYED)
+	if(battleGetSiegeLevel() > 0)
 	{
-		ret[95] = ret[96] = EAccessibility::GATE; //block gate's hexes
+		EAccessibility::EAccessibility accessability = EAccessibility::ACCESSIBLE;
+		switch(battleGetDrawbridgeState())
+		{
+		case EDrawbridgeState::RAISED:
+			accessability = EAccessibility::GATE;
+			break;
+
+		case EDrawbridgeState::RAISED_BLOCKED:
+			accessability = EAccessibility::UNAVAILABLE;
+			break;
+		}
+		ret[95] = ret[96] = accessability;
 	}
 
 	//tiles occupied by standing stacks

+ 1 - 0
lib/CBattleCallback.h

@@ -199,6 +199,7 @@ public:
 	// for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall,
 	// [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
 	si8 battleGetWallState(int partOfWall) const;
+	EDrawbridgeState battleGetDrawbridgeState() const;
 
 	//helpers
 	///returns all stacks, alive or dead or undead or mechanical :)

+ 35 - 0
server/CGameHandler.cpp

@@ -1148,6 +1148,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
 				handleDamageFromObstacle(*theLastObstacle, curStack);
 			}
 	}
+	updateDrawbridgeState();
 	return ret;
 }
 
@@ -3449,6 +3450,40 @@ bool CGameHandler::queryReply(QueryID qid, ui32 answer, PlayerColor player)
 
 static EndAction end_action;
 
+void CGameHandler::updateDrawbridgeState()
+{
+	BattleDrawbridgeStateChanged db;
+	db.state = gs->curB->si.drawbridgeState;
+	if(gs->curB->si.wallState[EWallPart::GATE] == EWallState::DESTROYED)
+	{
+		db.state = EDrawbridgeState::LOWERED_BORKED;
+	}
+	else if(db.state == EDrawbridgeState::LOWERED)
+	{
+		if(gs->curB->battleGetStackByPos(BattleHex(94), false) ||
+			gs->curB->battleGetStackByPos(BattleHex(95), false) ||
+			gs->curB->battleGetStackByPos(BattleHex(96), false))
+		{
+			db.state = EDrawbridgeState::LOWERED;
+		}
+		else
+			db.state = EDrawbridgeState::RAISED;
+	}
+	else if(db.state == EDrawbridgeState::RAISED || db.state == EDrawbridgeState::RAISED_BLOCKED)
+	{
+		if(gs->curB->battleGetStackByPos(BattleHex(94), false))
+			db.state = EDrawbridgeState::RAISED_BLOCKED;
+		else if(gs->curB->battleGetStackByPos(BattleHex(95), false) ||
+			gs->curB->battleGetStackByPos(BattleHex(96), false))
+		{
+			db.state = EDrawbridgeState::LOWERED;
+		}
+		else
+			db.state = EDrawbridgeState::RAISED;
+	}
+	sendAndApply(&db);
+}
+
 bool CGameHandler::makeBattleAction( BattleAction &ba )
 {
 	bool ok = true;

+ 1 - 0
server/CGameHandler.h

@@ -200,6 +200,7 @@ public:
 	PlayerColor getPlayerAt(CConnection *c) const;
 
 	void playerMessage( PlayerColor player, const std::string &message, ObjectInstanceID currObj);
+	void updateDrawbridgeState();
 	bool makeBattleAction(BattleAction &ba);
 	bool makeAutomaticAction(const CStack *stack, BattleAction &ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack)
 	bool makeCustomAction(BattleAction &ba);