Explorar o código

Fix: Map objects sometimes do not increment primary skills for some heroes

Dmitry Orlov %!s(int64=4) %!d(string=hai) anos
pai
achega
55b3f0b24c
Modificáronse 5 ficheiros con 33 adicións e 13 borrados
  1. 3 0
      AUTHORS
  2. 22 6
      lib/CHeroHandler.cpp
  3. 1 0
      lib/CHeroHandler.h
  4. 2 6
      lib/HeroBonus.cpp
  5. 5 1
      lib/rmg/CMapGenerator.cpp

+ 3 - 0
AUTHORS

@@ -75,3 +75,6 @@ Andrzej Żak aka godric3
    
 Andrii Danylchenko
    * VCAI improvements
+
+Dmitry Orlov, <[email protected]>
+   * special buildings support in fan towns, new features and bug fixes

+ 22 - 6
lib/CHeroHandler.cpp

@@ -96,6 +96,24 @@ bool CObstacleInfo::isAppropriate(ETerrainType terrainType, int specialBattlefie
 	return vstd::contains(allowedTerrains, terrainType);
 }
 
+void CHeroClassHandler::fillPrimarySkillData(const JsonNode & node, CHeroClass * heroClass, PrimarySkill::PrimarySkill pSkill)
+{
+	const auto & skillName = PrimarySkill::names[pSkill];
+	auto currentPrimarySkillValue = (int)node["primarySkills"][skillName].Integer();
+	//minimal value is 0 for attack and defense and 1 for spell power and knowledge
+	auto primarySkillLegalMinimum = (pSkill == PrimarySkill::ATTACK || pSkill == PrimarySkill::DEFENSE) ? 0 : 1;
+
+	if(currentPrimarySkillValue < primarySkillLegalMinimum)
+	{
+		logMod->error("Hero class '%s' has incorrect initial value '%d' for skill '%s'. Value '%d' will be used instead.",
+			heroClass->identifier, currentPrimarySkillValue, skillName, primarySkillLegalMinimum);
+		currentPrimarySkillValue = primarySkillLegalMinimum;
+	}
+	heroClass->primarySkillInitial.push_back(currentPrimarySkillValue);
+	heroClass->primarySkillLowLevel.push_back((int)node["lowLevelChance"][skillName].Float());
+	heroClass->primarySkillHighLevel.push_back((int)node["highLevelChance"][skillName].Float());
+}
+
 CHeroClass * CHeroClassHandler::loadFromJson(const JsonNode & node, const std::string & identifier)
 {
 	std::string affinityStr[2] = { "might", "magic" };
@@ -111,12 +129,10 @@ CHeroClass * CHeroClassHandler::loadFromJson(const JsonNode & node, const std::s
 	heroClass->name = node["name"].String();
 	heroClass->affinity = vstd::find_pos(affinityStr, node["affinity"].String());
 
-	for(const std::string & pSkill : PrimarySkill::names)
-	{
-		heroClass->primarySkillInitial.push_back((int)node["primarySkills"][pSkill].Float());
-		heroClass->primarySkillLowLevel.push_back((int)node["lowLevelChance"][pSkill].Float());
-		heroClass->primarySkillHighLevel.push_back((int)node["highLevelChance"][pSkill].Float());
-	}
+	fillPrimarySkillData(node, heroClass, PrimarySkill::ATTACK);
+	fillPrimarySkillData(node, heroClass, PrimarySkill::DEFENSE);
+	fillPrimarySkillData(node, heroClass, PrimarySkill::SPELL_POWER);
+	fillPrimarySkillData(node, heroClass, PrimarySkill::KNOWLEDGE);
 
 	for(auto skillPair : node["secondarySkills"].Struct())
 	{

+ 1 - 0
lib/CHeroHandler.h

@@ -236,6 +236,7 @@ struct DLL_LINKAGE CObstacleInfo
 
 class DLL_LINKAGE CHeroClassHandler : public IHandlerBase
 {
+	void fillPrimarySkillData(const JsonNode & node, CHeroClass * heroClass, PrimarySkill::PrimarySkill pSkill);
 	CHeroClass *loadFromJson(const JsonNode & node, const std::string & identifier);
 public:
 	std::vector< ConstTransitivePtr<CHeroClass> > heroClasses;

+ 2 - 6
lib/HeroBonus.cpp

@@ -786,13 +786,9 @@ int IBonusBearer::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
 {
 	static const CSelector selectorAllSkills = Selector::type()(Bonus::PRIMARY_SKILL);
 	static const std::string keyAllSkills = "type_PRIMARY_SKILL";
-
 	auto allSkills = getBonuses(selectorAllSkills, keyAllSkills);
-
-	int ret = allSkills->valOfBonuses(Selector::subtype()(id));
-
-	vstd::amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
-	return ret;
+	auto ret = allSkills->valOfBonuses(Selector::subtype()(id));
+	return ret; //sp=0 works in old saves
 }
 
 si32 IBonusBearer::magicResistance() const

+ 5 - 1
lib/rmg/CMapGenerator.cpp

@@ -167,10 +167,14 @@ std::string CMapGenerator::getMapDescription() const
 	const std::string monsterStrengthStr[3] = { "weak", "normal", "strong" };
 
 	int monsterStrengthIndex = mapGenOptions->getMonsterStrength() - EMonsterStrength::GLOBAL_WEAK; //does not start from 0
+	const auto * mapTemplate = mapGenOptions->getMapTemplate();
+
+	if(!mapTemplate)
+		throw rmgException("Map template for Random Map Generator is not found. Could not start the game.");
 
     std::stringstream ss;
     ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
-        ", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapGenOptions->getMapTemplate()->getName() %
+        ", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapTemplate->getName() %
 		randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions->getPlayerCount()) %
 		static_cast<int>(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] %
 		monsterStrengthStr[monsterStrengthIndex]);