From 7d7e65a31604166c12fa51a2961cbf0f5fd94343 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 13 Dec 2013 18:27:54 +0000 Subject: [PATCH] changes in hero class format: - new property: affinity (might/magic) since in mods it is impossible to rely on odd/even numeric indexes - property commander is now part of hero class --- Mods/WoG/config/wog/factions.json | 38 -------------- Mods/WoG/config/wog/heroClasses.json | 74 ++++++++++++++++++++++++++++ Mods/WoG/mod.json | 4 +- config/factions/castle.json | 1 - config/factions/conflux.json | 1 - config/factions/dungeon.json | 1 - config/factions/fortress.json | 1 - config/factions/inferno.json | 1 - config/factions/necropolis.json | 1 - config/factions/neutral.json | 3 +- config/factions/rampart.json | 1 - config/factions/stronghold.json | 1 - config/factions/tower.json | 1 - config/heroClasses.json | 40 ++++++++++++++- config/schemas/faction.json | 6 +-- config/schemas/heroClass.json | 12 ++++- lib/CHeroHandler.cpp | 18 ++++++- lib/CHeroHandler.h | 11 ++++- lib/CObjectHandler.cpp | 2 +- lib/CTownHandler.cpp | 13 ++++- lib/CTownHandler.h | 4 +- 21 files changed, 167 insertions(+), 67 deletions(-) delete mode 100644 Mods/WoG/config/wog/factions.json create mode 100644 Mods/WoG/config/wog/heroClasses.json diff --git a/Mods/WoG/config/wog/factions.json b/Mods/WoG/config/wog/factions.json deleted file mode 100644 index b2f1a6676..000000000 --- a/Mods/WoG/config/wog/factions.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "core:castle" : - { - "commander" : "paladin1" - }, - "core:conflux" : - { - "commander" : "astralSpirit1" - }, - "core:dungeon" : - { - "commander" : "brute1" - }, - "core:fortress" : - { - "commander" : "shaman1" - }, - "core:inferno" : - { - "commander" : "succubus1" - }, - "core:necropolis" : - { - "commander" : "soulEater1" - }, - "core:rampart" : - { - "commander" : "hierophant1" - }, - "core:stronghold" : - { - "commander" : "ogreLeader1" - }, - "core:tower" : - { - "commander" : "templeGuardian1" - } -} diff --git a/Mods/WoG/config/wog/heroClasses.json b/Mods/WoG/config/wog/heroClasses.json new file mode 100644 index 000000000..8b33e7cd6 --- /dev/null +++ b/Mods/WoG/config/wog/heroClasses.json @@ -0,0 +1,74 @@ +{ + "core:knight" : + { + "commander" : "paladin1" + }, + "core:cleric" : + { + "commander" : "paladin1" + }, + "core:planeswalker" : + { + "commander" : "astralSpirit1" + }, + "core:elementalist" : + { + "commander" : "astralSpirit1" + }, + "core:warlock" : + { + "commander" : "brute1" + }, + "core:overlord" : + { + "commander" : "brute1" + }, + "core:beastmaster" : + { + "commander" : "shaman1" + }, + "core:witch" : + { + "commander" : "shaman1" + }, + "core:demoniac" : + { + "commander" : "succubus1" + }, + "core:heretic" : + { + "commander" : "succubus1" + }, + "core:deathknight" : + { + "commander" : "soulEater1" + }, + "core:necromancer" : + { + "commander" : "soulEater1" + }, + "core:ranger" : + { + "commander" : "hierophant1" + }, + "core:druid" : + { + "commander" : "hierophant1" + }, + "core:barbarian" : + { + "commander" : "ogreLeader1" + }, + "core:battlemage" : + { + "commander" : "ogreLeader1" + }, + "core:alchemist" : + { + "commander" : "templeGuardian1" + }, + "core:wizard" : + { + "commander" : "templeGuardian1" + } +} diff --git a/Mods/WoG/mod.json b/Mods/WoG/mod.json index 93a5280ad..3dbcc5820 100644 --- a/Mods/WoG/mod.json +++ b/Mods/WoG/mod.json @@ -17,9 +17,9 @@ "config/wog/creatures.json" ], - "factions" : + "heroClasses" : [ - "config/wog/factions.json" + "config/wog/heroClasses.json" ], "filesystem": diff --git a/config/factions/castle.json b/config/factions/castle.json index 52b886a68..d6c05199a 100644 --- a/config/factions/castle.json +++ b/config/factions/castle.json @@ -4,7 +4,6 @@ "index" : 0, "nativeTerrain": "grass", "alignment" : "good", - "commander" : "zealot", "creatureBackground" : { "120px" : "TPCASCAS", diff --git a/config/factions/conflux.json b/config/factions/conflux.json index cdb4fb67b..c1be3d022 100644 --- a/config/factions/conflux.json +++ b/config/factions/conflux.json @@ -4,7 +4,6 @@ "index" : 8, "nativeTerrain": "grass", "alignment" : "neutral", - "commander" : "iceElemental", "creatureBackground" : { "120px" : "TPCASELE", diff --git a/config/factions/dungeon.json b/config/factions/dungeon.json index 519633b1d..99c81debd 100644 --- a/config/factions/dungeon.json +++ b/config/factions/dungeon.json @@ -4,7 +4,6 @@ "index" : 5, "nativeTerrain": "subterra", "alignment" : "evil", - "commander" : "medusaQueen", "creatureBackground" : { "120px" : "TPCASDUN", diff --git a/config/factions/fortress.json b/config/factions/fortress.json index 35dd2f638..7b5137b14 100644 --- a/config/factions/fortress.json +++ b/config/factions/fortress.json @@ -4,7 +4,6 @@ "index" : 7, "nativeTerrain": "swamp", "alignment" : "neutral", - "commander" : "lizardWarrior", "creatureBackground" : { "120px" : "TPCASFOR", diff --git a/config/factions/inferno.json b/config/factions/inferno.json index ef0cb1798..d62555fc0 100644 --- a/config/factions/inferno.json +++ b/config/factions/inferno.json @@ -4,7 +4,6 @@ "index" : 3, "nativeTerrain": "lava", "alignment" : "evil", - "commander" : "magog", "creatureBackground" : { "120px" : "TPCASINF", diff --git a/config/factions/necropolis.json b/config/factions/necropolis.json index 88ce4a2c2..c1096de3c 100644 --- a/config/factions/necropolis.json +++ b/config/factions/necropolis.json @@ -4,7 +4,6 @@ "index" : 4, "nativeTerrain": "dirt", "alignment" : "evil", - "commander" : "powerLich", "creatureBackground" : { "120px" : "TPCASNEC", diff --git a/config/factions/neutral.json b/config/factions/neutral.json index 6fa4ccc61..6a6abac52 100644 --- a/config/factions/neutral.json +++ b/config/factions/neutral.json @@ -8,7 +8,6 @@ { "120px" : "TPCASNEU", "130px" : "CRBKGNEU" - }, - "commander" : "enchanter" //just in case + } } } diff --git a/config/factions/rampart.json b/config/factions/rampart.json index 57bf8fc20..a7fa6726c 100644 --- a/config/factions/rampart.json +++ b/config/factions/rampart.json @@ -4,7 +4,6 @@ "index" : 1, "nativeTerrain": "grass", "alignment" : "good", - "commander" : "grandElf", "creatureBackground" : { "120px" : "TPCASRAM", diff --git a/config/factions/stronghold.json b/config/factions/stronghold.json index 08851735c..6b577bb75 100644 --- a/config/factions/stronghold.json +++ b/config/factions/stronghold.json @@ -4,7 +4,6 @@ "index" : 6, "nativeTerrain": "rough", "alignment" : "neutral", - "commander" : "orcChieftain", "creatureBackground" : { "120px" : "TPCASSTR", diff --git a/config/factions/tower.json b/config/factions/tower.json index ef9da47da..06880ba07 100644 --- a/config/factions/tower.json +++ b/config/factions/tower.json @@ -4,7 +4,6 @@ "index" : 2, "nativeTerrain" : "snow", "alignment" : "good", - "commander" : "archMage", "creatureBackground" : { "120px" : "TPCASTOW", diff --git a/config/heroClasses.json b/config/heroClasses.json index a0697c754..0a1449113 100644 --- a/config/heroClasses.json +++ b/config/heroClasses.json @@ -4,6 +4,8 @@ "index": 0, "faction" : "castle", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "zealot", "animation": { "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" }, @@ -15,6 +17,8 @@ "index": 1, "faction" : "castle", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "zealot", "animation": { "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" }, @@ -26,6 +30,8 @@ "index": 2, "faction" : "rampart", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "grandElf", "animation": { "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" }, @@ -37,6 +43,8 @@ "index": 3, "faction" : "rampart", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "grandElf", "animation": { "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" }, @@ -48,6 +56,8 @@ "index": 4, "faction" : "tower", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "archMage", "animation": { "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" }, @@ -59,6 +69,8 @@ "index": 5, "faction" : "tower", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "archMage", "animation": { "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" }, @@ -70,6 +82,8 @@ "index": 6, "faction" : "inferno", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "magog", "animation": { "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" }, @@ -81,6 +95,8 @@ "index": 7, "faction" : "inferno", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "magog", "animation": { "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" }, @@ -92,6 +108,8 @@ "index": 8, "faction" : "necropolis", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "powerLich", "animation": { "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" }, @@ -103,6 +121,8 @@ "index": 9, "faction" : "necropolis", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "powerLich", "animation": { "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" }, @@ -114,6 +134,8 @@ "index": 10, "faction" : "dungeon", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "medusaQueen", "animation": { "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" }, @@ -125,6 +147,8 @@ "index": 11, "faction" : "dungeon", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "medusaQueen", "animation": { "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" }, @@ -136,6 +160,8 @@ "index": 12, "faction" : "stronghold", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "orcChieftain", "animation": { "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" }, @@ -147,6 +173,8 @@ "index": 13, "faction" : "stronghold", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "orcChieftain", "animation": { "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" }, @@ -158,6 +186,8 @@ "index": 14, "faction" : "fortress", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "lizardWarrior", "animation": { "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" }, @@ -169,6 +199,8 @@ "index": 15, "faction" : "fortress", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "lizardWarrior", "animation": { "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" }, @@ -180,9 +212,11 @@ "index": 16, "faction" : "conflux", "defaultTavern" : 5, + "affinity" : "might", + "commander" : "iceElemental", "animation": { - "battle" : { "male" : "CH16.DEF", "female" : "CH17.DEF" }, + "battle" : { "male" : "CH16.DEF", "female" : "CH16.DEF" }, "map": { "male" : "AH16_.def", "female" : "AH16_.def" } } }, @@ -191,9 +225,11 @@ "index": 17, "faction" : "conflux", "defaultTavern" : 5, + "affinity" : "magic", + "commander" : "iceElemental", "animation": { - "battle" : { "male" : "CH16.DEF", "female" : "CH17.DEF" }, + "battle" : { "male" : "CH17.DEF", "female" : "CH17.DEF" }, "map": { "male" : "AH17_.def", "female" : "AH17_.def" } } } diff --git a/config/schemas/faction.json b/config/schemas/faction.json index 4188ec70d..5395d188f 100644 --- a/config/schemas/faction.json +++ b/config/schemas/faction.json @@ -33,7 +33,7 @@ "description": "Json format for defining new faction (aka towns) in VCMI", "required" : [ "name", "alignment", "creatureBackground" ], "dependencies" : { - "town" : [ "puzzleMap", "commander" ] + "town" : [ "puzzleMap" ] }, "additionalProperties" : false, @@ -51,10 +51,6 @@ "enum" : [ "good", "neutral", "evil" ], "description": "Town alignment, good, neutral or evil" }, - "commander": { - "type":"string", - "description": "Identifier of creature that is used as commander by heroes" - }, "creatureBackground": { "type":"object", "additionalProperties" : false, diff --git a/config/schemas/heroClass.json b/config/schemas/heroClass.json index a9c5fa425..59bf42529 100644 --- a/config/schemas/heroClass.json +++ b/config/schemas/heroClass.json @@ -5,7 +5,8 @@ "description" : "Format used to define classes of heroes in VCMI", "required" : [ "animation", "faction", "highLevelChance", "lowLevelChance", - "name", "primarySkills", "secondarySkills", "tavern", "defaultTavern" + "name", "primarySkills", "secondarySkills", "tavern", "defaultTavern", + "affinity", "commander" ], "additionalProperties" : false, @@ -62,6 +63,15 @@ "type":"string", "description": "Faction this hero class belongs to" }, + "affinity" : { + "type" : "string", + "description" : "Affinity of hero class, might or magic", + "enum" : [ "might", "magic"] + }, + "commander": { + "type":"string", + "description": "Identifier of creature that is used as commander by heroes" + }, "highLevelChance": { "type":"object", "description": "Chance to get specific primary skill on level-up, applicable for levels starting from 10", diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 8ada18355..a424ff324 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -7,6 +7,7 @@ #include "JsonNode.h" #include "StringConstants.h" #include "BattleHex.h" +#include "CCreatureHandler.h" #include "CModHandler.h" #include "CTownHandler.h" #include "CObjectHandler.h" //for hero specialty @@ -45,7 +46,7 @@ SecondarySkill CHeroClass::chooseSecSkill(const std::set & possi bool CHeroClass::isMagicHero() const { - return id % 2; // 0 - might, 1 - magic + return affinity == MAGIC; } EAlignment::EAlignment CHeroClass::getAlignment() const @@ -88,6 +89,8 @@ bool CObstacleInfo::isAppropriate(ETerrainType terrainType, int specialBattlefie CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node) { + std::string affinityStr[2] = { "might", "magic" }; + auto heroClass = new CHeroClass(); heroClass->imageBattleFemale = node["animation"]["battle"]["female"].String(); @@ -96,6 +99,9 @@ CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node) heroClass->imageMapMale = node["animation"]["map"]["male"].String(); heroClass->name = node["name"].String(); + heroClass->affinity = vstd::find_pos(affinityStr, node["affinity"].String()); + if (heroClass->affinity >= 2) //FIXME: MODS COMPATIBILITY + heroClass->affinity = 0; for(const std::string & pSkill : PrimarySkill::names) { @@ -109,6 +115,16 @@ CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node) heroClass->secSkillProbability.push_back(node["secondarySkills"][secSkill].Float()); } + //FIXME: MODS COMPATIBILITY + if (!node["commander"].isNull()) + { + VLC->modh->identifiers.requestIdentifier ("creature", node["commander"], + [=](si32 commanderID) + { + heroClass->commander = VLC->creh->creatures[commanderID]; + }); + } + heroClass->defaultTavernChance = node["defaultTavern"].Float(); for(auto & tavern : node["tavern"].Struct()) { diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h index 465ac723f..2c27093b7 100644 --- a/lib/CHeroHandler.h +++ b/lib/CHeroHandler.h @@ -97,16 +97,25 @@ public: class DLL_LINKAGE CHeroClass { public: + enum EClassAffinity + { + MIGHT, + MAGIC + }; + std::string identifier; std::string name; // translatable //double aggression; // not used in vcmi. TFaction faction; ui8 id; + ui8 affinity; // affility, using EClassAffinity enum // default chance for hero of specific class to appear in tavern, if field "tavern" was not set // resulting chance = sqrt(town.chance * heroClass.chance) ui32 defaultTavernChance; + CCreature * commander; + std::vector primarySkillInitial; // initial primary skills std::vector primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level std::vector primarySkillHighLevel;// same for high levels (> 10) @@ -128,7 +137,7 @@ public: h & identifier & name & faction & id & defaultTavernChance;// & aggression; h & primarySkillInitial & primarySkillLowLevel; h & primarySkillHighLevel & secSkillProbability; - h & selectionProbability; + h & selectionProbability & affinity & commander; h & imageBattleMale & imageBattleFemale & imageMapMale & imageMapFemale; } EAlignment::EAlignment getAlignment() const; diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 12d88b6b3..ddbc81cf9 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -824,7 +824,7 @@ void CGHeroInstance::initHero() if (VLC->modh->modules.COMMANDERS && !commander) { - commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction]->commander); + commander = new CCommanderInstance(type->heroClass->commander->idNumber); commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders commander->giveStackExp (exp); //after our exp is set } diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index e6534ebf2..bcf7da482 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -5,6 +5,7 @@ #include "CGeneralTextHandler.h" #include "JsonNode.h" #include "StringConstants.h" +#include "CCreatureHandler.h" #include "CModHandler.h" #include "CHeroHandler.h" #include "CArtHandler.h" @@ -628,11 +629,19 @@ CFaction * CTownHandler::loadFromJson(const JsonNode &source, std::string identi faction->name = source["name"].String(); faction->identifier = identifier; - VLC->modh->identifiers.requestIdentifier ("creature", source["commander"], + //FIXME: MODS COMPATIBILITY + if (!source["commander"].isNull()) + { + VLC->modh->identifiers.requestIdentifier ("creature", source["commander"], [=](si32 commanderID) { - faction->commander = CreatureID(commanderID); + for (auto ptr : VLC->heroh->classes.heroClasses) + { + if (ptr->commander == nullptr && ptr->faction == faction->index) + ptr->commander = VLC->creh->creatures[commanderID]; + } }); + } faction->creatureBg120 = source["creatureBackground"]["120px"].String(); faction->creatureBg130 = source["creatureBackground"]["130px"].String(); diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 3829039d4..bb2c39cdc 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -112,8 +112,6 @@ public: ETerrainType nativeTerrain; EAlignment::EAlignment alignment; - CreatureID commander; - CTown * town; //NOTE: can be null std::string creatureBg120; @@ -123,7 +121,7 @@ public: template void serialize(Handler &h, const int version) { - h & name & identifier & index & nativeTerrain & alignment & commander & town & creatureBg120 & creatureBg130 & puzzleMap; + h & name & identifier & index & nativeTerrain & alignment & town & creatureBg120 & creatureBg130 & puzzleMap; } };