1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

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
This commit is contained in:
Ivan Savenko 2013-12-13 18:27:54 +00:00
parent c5e0e48d98
commit 7d7e65a316
21 changed files with 167 additions and 67 deletions

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -17,9 +17,9 @@
"config/wog/creatures.json" "config/wog/creatures.json"
], ],
"factions" : "heroClasses" :
[ [
"config/wog/factions.json" "config/wog/heroClasses.json"
], ],
"filesystem": "filesystem":

View File

@ -4,7 +4,6 @@
"index" : 0, "index" : 0,
"nativeTerrain": "grass", "nativeTerrain": "grass",
"alignment" : "good", "alignment" : "good",
"commander" : "zealot",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASCAS", "120px" : "TPCASCAS",

View File

@ -4,7 +4,6 @@
"index" : 8, "index" : 8,
"nativeTerrain": "grass", "nativeTerrain": "grass",
"alignment" : "neutral", "alignment" : "neutral",
"commander" : "iceElemental",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASELE", "120px" : "TPCASELE",

View File

@ -4,7 +4,6 @@
"index" : 5, "index" : 5,
"nativeTerrain": "subterra", "nativeTerrain": "subterra",
"alignment" : "evil", "alignment" : "evil",
"commander" : "medusaQueen",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASDUN", "120px" : "TPCASDUN",

View File

@ -4,7 +4,6 @@
"index" : 7, "index" : 7,
"nativeTerrain": "swamp", "nativeTerrain": "swamp",
"alignment" : "neutral", "alignment" : "neutral",
"commander" : "lizardWarrior",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASFOR", "120px" : "TPCASFOR",

View File

@ -4,7 +4,6 @@
"index" : 3, "index" : 3,
"nativeTerrain": "lava", "nativeTerrain": "lava",
"alignment" : "evil", "alignment" : "evil",
"commander" : "magog",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASINF", "120px" : "TPCASINF",

View File

@ -4,7 +4,6 @@
"index" : 4, "index" : 4,
"nativeTerrain": "dirt", "nativeTerrain": "dirt",
"alignment" : "evil", "alignment" : "evil",
"commander" : "powerLich",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASNEC", "120px" : "TPCASNEC",

View File

@ -8,7 +8,6 @@
{ {
"120px" : "TPCASNEU", "120px" : "TPCASNEU",
"130px" : "CRBKGNEU" "130px" : "CRBKGNEU"
}, }
"commander" : "enchanter" //just in case
} }
} }

View File

@ -4,7 +4,6 @@
"index" : 1, "index" : 1,
"nativeTerrain": "grass", "nativeTerrain": "grass",
"alignment" : "good", "alignment" : "good",
"commander" : "grandElf",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASRAM", "120px" : "TPCASRAM",

View File

@ -4,7 +4,6 @@
"index" : 6, "index" : 6,
"nativeTerrain": "rough", "nativeTerrain": "rough",
"alignment" : "neutral", "alignment" : "neutral",
"commander" : "orcChieftain",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASSTR", "120px" : "TPCASSTR",

View File

