1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- Implemented "mapObject" entry for hero classes

- Updated schemas
- Some bugfixing
This commit is contained in:
Ivan Savenko 2014-06-16 19:27:26 +03:00
parent 89b89ff85d
commit 09d595e385
15 changed files with 125 additions and 164 deletions

View File

@ -22,6 +22,7 @@
#include "../lib/GameConstants.h"
#include "../lib/CStopWatch.h"
#include "CAnimation.h"
#include "../lib/mapObjects/CObjectClassesHandler.h"
using namespace boost::assign;
using namespace CSDL_Ext;
@ -145,13 +146,11 @@ void Graphics::loadHeroAnims()
for(auto & elem : CGI->heroh->classes.heroClasses)
{
const CHeroClass * hc = elem;
if (!vstd::contains(heroAnims, hc->imageMapFemale))
heroAnims[hc->imageMapFemale] = loadHeroAnim(hc->imageMapFemale, rotations);
if (!vstd::contains(heroAnims, hc->imageMapMale))
heroAnims[hc->imageMapMale] = loadHeroAnim(hc->imageMapMale, rotations);
for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->id)->getTemplates())
{
if (!heroAnims.count(templ.animationFile))
heroAnims[templ.animationFile] = loadHeroAnim(templ.animationFile, rotations);
}
}
boatAnims.push_back(loadHeroAnim("AB01_.DEF", rotations));

View File

@ -541,10 +541,8 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
//pick graphics of hero (or boat if hero is sailing)
if (themp->boat)
iv = &graphics->boatAnims[themp->boat->subID]->ourImages;
else if (themp->sex)
iv = &graphics->heroAnims[themp->type->heroClass->imageMapFemale]->ourImages;
else
iv = &graphics->heroAnims[themp->type->heroClass->imageMapMale]->ourImages;
iv = &graphics->heroAnims[themp->appearance.animationFile]->ourImages;
//pick appropriate flag set
if(themp->boat)

View File

@ -6,11 +6,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "zealot",
"animation":
{
"battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" },
"map": { "male" : "AH00_.def", "female" : "AH00_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH00_.def" } } },
"animation": { "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" } }
},
"cleric" :
{
@ -19,11 +16,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "zealot",
"animation":
{
"battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" },
"map": { "male" : "AH01_.def", "female" : "AH01_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH01_.def" } } },
"animation": { "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" } }
},
"ranger" :
{
@ -32,11 +26,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "grandElf",
"animation":
{
"battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" },
"map": { "male" : "AH02_.def", "female" : "AH02_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH02_.def" } } },
"animation": { "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" } }
},
"druid" :
{
@ -45,11 +36,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "grandElf",
"animation":
{
"battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" },
"map": { "male" : "AH03_.def", "female" : "AH03_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH03_.def" } } },
"animation": { "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" } }
},
"alchemist" :
{
@ -58,11 +46,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "archMage",
"animation":
{
"battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" },
"map": { "male" : "AH04_.def", "female" : "AH04_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH04_.def" } } },
"animation": { "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" } }
},
"wizard" :
{
@ -71,11 +56,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "archMage",
"animation":
{
"battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" },
"map": { "male" : "AH05_.def", "female" : "AH05_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH05_.def" } } },
"animation": { "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" } }
},
"demoniac" :
{
@ -84,11 +66,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "magog",
"animation":
{
"battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" },
"map": { "male" : "AH06_.def", "female" : "AH06_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH06_.def" } } },
"animation": { "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" } }
},
"heretic" :
{
@ -97,11 +76,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "magog",
"animation":
{
"battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" },
"map": { "male" : "AH07_.def", "female" : "AH07_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH07_.def" } } },
"animation": { "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" } }
},
"deathknight" :
{
@ -110,11 +86,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "powerLich",
"animation":
{
"battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" },
"map": { "male" : "AH08_.def", "female" : "AH08_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH08_.def" } } },
"animation": { "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" } }
},
"necromancer" :
{
@ -123,11 +96,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "powerLich",
"animation":
{
"battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" },
"map": { "male" : "AH09_.def", "female" : "AH09_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH09_.def" } } },
"animation": { "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" } }
},
"warlock" :
{
@ -136,11 +106,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "medusaQueen",
"animation":
{
"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
"map": { "male" : "AH10_.def", "female" : "AH10_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH10_.def" } } },
"animation": { "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" } }
},
"overlord" :
{
@ -149,11 +116,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "medusaQueen",
"animation":
{
"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
"map": { "male" : "AH11_.def", "female" : "AH11_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH11_.def" } } },
"animation": { "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" } }
},
"barbarian" :
{
@ -162,11 +126,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "orcChieftain",
"animation":
{
"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
"map": { "male" : "AH12_.def", "female" : "AH12_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH12_.def" } } },
"animation": { "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" } }
},
"battlemage" :
{
@ -175,11 +136,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "orcChieftain",
"animation":
{
"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
"map": { "male" : "AH13_.def", "female" : "AH13_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH13_.def" } } },
"animation": { "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" } }
},
"beastmaster" :
{
@ -188,11 +146,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "lizardWarrior",
"animation":
{
"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
"map": { "male" : "AH14_.def", "female" : "AH14_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH14_.def" } } },
"animation": { "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" } }
},
"witch" :
{
@ -201,11 +156,8 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "lizardWarrior",
"animation":
{
"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
"map": { "male" : "AH15_.def", "female" : "AH15_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH15_.def" } } },
"animation": { "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" } }
},
"planeswalker" :
{
@ -214,11 +166,8 @@
"defaultTavern" : 5,
"affinity" : "might",
"commander" : "iceElemental",
"animation":
{
"battle" : { "male" : "CH16.DEF", "female" : "CH16.DEF" },
"map": { "male" : "AH16_.def", "female" : "AH16_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH16_.def" } } },
"animation": { "battle" : { "male" : "CH16.DEF", "female" : "CH16.DEF" } }
},
"elementalist" :
{
@ -227,10 +176,7 @@
"defaultTavern" : 5,
"affinity" : "magic",
"commander" : "iceElemental",
"animation":
{
"battle" : { "male" : "CH17.DEF", "female" : "CH17.DEF" },
"map": { "male" : "AH17_.def", "female" : "AH17_.def" }
}
"mapObject" : { "templates" : { "default" : { "animation" : "AH17_.def" } } },
"animation": { "battle" : { "male" : "CH17.DEF", "female" : "CH17.DEF" } }
}
}

