1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

reworked mod loading to follow standard approach

This commit is contained in:
Henning Koehler
2017-09-03 23:49:36 +12:00
parent cd35ece10c
commit 37df5c9d88
6 changed files with 51 additions and 154 deletions

View File

@@ -97,6 +97,11 @@
"description": "List of configuration files for spells", "description": "List of configuration files for spells",
"items": { "type":"string", "format" : "textFile" } "items": { "type":"string", "format" : "textFile" }
}, },
"skills": {
"type":"array",
"description": "List of configuration files for skills",
"items": { "type":"string", "format" : "textFile" }
},
"templates":{ "templates":{
"type":"array", "type":"array",
"description": "List of configuration files for RMG templates", "description": "List of configuration files for RMG templates",

View File

@@ -11,7 +11,7 @@
"skillBonus" : { "skillBonus" : {
"type" : "object", "type" : "object",
"description" : "Set of bonuses provided by skill at given level", "description" : "Set of bonuses provided by skill at given level",
"required" : ["effects"], "required" : ["description", "effects"],
"properties" : { "properties" : {
"description" : { "description" : {
"type" : "string", "type" : "string",
@@ -28,9 +28,17 @@
}, },
"required" : ["basic", "advanced", "expert"], "required" : ["name", "basic", "advanced", "expert"],
"properties" : { "properties" : {
"index" : {
"type": "number",
"description": "numeric id of skill, required for existing skills"
},
"name" : {
"type": "string",
"description": "localizable skill name"
},
"base" : { "base" : {
"type" : "object", "type" : "object",
"description" : "will be merged with all levels", "description" : "will be merged with all levels",

View File

@@ -1,5 +1,6 @@
{ {
"pathfinding" : { "pathfinding" : {
"index" : 0,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -26,6 +27,7 @@
} }
}, },
"archery" : { "archery" : {
"index" : 1,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -52,6 +54,7 @@
} }
}, },
"logistics" : { "logistics" : {
"index" : 2,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -78,6 +81,7 @@
} }
}, },
"scouting" : { "scouting" : {
"index" : 3,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -103,6 +107,7 @@
} }
}, },
"diplomacy" : { "diplomacy" : {
"index" : 4,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -137,6 +142,7 @@
} }
}, },
"navigation" : { "navigation" : {
"index" : 5,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -163,6 +169,7 @@
} }
}, },
"leadership" : { "leadership" : {
"index" : 6,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -188,6 +195,7 @@
} }
}, },
"wisdom" : { "wisdom" : {
"index" : 7,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -214,6 +222,7 @@
} }
}, },
"mysticism" : { "mysticism" : {
"index" : 8,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -239,6 +248,7 @@
} }
}, },
"luck" : { "luck" : {
"index" : 9,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -264,6 +274,7 @@
} }
}, },
"ballistics" : { "ballistics" : {
"index" : 10,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -296,6 +307,7 @@
} }
}, },
"eagleEye" : { "eagleEye" : {
"index" : 11,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -330,6 +342,7 @@
} }
}, },
"necromancy" : { "necromancy" : {
"index" : 12,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -356,6 +369,7 @@
} }
}, },
"estates" : { "estates" : {
"index" : 13,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -385,6 +399,7 @@
} }
}, },
"fireMagic" : { "fireMagic" : {
"index" : 14,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -411,6 +426,7 @@
} }
}, },
"airMagic" : { "airMagic" : {
"index" : 15,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -437,6 +453,7 @@
} }
}, },
"waterMagic" : { "waterMagic" : {
"index" : 16,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -463,6 +480,7 @@
} }
}, },
"earthMagic" : { "earthMagic" : {
"index" : 17,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -489,6 +507,7 @@
} }
}, },
"scholar" : { "scholar" : {
"index" : 18,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -515,6 +534,7 @@
} }
}, },
"tactics" : { "tactics" : {
"index" : 19,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -541,6 +561,7 @@
} }
}, },
"artillery" : { "artillery" : {
"index" : 20,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -581,6 +602,7 @@
} }
}, },
"learning" : { "learning" : {
"index" : 21,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -607,6 +629,7 @@
} }
}, },
"offence" : { "offence" : {
"index" : 22,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -633,6 +656,7 @@
} }
}, },
"armorer" : { "armorer" : {
"index" : 23,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -659,6 +683,7 @@
} }
}, },
"intelligence" : { "intelligence" : {
"index" : 24,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -685,6 +710,7 @@
} }
}, },
"sorcery" : { "sorcery" : {
"index" : 25,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -711,6 +737,7 @@
} }
}, },
"resistance" : { "resistance" : {
"index" : 26,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@@ -737,6 +764,7 @@
} }
}, },
"firstAid" : { "firstAid" : {
"index" : 27,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {

View File

@@ -404,6 +404,7 @@ bool CContentHandler::ContentTypeHandler::loadMod(std::string modName, bool vali
continue; continue;
} }
// normal new object // normal new object
logMod->trace("no index in loadMod(%s)", name);
performValidate(data,name); performValidate(data,name);
handler->loadObject(modName, name, data); handler->loadObject(modName, name, data);
} }

