From 52c563f8e279b77709e51f06139dc1422cb87938 Mon Sep 17 00:00:00 2001
From: past-due <30942300+past-due@users.noreply.github.com>
Date: Thu, 2 Nov 2023 20:03:03 -0400
Subject: [PATCH] Allow demolishing departed ally structures

---
 src/action.cpp  | 7 ++++++-
 src/display.cpp | 6 ++++--
 src/order.cpp   | 4 +++-
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/action.cpp b/src/action.cpp
index aa5899d0b73..af3c0418a4e 100644
--- a/src/action.cpp
+++ b/src/action.cpp
@@ -1736,7 +1736,12 @@ void actionUpdateDroid(DROID *psDroid)
 				}
 				else if (order->type == DORDER_DEMOLISH && structureAtPos->player != psDroid->player)
 				{
-					cantDoRepairLikeAction = true;
+					bool ObjAllied = (aiCheckAlliances(psDroid->player, structureAtPos->player));
+					bool ObjDepartedAlly = (bMultiPlayer && NetPlay.players[structureAtPos->player].difficulty == AIDifficulty::HUMAN && !NetPlay.players[structureAtPos->player].allocated);
+					if (!ObjAllied || !ObjDepartedAlly)
+					{
+						cantDoRepairLikeAction = true;
+					}
 				}
 
 				if (cantDoRepairLikeAction)
diff --git a/src/display.cpp b/src/display.cpp
index 41fd442831a..c56553ca369 100644
--- a/src/display.cpp
+++ b/src/display.cpp
@@ -777,6 +777,7 @@ void processMouseClickInput()
 
 		ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer is too high: %" PRIu32 "", selectedPlayer);
 		ObjAllied = (ObjUnderMouse && selectedPlayer != ObjUnderMouse->player && aiCheckAlliances(selectedPlayer, ObjUnderMouse->player));
+		bool ObjDepartedAlly = (ObjUnderMouse && bMultiPlayer && NetPlay.players[ObjUnderMouse->player].difficulty == AIDifficulty::HUMAN && !NetPlay.players[ObjUnderMouse->player].allocated);
 
 		if (item != MT_NOTARGET)
 		{
@@ -820,7 +821,7 @@ void processMouseClickInput()
 			else if (selection == SC_DROID_DEMOLISH)
 			{
 				// Can't demolish allied objects, or something that isn't built yet
-				if (ObjAllied || (ObjUnderMouse && (ObjUnderMouse->type != OBJ_STRUCTURE || (((STRUCTURE *)ObjUnderMouse)->status == SS_BLUEPRINT_PLANNED))))
+				if ((ObjAllied && !ObjDepartedAlly) || (ObjUnderMouse && (ObjUnderMouse->type != OBJ_STRUCTURE || (((STRUCTURE *)ObjUnderMouse)->status == SS_BLUEPRINT_PLANNED))))
 				{
 					item = MT_BLOCKING;
 				}
@@ -920,7 +921,8 @@ void processMouseClickInput()
 			     arnMPointers[item][selection] == CURSOR_EMBARK ||
 			     arnMPointers[item][selection] == CURSOR_ATTACH ||
 			     arnMPointers[item][selection] == CURSOR_LOCKON ||
-			     arnMPointers[item][selection] == CURSOR_DEST) && ObjAllied)
+			     arnMPointers[item][selection] == CURSOR_DEST) && ObjAllied
+				&& (selection != SC_DROID_DEMOLISH || !ObjDepartedAlly))
 			{
 				// If you want to do these things, just gift your unit to your ally.
 				item = MT_BLOCKING;
diff --git a/src/order.cpp b/src/order.cpp
index 75ac1cd77d7..ad5425a6cfa 100644
--- a/src/order.cpp
+++ b/src/order.cpp
@@ -2724,7 +2724,9 @@ DroidOrder chooseOrderObj(DROID *psDroid, BASE_OBJECT *psObj, bool altOrder)
 			int moduleIndex = nextModuleToBuild(psStruct, ctrlShiftDown() ? highestQueuedModule(psDroid, psStruct) : -1);
 
 			//Re-written to allow demolish order to be added to the queuing system
-			if (intDemolishSelectMode() && psObj->player == psDroid->player)
+			bool ObjDepartedAlly = (bMultiPlayer && NetPlay.players[psObj->player].difficulty == AIDifficulty::HUMAN && !NetPlay.players[psObj->player].allocated);
+			if (intDemolishSelectMode()
+				&& (psObj->player == psDroid->player || ObjDepartedAlly))
 			{
 				//check to see if anything is currently trying to build the structure
 				//can't build and demolish at the same time!