View File

@ -104,46 +104,16 @@
"type":"object",
"additionalProperties" : false,
"required" : [
"adventureMap", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
"mapObject", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
"hallBackground", "hallSlots", "horde", "mageGuild", "moatDamage", "defaultTavern", "tavernVideo", "guildBackground", "musicTheme", "siege", "structures", "townBackground", "warMachine"
],
"description": "town",
"properties":{
"adventureMap": {
"type":"object",
"additionalProperties" : false,
"description": "Paths to images of object on adventure map",
"required" : [ "capitol", "castle", "village" ],
"properties":{
"capitol": {
"type":"string",
"description": "Town with capitol",
"format" : "defFile"
},
"castle": {
"type":"string",
"description": "Town with built fort",
"format" : "defFile"
},
"village": {
"type":"string",
"description": "Village without built fort",
"format" : "defFile"
},
"dwellings" : {
"type" : "array",
"minItems" : 7,
"maxItems" : 7,
"description" : "Dwellings on adventure map",
"items" : {
"type" : "object",
"additionalProperties" : false,
"required" : [ "name", "graphics" ],
"properties" : {
"name": { "type":"string" },
"graphics": { "type":"string", "format" : "defFile" }
}
}
"mapObject" : {
"properties" : {
"filters" : {
"type" : "object",
"additionalProperties" : { "type" : "array" }
}
}
},

View File

@ -6,7 +6,7 @@
"required" : [
"animation", "faction", "highLevelChance", "lowLevelChance",
"name", "primarySkills", "secondarySkills", "tavern", "defaultTavern",
"affinity", "commander"
"affinity", "commander", "mapObject"
],
"additionalProperties" : false,
@ -15,7 +15,7 @@
"type":"object",
"additionalProperties" : false,
"description": "Files related to hero animation",
"required": [ "battle", "map" ],
"required": [ "battle" ],
"properties":{
"battle": {
"type":"object",
@ -34,24 +34,14 @@
"format" : "defFile"
}
}
},
"map": {
"type":"object",
"additionalProperties" : false,
"description": "Hero animations for adventure map",
"required": [ "female", "male" ],
"properties":{
"female": {
"type":"string",
"description": "Female version. Warning: not implemented!",
"format" : "defFile"
},
"male": {
"type":"string",
"description": "Male version",
"format" : "defFile"
}
}
}
}
},
"mapObject" : {
"properties" : {
"filters" : {
"type" : "object",
"additionalProperties" : { "type" : "array" }
}
}
},

View File

@ -17,7 +17,7 @@
"base": {
"type" : "object"
},
"types": {
"templates": {
"type":"object",
"additionalProperties": {
"$ref" : "vcmi:objectTemplate"

View File

@ -104,6 +104,7 @@ CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node)
heroClass->imageBattleFemale = node["animation"]["battle"]["female"].String();
heroClass->imageBattleMale = node["animation"]["battle"]["male"].String();
//MODS COMPATIBILITY FOR 0.96
heroClass->imageMapFemale = node["animation"]["map"]["female"].String();
heroClass->imageMapMale = node["animation"]["map"]["male"].String();
@ -223,7 +224,7 @@ void CHeroClassHandler::loadObject(std::string scope, std::string name, const Js
VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index)
{
JsonNode classConf;
JsonNode classConf = data["mapObject"];
classConf["heroClass"].String() = name;
classConf.setMeta(scope);
VLC->objtypeh->loadSubObject(name, classConf, index, object->id);

View File

@ -764,6 +764,15 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
config["faction"].String() = object->identifier;
config["faction"].meta = scope;
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
// MODS COMPATIBILITY FOR 0.96
auto & advMap = data["town"]["adventureMap"];
if (!advMap["fort"].isNull())
{
JsonNode config;
config["appearance"] = advMap["fort"];
VLC->objtypeh->getHandlerFor(index, object->index)->addTemplate(config);
}
});
}

View File

@ -232,9 +232,9 @@ void CGHeroInstance::initHero(HeroTypeID SUBID)
void CGHeroInstance::setType(si32 ID, si32 subID)
{
assert(ID == Obj::HERO); // just in case
CGObjectInstance::setType(ID, subID);
type = VLC->heroh->heroes[subID];
portrait = type->imageIndex;
CGObjectInstance::setType(ID, type->heroClass->id);
randomizeArmy(type->heroClass->faction);
}
@ -472,6 +472,10 @@ void CGHeroInstance::initObj()
skillsInfo.resetMagicSchoolCounter();
skillsInfo.resetWisdomCounter();
auto customApp = VLC->objtypeh->getHandlerFor(ID, type->heroClass->id)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this);
if (customApp)
appearance = customApp.get();
for(const auto &spec : type->spec) //TODO: unfity with bonus system
{
auto bonus = new Bonus();

View File

@ -563,6 +563,7 @@ void CGTownInstance::initObj()
//add special bonuses from buildings
recreateBuildingsBonuses();
updateAppearance();
}
void CGTownInstance::newTurn() const