@ -4,7 +4,6 @@
"index" : 2, "index" : 2,
"nativeTerrain" : "snow", "nativeTerrain" : "snow",
"alignment" : "good", "alignment" : "good",
"commander" : "archMage",
"creatureBackground" : "creatureBackground" :
{ {
"120px" : "TPCASTOW", "120px" : "TPCASTOW",

View File

@ -4,6 +4,8 @@
"index": 0, "index": 0,
"faction" : "castle", "faction" : "castle",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "zealot",
"animation": "animation":
{ {
"battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" }, "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" },
@ -15,6 +17,8 @@
"index": 1, "index": 1,
"faction" : "castle", "faction" : "castle",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "zealot",
"animation": "animation":
{ {
"battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" }, "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" },
@ -26,6 +30,8 @@
"index": 2, "index": 2,
"faction" : "rampart", "faction" : "rampart",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "grandElf",
"animation": "animation":
{ {
"battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" }, "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" },
@ -37,6 +43,8 @@
"index": 3, "index": 3,
"faction" : "rampart", "faction" : "rampart",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "grandElf",
"animation": "animation":
{ {
"battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" }, "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" },
@ -48,6 +56,8 @@
"index": 4, "index": 4,
"faction" : "tower", "faction" : "tower",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "archMage",
"animation": "animation":
{ {
"battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" }, "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" },
@ -59,6 +69,8 @@
"index": 5, "index": 5,
"faction" : "tower", "faction" : "tower",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "archMage",
"animation": "animation":
{ {
"battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" }, "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" },
@ -70,6 +82,8 @@
"index": 6, "index": 6,
"faction" : "inferno", "faction" : "inferno",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "magog",
"animation": "animation":
{ {
"battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" }, "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" },
@ -81,6 +95,8 @@
"index": 7, "index": 7,
"faction" : "inferno", "faction" : "inferno",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "magog",
"animation": "animation":
{ {
"battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" }, "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" },
@ -92,6 +108,8 @@
"index": 8, "index": 8,
"faction" : "necropolis", "faction" : "necropolis",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "powerLich",
"animation": "animation":
{ {
"battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" }, "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" },
@ -103,6 +121,8 @@
"index": 9, "index": 9,
"faction" : "necropolis", "faction" : "necropolis",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "powerLich",
"animation": "animation":
{ {
"battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" }, "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" },
@ -114,6 +134,8 @@
"index": 10, "index": 10,
"faction" : "dungeon", "faction" : "dungeon",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "medusaQueen",
"animation": "animation":
{ {
"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" }, "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
@ -125,6 +147,8 @@
"index": 11, "index": 11,
"faction" : "dungeon", "faction" : "dungeon",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "medusaQueen",
"animation": "animation":
{ {
"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" }, "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
@ -136,6 +160,8 @@
"index": 12, "index": 12,
"faction" : "stronghold", "faction" : "stronghold",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "orcChieftain",
"animation": "animation":
{ {
"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" }, "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
@ -147,6 +173,8 @@
"index": 13, "index": 13,
"faction" : "stronghold", "faction" : "stronghold",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "orcChieftain",
"animation": "animation":
{ {
"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" }, "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
@ -158,6 +186,8 @@
"index": 14, "index": 14,
"faction" : "fortress", "faction" : "fortress",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "lizardWarrior",
"animation": "animation":
{ {
"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" }, "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
@ -169,6 +199,8 @@
"index": 15, "index": 15,
"faction" : "fortress", "faction" : "fortress",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "lizardWarrior",
"animation": "animation":
{ {
"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" }, "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
@ -180,9 +212,11 @@
"index": 16, "index": 16,
"faction" : "conflux", "faction" : "conflux",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "might",
"commander" : "iceElemental",
"animation": "animation":
{ {
"battle" : { "male" : "CH16.DEF", "female" : "CH17.DEF" }, "battle" : { "male" : "CH16.DEF", "female" : "CH16.DEF" },
"map": { "male" : "AH16_.def", "female" : "AH16_.def" } "map": { "male" : "AH16_.def", "female" : "AH16_.def" }
} }
}, },
@ -191,9 +225,11 @@
"index": 17, "index": 17,
"faction" : "conflux", "faction" : "conflux",
"defaultTavern" : 5, "defaultTavern" : 5,
"affinity" : "magic",
"commander" : "iceElemental",
"animation": "animation":
{ {
"battle" : { "male" : "CH16.DEF", "female" : "CH17.DEF" }, "battle" : { "male" : "CH17.DEF", "female" : "CH17.DEF" },
"map": { "male" : "AH17_.def", "female" : "AH17_.def" } "map": { "male" : "AH17_.def", "female" : "AH17_.def" }
} }
} }

View File

@ -33,7 +33,7 @@
"description": "Json format for defining new faction (aka towns) in VCMI", "description": "Json format for defining new faction (aka towns) in VCMI",
"required" : [ "name", "alignment", "creatureBackground" ], "required" : [ "name", "alignment", "creatureBackground" ],
"dependencies" : { "dependencies" : {
"town" : [ "puzzleMap", "commander" ] "town" : [ "puzzleMap" ]
}, },
"additionalProperties" : false, "additionalProperties" : false,
@ -51,10 +51,6 @@
"enum" : [ "good", "neutral", "evil" ], "enum" : [ "good", "neutral", "evil" ],
"description": "Town alignment, good, neutral or evil" "description": "Town alignment, good, neutral or evil"
}, },
"commander": {
"type":"string",
"description": "Identifier of creature that is used as commander by heroes"
},
"creatureBackground": { "creatureBackground": {
"type":"object", "type":"object",
"additionalProperties" : false, "additionalProperties" : false,

View File

@ -5,7 +5,8 @@
"description" : "Format used to define classes of heroes in VCMI", "description" : "Format used to define classes of heroes in VCMI",
"required" : [ "required" : [
"animation", "faction", "highLevelChance", "lowLevelChance", "animation", "faction", "highLevelChance", "lowLevelChance",
"name", "primarySkills", "secondarySkills", "tavern", "defaultTavern" "name", "primarySkills", "secondarySkills", "tavern", "defaultTavern",
"affinity", "commander"
], ],
"additionalProperties" : false, "additionalProperties" : false,
@ -62,6 +63,15 @@
"type":"string", "type":"string",
"description": "Faction this hero class belongs to" "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": { "highLevelChance": {
"type":"object", "type":"object",
"description": "Chance to get specific primary skill on level-up, applicable for levels starting from 10", "description": "Chance to get specific primary skill on level-up, applicable for levels starting from 10",

View File

@ -7,6 +7,7 @@
#include "JsonNode.h" #include "JsonNode.h"
#include "StringConstants.h" #include "StringConstants.h"
#include "BattleHex.h" #include "BattleHex.h"
#include "CCreatureHandler.h"
#include "CModHandler.h" #include "CModHandler.h"
#include "CTownHandler.h" #include "CTownHandler.h"
#include "CObjectHandler.h" //for hero specialty #include "CObjectHandler.h" //for hero specialty
@ -45,7 +46,7 @@ SecondarySkill CHeroClass::chooseSecSkill(const std::set<SecondarySkill> & possi
bool CHeroClass::isMagicHero() const bool CHeroClass::isMagicHero() const
{ {
return id % 2; // 0 - might, 1 - magic return affinity == MAGIC;
} }
EAlignment::EAlignment CHeroClass::getAlignment() const EAlignment::EAlignment CHeroClass::getAlignment() const
@ -88,6 +89,8 @@ bool CObstacleInfo::isAppropriate(ETerrainType terrainType, int specialBattlefie
CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node) CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node)
{ {
std::string affinityStr[2] = { "might", "magic" };
auto heroClass = new CHeroClass(); auto heroClass = new CHeroClass();
heroClass->imageBattleFemale = node["animation"]["battle"]["female"].String(); 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->imageMapMale = node["animation"]["map"]["male"].String();
heroClass->name = node["name"].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) 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()); 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(); heroClass->defaultTavernChance = node["defaultTavern"].Float();
for(auto & tavern : node["tavern"].Struct()) for(auto & tavern : node["tavern"].Struct())
{ {

View File

@ -97,16 +97,25 @@ public:
class DLL_LINKAGE CHeroClass class DLL_LINKAGE CHeroClass
{ {
public: public:
enum EClassAffinity
{
MIGHT,
MAGIC
};
std::string identifier; std::string identifier;
std::string name; // translatable std::string name; // translatable
//double aggression; // not used in vcmi. //double aggression; // not used in vcmi.
TFaction faction; TFaction faction;
ui8 id; 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 // default chance for hero of specific class to appear in tavern, if field "tavern" was not set
// resulting chance = sqrt(town.chance * heroClass.chance) // resulting chance = sqrt(town.chance * heroClass.chance)
ui32 defaultTavernChance; ui32 defaultTavernChance;
CCreature * commander;
std::vector<int> primarySkillInitial; // initial primary skills std::vector<int> primarySkillInitial; // initial primary skills
std::vector<int> primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level std::vector<int> primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level
std::vector<int> primarySkillHighLevel;// same for high levels (> 10) std::vector<int> primarySkillHighLevel;// same for high levels (> 10)
@ -128,7 +137,7 @@ public:
h & identifier & name & faction & id & defaultTavernChance;// & aggression; h & identifier & name & faction & id & defaultTavernChance;// & aggression;
h & primarySkillInitial & primarySkillLowLevel; h & primarySkillInitial & primarySkillLowLevel;
h & primarySkillHighLevel & secSkillProbability; h & primarySkillHighLevel & secSkillProbability;
h & selectionProbability; h & selectionProbability & affinity & commander;
h & imageBattleMale & imageBattleFemale & imageMapMale & imageMapFemale; h & imageBattleMale & imageBattleFemale & imageMapMale & imageMapFemale;
} }
EAlignment::EAlignment getAlignment() const; EAlignment::EAlignment getAlignment() const;

View File

@ -824,7 +824,7 @@ void CGHeroInstance::initHero()
if (VLC->modh->modules.COMMANDERS && !commander) 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->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
commander->giveStackExp (exp); //after our exp is set commander->giveStackExp (exp); //after our exp is set
} }

View File

@ -5,6 +5,7 @@
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "JsonNode.h" #include "JsonNode.h"
#include "StringConstants.h" #include "StringConstants.h"
#include "CCreatureHandler.h"
#include "CModHandler.h" #include "CModHandler.h"
#include "CHeroHandler.h" #include "CHeroHandler.h"
#include "CArtHandler.h" #include "CArtHandler.h"
@ -628,11 +629,19 @@ CFaction * CTownHandler::loadFromJson(const JsonNode &source, std::string identi
faction->name = source["name"].String(); faction->name = source["name"].String();
faction->identifier = identifier; faction->identifier = identifier;
//FIXME: MODS COMPATIBILITY
if (!source["commander"].isNull())
{
VLC->modh->identifiers.requestIdentifier ("creature", source["commander"], VLC->modh->identifiers.requestIdentifier ("creature", source["commander"],
[=](si32 commanderID) [=](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->creatureBg120 = source["creatureBackground"]["120px"].String();
faction->creatureBg130 = source["creatureBackground"]["130px"].String(); faction->creatureBg130 = source["creatureBackground"]["130px"].String();

View File

@ -112,8 +112,6 @@ public:
ETerrainType nativeTerrain; ETerrainType nativeTerrain;
EAlignment::EAlignment alignment; EAlignment::EAlignment alignment;
CreatureID commander;
CTown * town; //NOTE: can be null CTown * town; //NOTE: can be null
std::string creatureBg120; std::string creatureBg120;
@ -123,7 +121,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> 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;
} }
}; };