Browse Source

Merge pull request #5926 from IvanSavenko/commander_fixes

Fixes for commanders logic
Ivan Savenko 3 months ago
parent
commit
163c95ffb0
3 changed files with 36 additions and 14 deletions
  1. 2 0
      client/windows/CCreatureWindow.cpp
  2. 15 5
      lib/json/JsonBonus.cpp
  3. 19 9
      server/CGameHandler.cpp

+ 2 - 0
client/windows/CCreatureWindow.cpp

@@ -132,11 +132,13 @@ void CCommanderSkillIcon::clickPressed(const Point & cursorPosition)
 {
 	callback();
 	isSelected = true;
+	redraw();
 }
 
 void CCommanderSkillIcon::deselect()
 {
 	isSelected = false;
+	redraw();
 }
 
 bool CCommanderSkillIcon::getIsMasterAbility()

+ 15 - 5
lib/json/JsonBonus.cpp

@@ -537,6 +537,14 @@ static std::shared_ptr<const ILimiter> parseCreatureTypeLimiter(const JsonNode &
 	});
 
 	creatureLimiter->includeUpgrades = upgradesNode.Bool();
+
+	if (upgradesNode.isString())
+	{
+		logGlobal->warn("CREATURE_TYPE_LIMITER: parameter 'includeUpgrades' is invalid! expected boolean, but string '%s' found!", upgradesNode.String());
+		if (upgradesNode.String() == "true") // MOD COMPATIBILITY - broken mod, compensating
+			creatureLimiter->includeUpgrades = true;
+	}
+
 	return creatureLimiter;
 }
 
@@ -544,12 +552,11 @@ static std::shared_ptr<const ILimiter> parseHasAnotherBonusLimiter(const JsonNod
 {
 	auto bonusLimiter = std::make_shared<HasAnotherBonusLimiter>();
 
-	static const JsonNode nullNode;
 	const JsonNode & parameters = limiter["parameters"];
-	const JsonNode & jsonType    = limiter.Struct().count("bonusType") ? limiter["bonusType"] : parameters[0];
-	const JsonNode & jsonSubtype = limiter.Struct().count("bonusSubtype") ? limiter["bonusSubtype"] : (parameters.Vector().size() > 2 ? parameters[1] : nullNode);
-	const JsonNode & jsonSourceType  = limiter.Struct().count("bonusSourceType") ? limiter["bonusSourceType"] : (parameters.Vector().size() > 2 ? parameters[2]["type"] : parameters[1]["type"]);
-	const JsonNode & jsonSourceID  = limiter.Struct().count("bonusSourceID") ? limiter["bonusSourceID"] : (parameters.Vector().size() > 2 ? parameters[2]["id"] : parameters[1]["id"]);
+	const JsonNode & jsonType = limiter.Struct().count("bonusType") ? limiter["bonusType"] : parameters[0];
+	const JsonNode & jsonSubtype = limiter.Struct().count("bonusSubtype") ? limiter["bonusSubtype"] : parameters[1];
+	const JsonNode & jsonSourceType = limiter.Struct().count("bonusSourceType") ? limiter["bonusSourceType"] : parameters[2]["type"];
+	const JsonNode & jsonSourceID = limiter.Struct().count("bonusSourceID") ? limiter["bonusSourceID"] : parameters[2]["id"];
 
 	if (!jsonType.isNull())
 	{
@@ -557,7 +564,10 @@ static std::shared_ptr<const ILimiter> parseHasAnotherBonusLimiter(const JsonNod
 		{
 			bonusLimiter->type = static_cast<BonusType>(bonusID);
 			if (!jsonSubtype.isNull())
+			{
 				loadBonusSubtype(bonusLimiter->subtype, bonusLimiter->type, jsonSubtype);
+				bonusLimiter->isSubtypeRelevant = true;
+			}
 		});
 	}
 

+ 19 - 9
server/CGameHandler.cpp

@@ -353,19 +353,21 @@ void CGameHandler::giveStackExperience(const CArmedInstance * army, TExpType val
 void CGameHandler::giveExperience(const CGHeroInstance * hero, TExpType amountToGain)
 {
 	TExpType maxExp = LIBRARY->heroh->reqExp(LIBRARY->heroh->maxSupportedLevel());
-	TExpType currExp = hero->exp;
+	TExpType currHeroExp = hero->exp;
 
 	if (gameState().getMap().levelLimit != 0)
 		maxExp = LIBRARY->heroh->reqExp(gameState().getMap().levelLimit);
 
-	TExpType canGainExp = 0;
-	if (maxExp > currExp)
-		canGainExp = maxExp - currExp;
+	TExpType canGainHeroExp = 0;
+	if (maxExp > currHeroExp)
+		canGainHeroExp = maxExp - currHeroExp;
 
-	if (amountToGain > canGainExp)
+	TExpType actualHeroExperience = 0;
+
+	if (amountToGain > canGainHeroExp)
 	{
 		// set given experience to max possible, but don't decrease if hero already over top
-		amountToGain = canGainExp;
+		actualHeroExperience = canGainHeroExp;
 
 		InfoWindow iw;
 		iw.player = hero->tempOwner;
@@ -373,21 +375,29 @@ void CGameHandler::giveExperience(const CGHeroInstance * hero, TExpType amountTo
 		iw.text.replaceTextID(hero->getNameTextID());
 		sendAndApply(iw);
 	}
+	else
+		actualHeroExperience = amountToGain;
 
 	SetHeroExperience she;
 	she.id = hero->id;
 	she.mode = ChangeValueMode::RELATIVE;
-	she.val = amountToGain;
+	she.val = actualHeroExperience;
 	sendAndApply(she);
 
 	//hero may level up
 	if (hero->getCommander() && hero->getCommander()->alive)
 	{
-		//FIXME: trim experience according to map limit?
+		TExpType canGainCommanderExp = 0;
+		TExpType currCommanderExp = hero->getCommander()->getTotalExperience();
+		if (maxExp > currHeroExp)
+			canGainCommanderExp = maxExp - currCommanderExp;
+
+		TExpType actualCommanderExperience = amountToGain > canGainCommanderExp ? canGainCommanderExp : amountToGain;
+
 		SetCommanderProperty scp;
 		scp.heroid = hero->id;
 		scp.which = SetCommanderProperty::EXPERIENCE;
-		scp.amount = amountToGain;
+		scp.amount = actualCommanderExperience;
 		sendAndApply(scp);
 	}