Browse Source

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 years ago
parent
commit
75cffa7d0b
1 changed files with 46 additions and 0 deletions
  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;
 		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(what==1) //swap
 	{
 	{
 		if ( ((s1->tempOwner != player && s1->tempOwner != PlayerColor::UNFLAGGABLE) && s1->getStackCount(p1))
 		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;
 			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);
 		swapStacks(sl1, sl2);
 	}
 	}
 	else if(what==2)//merge
 	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!")))
 		|| (((s1->tempOwner != player && s1->tempOwner != PlayerColor::UNFLAGGABLE) && s2->getStackCount(p2)) && complain("Can't take troops from another player!")))
 			return false;
 			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);
 		moveStack(sl1, sl2);
 	}
 	}
 	else if(what==3) //split
 	else if(what==3) //split
@@ -2681,6 +2714,17 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 				return false;
 				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);
 			moveStack(sl1, sl2, countToMove);
 			//S2.slots[p2]->count = val;
 			//S2.slots[p2]->count = val;
 			//S1.slots[p1]->count = total - val;
 			//S1.slots[p1]->count = total - val;
@@ -2693,6 +2737,8 @@ bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui
 				return false;
 				return false;
 			}
 			}
 
 
+			if(notRemovable(sl1.army))
+				return false;
 
 
 			moveStack(sl1, sl2, val);
 			moveStack(sl1, sl2, val);
 		}
 		}