View File

@@ -27,7 +27,7 @@
#include "battle/CBattleInfoCallback.h" #include "battle/CBattleInfoCallback.h"
///CSkill ///CSkill
CSkill::LevelInfo::LevelInfo() : description("") CSkill::LevelInfo::LevelInfo()
{ {
} }
@@ -35,7 +35,7 @@ CSkill::LevelInfo::~LevelInfo()
{ {
} }
CSkill::CSkill(SecondarySkill id) : id(id), name("") CSkill::CSkill(SecondarySkill id) : id(id)
{ {
if(id == SecondarySkill::DEFAULT) if(id == SecondarySkill::DEFAULT)
identifier = "default"; identifier = "default";
@@ -101,14 +101,6 @@ std::string CSkill::toString() const
///CSkillHandler ///CSkillHandler
CSkillHandler::CSkillHandler() CSkillHandler::CSkillHandler()
{ {
for(int id = 0; id < GameConstants::SKILL_QUANTITY; id++)
{
CSkill * skill = new CSkill(SecondarySkill(id));
for(int level = 1; level < NSecondarySkill::levels.size(); level++)
for (auto bonus : defaultBonus(SecondarySkill(id), level))
skill->addNewBonus(bonus, level);
objects.push_back(skill);
}
} }
std::vector<JsonNode> CSkillHandler::loadLegacyData(size_t dataSize) std::vector<JsonNode> CSkillHandler::loadLegacyData(size_t dataSize)
@@ -136,18 +128,18 @@ std::vector<JsonNode> CSkillHandler::loadLegacyData(size_t dataSize)
std::vector<JsonNode> legacyData; std::vector<JsonNode> legacyData;
for(int id = 0; id < GameConstants::SKILL_QUANTITY; id++) for(int id = 0; id < GameConstants::SKILL_QUANTITY; id++)
{ {
CSkill & skill = *objects[id];
JsonNode skillNode(JsonNode::DATA_STRUCT); JsonNode skillNode(JsonNode::DATA_STRUCT);
skillNode["name"].String() = skillNames[id];
for(int level = 1; level < NSecondarySkill::levels.size(); level++) for(int level = 1; level < NSecondarySkill::levels.size(); level++)
{ {
skill.name = skillNames[id];
std::string & desc = skillInfoTexts[id][level-1]; std::string & desc = skillInfoTexts[id][level-1];
skill.setDescription(desc, level);
auto & levelNode = skillNode[NSecondarySkill::levels[level]].Struct(); auto & levelNode = skillNode[NSecondarySkill::levels[level]].Struct();
levelNode["description"].String() = desc; levelNode["description"].String() = desc;
levelNode["effects"].Struct(); // create empty effects objects
} }
legacyData.push_back(skillNode); legacyData.push_back(skillNode);
} }
objects.resize(legacyData.size());
return legacyData; return legacyData;
} }
@@ -175,8 +167,6 @@ CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string &
if(NSecondarySkill::names[id].compare(identifier) == 0) if(NSecondarySkill::names[id].compare(identifier) == 0)
{ {
skill = new CSkill(SecondarySkill(id)); skill = new CSkill(SecondarySkill(id));
//skill name isn't stored in JSON
skill->name = objects[id]->name;
break; break;
} }
} }
@@ -187,6 +177,7 @@ CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string &
throw std::runtime_error("invalid skill"); throw std::runtime_error("invalid skill");
} }
skill->name = json["name"].String();
for(int level = 1; level < NSecondarySkill::levels.size(); level++) for(int level = 1; level < NSecondarySkill::levels.size(); level++)
{ {
const std::string & levelName = NSecondarySkill::levels[level]; // basic, advanced, expert const std::string & levelName = NSecondarySkill::levels[level]; // basic, advanced, expert
@@ -198,11 +189,7 @@ CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string &
bonus->sid = skill->id; bonus->sid = skill->id;
skill->addNewBonus(bonus, level); skill->addNewBonus(bonus, level);
} }
// parse skill description - tracked separately skill->setDescription(levelNode["description"].String(), level);
if(vstd::contains(levelNode.Struct(), "description") && !levelNode["description"].isNull())
skill->setDescription(levelNode["description"].String(), level);
else
skill->setDescription(skillInfo(skill->id, level), level);
} }
logMod->debug("loaded secondary skill %s(%d)", identifier, (int)skill->id); logMod->debug("loaded secondary skill %s(%d)", identifier, (int)skill->id);
logMod->trace("%s", skill->toString()); logMod->trace("%s", skill->toString());
@@ -210,33 +197,6 @@ CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string &
return skill; return skill;
} }
void CSkillHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
{
auto type_name = getTypeName();
auto object = loadFromJson(data, normalizeIdentifier(scope, "core", name));
if(object->id == SecondarySkill::DEFAULT) // new skill - no index identified
{
object->id = SecondarySkill(objects.size());
objects.push_back(object);
}
else
objects[object->id] = object;
registerObject(scope, type_name, name, object->id);
}
void CSkillHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
{
auto type_name = getTypeName();
auto object = loadFromJson(data, normalizeIdentifier(scope, "core", name));
assert(object->id == index);
objects[index] = object;
registerObject(scope, type_name, name, object->id);
}
void CSkillHandler::afterLoadFinalization() void CSkillHandler::afterLoadFinalization()
{ {
} }
@@ -264,105 +224,3 @@ std::vector<bool> CSkillHandler::getDefaultAllowed() const
std::vector<bool> allowedSkills(objects.size(), true); std::vector<bool> allowedSkills(objects.size(), true);
return allowedSkills; return allowedSkills;
} }
// HMM3 default bonus provided by secondary skill
std::vector<std::shared_ptr<Bonus>> CSkillHandler::defaultBonus(SecondarySkill skill, int level) const
{
std::vector<std::shared_ptr<Bonus>> result;
// add bonus based on current values - useful for adding multiple bonuses easily
auto addBonus = [=, &result](int bonusVal, Bonus::BonusType bonusType = Bonus::SECONDARY_SKILL_PREMY, int subtype = 0)
{
if(bonusType == Bonus::SECONDARY_SKILL_PREMY || bonusType == Bonus::SECONDARY_SKILL_VAL2)
subtype = skill;
result.push_back(std::make_shared<Bonus>(Bonus::PERMANENT, bonusType, Bonus::SECONDARY_SKILL, bonusVal, skill, subtype, Bonus::BASE_NUMBER));
};
switch(skill)
{
case SecondarySkill::PATHFINDING:
addBonus(25 * level);
break;
case SecondarySkill::ARCHERY:
addBonus(5 + 5 * level * level);
break;
case SecondarySkill::LOGISTICS:
addBonus(10 * level);
break;
case SecondarySkill::SCOUTING:
addBonus(level, Bonus::SIGHT_RADIOUS);
break;
case SecondarySkill::DIPLOMACY:
addBonus(level);
addBonus(20 * level, Bonus::SURRENDER_DISCOUNT);
break;
case SecondarySkill::NAVIGATION:
addBonus(50 * level);
break;
case SecondarySkill::LEADERSHIP:
addBonus(level, Bonus::MORALE);
break;
case SecondarySkill::LUCK:
addBonus(level, Bonus::LUCK);
break;
case SecondarySkill::BALLISTICS:
addBonus(100, Bonus::MANUAL_CONTROL, CreatureID::CATAPULT);
addBonus(level);
break;
case SecondarySkill::EAGLE_EYE:
addBonus(30 + 10 * level);
addBonus(1 + level, Bonus::SECONDARY_SKILL_VAL2);
break;
case SecondarySkill::NECROMANCY:
addBonus(10 * level);
break;
case SecondarySkill::ESTATES:
addBonus(125 << (level-1));
break;
case SecondarySkill::FIRE_MAGIC:
case SecondarySkill::AIR_MAGIC:
case SecondarySkill::WATER_MAGIC:
case SecondarySkill::EARTH_MAGIC:
addBonus(level);
break;
case SecondarySkill::SCHOLAR:
addBonus(1 + level);
break;
case SecondarySkill::TACTICS:
addBonus(1 + 2 * level);
break;
case SecondarySkill::ARTILLERY:
addBonus(100, Bonus::MANUAL_CONTROL, CreatureID::BALLISTA);
addBonus(25 + 25 * level);
if(level > 1) // extra attack
addBonus(1, Bonus::SECONDARY_SKILL_VAL2);
break;
case SecondarySkill::LEARNING:
addBonus(5 * level);
break;
case SecondarySkill::OFFENCE:
addBonus(10 * level);
break;
case SecondarySkill::ARMORER:
addBonus(5 * level);
break;
case SecondarySkill::INTELLIGENCE:
addBonus(25 << (level-1));
break;
case SecondarySkill::SORCERY:
addBonus(5 * level);
break;
case SecondarySkill::RESISTANCE:
addBonus(5 << (level-1));
break;
case SecondarySkill::FIRST_AID:
addBonus(100, Bonus::MANUAL_CONTROL, CreatureID::FIRST_AID_TENT);
addBonus(25 + 25 * level);
break;
default:
addBonus(level);
break;
}
return result;
}

View File

@@ -73,8 +73,6 @@ public:
std::vector<bool> getDefaultAllowed() const override; std::vector<bool> getDefaultAllowed() const override;
const std::string getTypeName() const override; const std::string getTypeName() const override;
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
const std::string & skillInfo(int skill, int level) const; const std::string & skillInfo(int skill, int level) const;
const std::string & skillName(int skill) const; const std::string & skillName(int skill) const;
@@ -86,5 +84,4 @@ public:
protected: protected:
CSkill * loadFromJson(const JsonNode & json, const std::string & identifier) override; CSkill * loadFromJson(const JsonNode & json, const std::string & identifier) override;
std::vector<std::shared_ptr<Bonus>> defaultBonus(SecondarySkill skill, int level) const;
}; };