View File

@ -105,7 +105,7 @@ void readTextFile(Container & objects, std::string path)
std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
{
readTextFile(legacyTemplates, "Data/Objects.txt");
readTextFile(legacyTemplates, "Data/Heroes.txt");
//readTextFile(legacyTemplates, "Data/Heroes.txt");
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
assert(dataSize == 256);
@ -161,7 +161,7 @@ CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(co
auto obj = new ObjectContainter();
obj->name = json["name"].String();
obj->handlerName = json["handler"].String();
obj->base = json["base"]; // FIXME: when this data will be actually merged?
obj->base = json["base"];
obj->id = selectNextID(json["index"], objects, 256);
for (auto entry : json["types"].Struct())
{

View File

@ -130,7 +130,7 @@ public:
//CGObjectInstance& operator=(const CGObjectInstance & right);
virtual const std::string & getHoverText() const;
void setType(si32 ID, si32 subID);
virtual void setType(si32 ID, si32 subID);
///IObjectInterface
void initObj() override;

View File

@ -91,10 +91,34 @@ void CHeroInstanceConstructor::initTypeData(const JsonNode & input)
{
VLC->modh->identifiers.requestIdentifier("heroClass", input["heroClass"],
[&](si32 index) { heroClass = VLC->heroh->classes.heroClasses[index]; });
filtersJson = input["filters"];
}
void CHeroInstanceConstructor::afterLoadFinalization()
{
for (auto entry : filtersJson.Struct())
{
filters[entry.first] = LogicalExpression<HeroTypeID>(entry.second, [this](const JsonNode & node)
{
return HeroTypeID(VLC->modh->identifiers.getIdentifier("hero", node.Vector()[0]).get());
});
}
}
bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, const ObjectTemplate & templ) const
{
auto hero = dynamic_cast<const CGHeroInstance *>(object);
auto heroTest = [&](const HeroTypeID & id)
{
return hero->type->ID == id;
};
if (filters.count(templ.stringID))
{
return filters.at(templ.stringID).test(heroTest);
}
return false;
}

View File

@ -73,20 +73,35 @@ public:
void initTypeData(const JsonNode & input);
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
void afterLoadFinalization();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & filtersJson & faction & filters;
h & static_cast<CDefaultObjectTypeHandler<CGTownInstance>&>(*this);
}
};
class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance>
{
JsonNode filtersJson;
protected:
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
public:
CHeroClass * heroClass;
std::map<std::string, LogicalExpression<HeroTypeID>> filters;
CHeroInstanceConstructor();
CGObjectInstance * create(ObjectTemplate tmpl) const;
void initTypeData(const JsonNode & input);
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
void afterLoadFinalization();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & filtersJson & heroClass & filters;
h & static_cast<CDefaultObjectTypeHandler<CGHeroInstance>&>(*this);
}
};
class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
@ -106,4 +121,10 @@ public:
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
bool producesCreature(const CCreature * crea) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & availableCreatures & guards;
h & static_cast<CDefaultObjectTypeHandler<CGDwelling>&>(*this);
}
};

View File

@ -185,8 +185,6 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
void ObjectTemplate::readJson(const JsonNode &node)
{
//id = Obj(node["basebase"].Float()); // temporary, should be removed and determined indirectly via object type parent (e.g. base->base)
//subid = node["base"].Float();
animationFile = node["animation"].String();
const JsonVector & visitDirs = node["visitableFrom"].Vector();