1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

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

This commit is contained in:
Dmitry Orlov 2021-02-13 00:24:14 +03:00
parent db1f9a15b0
commit 55b3f0b24c
5 changed files with 33 additions and 13 deletions

View File

@ -75,3 +75,6 @@ Andrzej Żak aka godric3
Andrii Danylchenko Andrii Danylchenko
* VCAI improvements * VCAI improvements
Dmitry Orlov, <shubus.corporation@gmail.com>
* special buildings support in fan towns, new features and bug fixes

View File

@ -96,6 +96,24 @@ bool CObstacleInfo::isAppropriate(ETerrainType terrainType, int specialBattlefie
return vstd::contains(allowedTerrains, terrainType); 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) CHeroClass * CHeroClassHandler::loadFromJson(const JsonNode & node, const std::string & identifier)
{ {
std::string affinityStr[2] = { "might", "magic" }; 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->name = node["name"].String();
heroClass->affinity = vstd::find_pos(affinityStr, node["affinity"].String()); heroClass->affinity = vstd::find_pos(affinityStr, node["affinity"].String());
for(const std::string & pSkill : PrimarySkill::names) fillPrimarySkillData(node, heroClass, PrimarySkill::ATTACK);
{ fillPrimarySkillData(node, heroClass, PrimarySkill::DEFENSE);
heroClass->primarySkillInitial.push_back((int)node["primarySkills"][pSkill].Float()); fillPrimarySkillData(node, heroClass, PrimarySkill::SPELL_POWER);
heroClass->primarySkillLowLevel.push_back((int)node["lowLevelChance"][pSkill].Float()); fillPrimarySkillData(node, heroClass, PrimarySkill::KNOWLEDGE);
heroClass->primarySkillHighLevel.push_back((int)node["highLevelChance"][pSkill].Float());
}
for(auto skillPair : node["secondarySkills"].Struct()) for(auto skillPair : node["secondarySkills"].Struct())
{ {

View File

@ -236,6 +236,7 @@ struct DLL_LINKAGE CObstacleInfo
class DLL_LINKAGE CHeroClassHandler : public IHandlerBase 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); CHeroClass *loadFromJson(const JsonNode & node, const std::string & identifier);
public: public:
std::vector< ConstTransitivePtr<CHeroClass> > heroClasses; std::vector< ConstTransitivePtr<CHeroClass> > heroClasses;

View File

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

View File

@ -167,10 +167,14 @@ std::string CMapGenerator::getMapDescription() const
const std::string monsterStrengthStr[3] = { "weak", "normal", "strong" }; const std::string monsterStrengthStr[3] = { "weak", "normal", "strong" };
int monsterStrengthIndex = mapGenOptions->getMonsterStrength() - EMonsterStrength::GLOBAL_WEAK; //does not start from 0 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; 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") + 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()) % randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions->getPlayerCount()) %
static_cast<int>(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] % static_cast<int>(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] %
monsterStrengthStr[monsterStrengthIndex]); monsterStrengthStr[monsterStrengthIndex]);