Selaa lähdekoodia

vcmi: allow adding global bonuses

I will use it to implement some H3 base features like
mana regen and base movement.
Konstantin 2 vuotta sitten
vanhempi
sitoutus
4acf3778ef
6 muutettua tiedostoa jossa 37 lisäystä ja 0 poistoa
  1. 14 0
      lib/CGameState.cpp
  2. 1 0
      lib/CGameState.h
  3. 5 0
      lib/CModHandler.cpp
  4. 2 0
      lib/CModHandler.h
  5. 1 0
      lib/HeroBonus.h
  6. 14 0
      lib/mapObjects/CGHeroInstance.cpp

+ 14 - 0
lib/CGameState.cpp

@@ -740,6 +740,7 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, bool allow
 
 	logGlobal->debug("Initialization:");
 
+	initGlobalBonuses();
 	initPlayerStates();
 	placeCampaignHeroes();
 	initGrailPosition();
@@ -934,6 +935,19 @@ void CGameState::checkMapChecksum()
 	}
 }
 
+void CGameState::initGlobalBonuses()
+{
+	const JsonNode & baseBonuses = VLC->modh->settings.data["baseBonuses"];
+	logGlobal->debug("\tLoading global bonuses");
+	for(const auto & b : baseBonuses.Vector())
+	{
+		auto bonus = JsonUtils::parseBonus(b);
+		bonus->source = Bonus::GLOBAL;//for all
+		bonus->sid = -1; //there is one global object
+		globalEffects.addNewBonus(bonus);
+	}
+}
+
 void CGameState::initGrailPosition()
 {
 	logGlobal->debug("\tPicking grail position");

+ 1 - 0
lib/CGameState.h

@@ -252,6 +252,7 @@ private:
 	void initNewGame(const IMapService * mapService, bool allowSavingRandomMap);
 	void initCampaign();
 	void checkMapChecksum();
+	void initGlobalBonuses();
 	void initGrailPosition();
 	void initRandomFactionsForPlayers();
 	void randomizeMapObjects();

+ 5 - 0
lib/CModHandler.cpp

@@ -812,6 +812,11 @@ void CModHandler::loadConfigFromFile (std::string name)
 	logMod->debug("\tCOMMANDERS\t%d", static_cast<int>(modules.COMMANDERS));
 	modules.MITHRIL = gameModules["MITHRIL"].Bool();
 	logMod->debug("\tMITHRIL\t%d", static_cast<int>(modules.MITHRIL));
+
+	const JsonNode & baseBonuses = VLC->modh->settings.data["heroBaseBonuses"];
+	logMod->debug("\tLoading base hero bonuses");
+	for(const auto & b : baseBonuses.Vector())
+		heroBaseBonuses.emplace_back(JsonUtils::parseBonus(b));
 }
 
 // currentList is passed by value to get current list of depending mods

+ 2 - 0
lib/CModHandler.h

@@ -354,6 +354,8 @@ public:
 	void load();
 	void afterLoad(bool onlyEssential);
 
+	std::vector<std::shared_ptr<Bonus>> heroBaseBonuses; //these bonuses will be applied to every hero on map
+
 	struct DLL_LINKAGE hardcodedFeatures
 	{
 		JsonNode data;

+ 1 - 0
lib/HeroBonus.h

@@ -356,6 +356,7 @@ public:
 	BONUS_SOURCE(SPECIAL_WEEK)\
 	BONUS_SOURCE(STACK_EXPERIENCE)\
 	BONUS_SOURCE(COMMANDER) /*TODO: consider using simply STACK_INSTANCE */\
+	BONUS_SOURCE(GLOBAL) /*used for base bonuses which all heroes or all stacks should have*/\
 	BONUS_SOURCE(OTHER) /*used for defensive stance and default value of spell level limit*/
 
 #define BONUS_VALUE_LIST \

+ 14 - 0
lib/mapObjects/CGHeroInstance.cpp

@@ -311,6 +311,20 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
 		levelUpAutomatically(rand);
 	}
 
+	// load base hero bonuses, TODO: per-map loading of base hero bonuses
+	// must be done separately from global bonuses since recruitable heroes in taverns 
+	// are not attached to global bonus node but need access to some global bonuses
+	// e.g. MANA_PER_KNOWLEDGE for correct preview and initial state after recruit	for(const auto & ob : VLC->modh->heroBaseBonuses)
+	// or MOVEMENT to compute initial movement before recruiting is finished
+	for(const auto & ob : VLC->modh->heroBaseBonuses)
+	{
+		auto bonus = ob;
+		bonus->source = Bonus::HERO_BASE_SKILL;
+		bonus->sid = id.getNum();
+		bonus->duration = Bonus::PERMANENT;
+		addNewBonus(bonus);
+	}
+
 	if (VLC->modh->modules.COMMANDERS && !commander)
 	{
 		commander = new CCommanderInstance(type->heroClass->commander->idNumber);