Pārlūkot izejas kodu

CGameHandler::arrangeStacks: honour removableUnits of CGGarrison

Now server properly check allowed actions for CGGarrison. Fix issue 2303
Server now allow all stack arrangement as long as troops stay inside garrison.
It's possible to put more troops inside using swap/merge/split, but not take anything out if it.
Arseniy Shestakov 9 gadi atpakaļ
vecāks
revīzija
75cffa7d0b
1 mainītis faili ar 46 papildinājumiem un 0 dzēšanām
  1. 46 0
      server/CGameHandler.cpp

+ 46 - 0
server/CGameHandler.cpp

@@ -2626,6 +2626,21 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 		return false;
 	}
 
+	// We can always put stacks into locked garrison, but not take them out of it
+	auto notRemovable = [&](const CArmedInstance * army)
+	{
+		if(id1 != id2) // Stack arrangement inside locked garrison is allowed
+		{
+			auto g = dynamic_cast<const CGGarrison *>(army);
+			if(g && !g->removableUnits)
+			{
+				complain("Stacks in this garrison are not removable!\n");
+				return true;
+			}
+		}
+		return false;
+	};
+
 	if(what==1) //swap
 	{
 		if ( ((s1->tempOwner != player && s1->tempOwner != PlayerColor::UNFLAGGABLE) && s1->getStackCount(p1))
@@ -2641,6 +2656,16 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 			return false;
 		}
 
+		if(!s1->slotEmpty(p1) && !s2->slotEmpty(p2))
+		{
+			if(notRemovable(sl1.army) || notRemovable(sl2.army))
+				return false;
+		}
+		if(s1->slotEmpty(p1) && notRemovable(sl2.army))
+			return false;
+		else if(s2->slotEmpty(p2) && notRemovable(sl1.army))
+			return false;
+
 		swapStacks(sl1, sl2);
 	}
 	else if(what==2)//merge
@@ -2649,6 +2674,14 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 		|| (((s1->tempOwner != player && s1->tempOwner != PlayerColor::UNFLAGGABLE) && s2->getStackCount(p2)) && complain("Can't take troops from another player!")))
 			return false;
 
+		if(s1->slotEmpty(p1) || s2->slotEmpty(p2))
+		{
+			complain("Cannot merge empty stack!");
+			return false;
+		}
+		else if(notRemovable(sl1.army))
+			return false;
+
 		moveStack(sl1, sl2);
 	}
 	else if(what==3) //split
@@ -2681,6 +2714,17 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 				return false;
 			}
 
+			if(notRemovable(sl1.army))
+			{
+				if(s1->getStackCount(p1) > countLeftOnSrc)
+					return false;
+			}
+			else if(notRemovable(sl2.army))
+			{
+				if(s2->getStackCount(p1) < countLeftOnSrc)
+					return false;
+			}
+
 			moveStack(sl1, sl2, countToMove);
 			//S2.slots[p2]->count = val;
 			//S1.slots[p1]->count = total - val;
@@ -2693,6 +2737,8 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 				return false;
 			}
 
+			if(notRemovable(sl1.army))
+				return false;
 
 			moveStack(sl1, sl2, val);
 		}