Browse Source

Initial garrison of a town should now match H3 logic

Ivan Savenko 1 year ago
parent
commit
73459876bf
2 changed files with 39 additions and 0 deletions
  1. 38 0
      lib/mapObjects/CGTownInstance.cpp
  2. 1 0
      lib/mapObjects/CGTownInstance.h

+ 38 - 0
lib/mapObjects/CGTownInstance.cpp

@@ -476,10 +476,48 @@ void CGTownInstance::initObj(vstd::RNG & rand) ///initialize town structures
 		}
 	}
 	initializeConfigurableBuildings(rand);
+	initializeNeutralTownGarrison(rand);
 	recreateBuildingsBonuses();
 	updateAppearance();
 }
 
+void CGTownInstance::initializeNeutralTownGarrison(vstd::RNG & rand)
+{
+	struct RandomGuardsInfo{
+		int tier;
+		int chance;
+		int min;
+		int max;
+	};
+
+	constexpr std::array<RandomGuardsInfo, 4> randomGuards = {
+		RandomGuardsInfo{ 0, 33, 8, 15 },
+		RandomGuardsInfo{ 1, 33, 5,  7 },
+		RandomGuardsInfo{ 2, 20, 3,  5 },
+		RandomGuardsInfo{ 3, 14, 1,  3 },
+	};
+
+	// Only neutral towns may get initial garrison
+	if (getOwner().isValidPlayer())
+		return;
+
+	// Only towns with garrison not set in map editor may get initial garrison
+	// FIXME: H3 editor allow explicitly empty garrison, but vcmi loses this flag on load
+	if (stacksCount() > 0)
+		return;
+
+	for (auto const & guard : randomGuards)
+	{
+		if (rand.nextInt(99) >= guard.chance)
+			continue;
+
+		CreatureID guardID = getTown()->creatures[guard.tier].at(0);
+		int guardSize = rand.nextInt(guard.min, guard.max);
+
+		putStack(getFreeSlot(), new CStackInstance(guardID, guardSize));
+	}
+}
+
 void CGTownInstance::newTurn(vstd::RNG & rand) const
 {
 	for(const auto & building : rewardableBuildings)

+ 1 - 0
lib/mapObjects/CGTownInstance.h

@@ -246,6 +246,7 @@ private:
 	int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<const CGObjectInstance* >& dwellings) const;
 	bool townEnvisagesBuilding(BuildingSubID::EBuildingSubID bid) const;
 	void initializeConfigurableBuildings(vstd::RNG & rand);
+	void initializeNeutralTownGarrison(vstd::RNG & rand);
 };
 
 VCMI_LIB_NAMESPACE_END