diff --git a/config/schemas/mod.json b/config/schemas/mod.json index 6611a3f20..55b87553b 100644 --- a/config/schemas/mod.json +++ b/config/schemas/mod.json @@ -270,6 +270,10 @@ "description" : "List of configuration files for creatures", "$ref" : "#/definitions/fileListOrObject" }, + "campaignRegions" : { + "description" : "List of configuration files for campaign regions", + "$ref" : "#/definitions/fileListOrObject" + }, "artifacts" : { "description" : "List of configuration files for artifacts", "$ref" : "#/definitions/fileListOrObject" diff --git a/lib/campaign/CampaignState.cpp b/lib/campaign/CampaignState.cpp index dd347fc20..5c032306e 100644 --- a/lib/campaign/CampaignState.cpp +++ b/lib/campaign/CampaignState.cpp @@ -218,7 +218,7 @@ void CampaignState::setCurrentMapAsConquered(std::vector heroe { boost::range::sort(heroes, [](const CGHeroInstance * a, const CGHeroInstance * b) { - return a->getValueForCampaign() > b->getValueForCampaign(); + return CGHeroInstance::compareCampaignValue(a, b); }); logGlobal->info("Scenario %d of campaign %s (%s) has been completed", currentMap->getNum(), getFilename(), getNameTranslated()); diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index 205bae9a7..b95193ea0 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -553,7 +553,7 @@ void CGameStateCampaign::initHeroes() int maxB = -1; for (int b=0; bgetValueForCampaign() > heroes[maxB]->getValueForCampaign()) + if(maxB == -1 || CGHeroInstance::compareCampaignValue(heroes[b], heroes[maxB])) { maxB = b; } diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index d7f9243d4..6eacf012e 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -748,17 +748,30 @@ uint64_t CGHeroInstance::getValueForDiplomacy() const return heroStrength * armyStrength; } -uint32_t CGHeroInstance::getValueForCampaign() const +bool CGHeroInstance::compareCampaignValue(const CGHeroInstance * left, const CGHeroInstance * right) { - // Determined by testing H3: hero is preferred for transfer in campaigns if total sum of his primary skills and his secondary skill levels is greatest - // Additional info from wiki: https://heroes.thelazy.net/index.php/Power_rating - uint32_t score = level; - score += getPrimSkillLevel(PrimarySkill::ATTACK); - score += getPrimSkillLevel(PrimarySkill::DEFENSE); - score += getPrimSkillLevel(PrimarySkill::SPELL_POWER); - score += getPrimSkillLevel(PrimarySkill::DEFENSE); + // https://heroes.thelazy.net/index.php/Power_rating - return score; + uint32_t leftLevel = left->level; + uint64_t leftExperience = left->exp; + uint32_t leftPrimary = left->getPrimSkillLevel(PrimarySkill::ATTACK) + left->getPrimSkillLevel(PrimarySkill::DEFENSE) + left->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + left->getPrimSkillLevel(PrimarySkill::DEFENSE); + uint32_t leftPrimaryAndLevel = leftPrimary + leftLevel; + + uint32_t rightLevel = right->level; + uint64_t rightExperience = right->exp; + uint32_t rightPrimary = right->getPrimSkillLevel(PrimarySkill::ATTACK) + right->getPrimSkillLevel(PrimarySkill::DEFENSE) + right->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + right->getPrimSkillLevel(PrimarySkill::DEFENSE); + uint32_t rightPrimaryAndLevel = rightPrimary + rightLevel; + + if (leftPrimaryAndLevel != rightPrimaryAndLevel) + return leftPrimaryAndLevel > rightPrimaryAndLevel; + + if (leftLevel != rightLevel) + return leftLevel > rightLevel; + + if (leftExperience != rightExperience) + return leftExperience > rightExperience; + + return left->getHeroTypeID() > right->getHeroTypeID(); } ui64 CGHeroInstance::getTotalStrength() const diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 3f37397ed..f90d38e12 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -212,7 +212,8 @@ public: double getMagicStrength() const; // takes knowledge / spell power skill but also current mana, whether the hero owns a spell-book and whether that books contains anything into account double getHeroStrength() const; // includes fighting and magic strength - uint32_t getValueForCampaign() const; + /// Returns true if 'left' hero is stronger than 'right' when considering campaign transfer priority + static bool compareCampaignValue(const CGHeroInstance * left, const CGHeroInstance * right); uint64_t getValueForDiplomacy() const; ui64 getTotalStrength() const; // includes fighting strength and army strength