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

Large changeset, first part of editing H3 objects via mods feature. Changes:

- loading of all objects (including H3 objects) will be directed by mod handlers
- common base for all handlers accessible from mod system (IHanderBase)
- json format changes: use struct with string ID's instead of vector

- fixed some gcc/clang errors and warnings
- fixed several cases of memory leaks and invalid memory access (mostly related to usage of bonus system and/or identifiers resolution)

Note that right now loading is much slower than before due to excessive json validation (or not fast enough validator)
This commit is contained in:
Ivan Savenko
2013-04-21 12:49:26 +00:00
parent 8a4f81b981
commit c6cc6e6301
85 changed files with 4714 additions and 4441 deletions

View File

@ -213,7 +213,7 @@ static void readBankLevel(const JsonNode &level, BankConfig &bc)
bc.easiest = level["easiest"].Float();
}
void CObjectHandler::load()
CObjectHandler::CObjectHandler()
{
logGlobal->traceStream() << "\t\tReading cregens ";
@ -614,7 +614,7 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &fro
bool nativeArmy = true;
BOOST_FOREACH(auto stack, stacks)
{
int nativeTerrain = VLC->townh->factions[stack.second->type->faction].nativeTerrain;
int nativeTerrain = VLC->townh->factions[stack.second->type->faction]->nativeTerrain;
if (nativeTerrain != -1 && nativeTerrain != from.terType)
{
@ -813,7 +813,7 @@ void CGHeroInstance::initHero()
if (VLC->modh->modules.COMMANDERS && !commander)
{
commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction].commander);
commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction]->commander);
commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
commander->giveStackExp (exp); //after our exp is set
}
@ -1672,9 +1672,9 @@ void CGDwelling::initObj()
creatures[0].second.push_back(crid);
if (subID >= VLC->generaltexth->creGens.size()) //very messy workaround
{
TFaction faction = VLC->creh->creatures[subID]->faction;
assert (VLC->townh->towns[faction].dwellingNames.size());
hoverName = VLC->townh->towns[faction].dwellingNames[VLC->creh->creatures[subID]->level - 1];
auto & dwellingNames = VLC->townh->factions[crs->faction]->town->dwellingNames;
assert (!dwellingNames.empty());
hoverName = dwellingNames[VLC->creh->creatures[subID]->level - 1];
}
else
hoverName = VLC->generaltexth->creGens[subID];
@ -2201,7 +2201,7 @@ void CGTownInstance::initObj()
///initialize town structures
{
blockVisit = true;
hoverName = name + ", " + VLC->townh->factions[town->typeID].name;
hoverName = name + ", " + town->faction->name;
if (subID == ETownType::DUNGEON)
creatures.resize(GameConstants::CREATURES_PER_TOWN+1);//extra dwelling for Dungeon
@ -2355,7 +2355,7 @@ void CGTownInstance::removeCapitols (PlayerColor owner) const
int CGTownInstance::getBoatType() const
{
switch (VLC->townh->factions[town->typeID].alignment)
switch (town->faction->alignment)
{
case EAlignment::EVIL : return 0;
case EAlignment::GOOD : return 1;
@ -2431,7 +2431,7 @@ std::vector<int> CGTownInstance::availableItemsIds(EMarketMode::EMarketMode mode
std::string CGTownInstance::nodeName() const
{
return "Town (" + (town ? VLC->townh->factions[town->typeID].name : "unknown") + ") of " + name;
return "Town (" + (town ? town->faction->name : "unknown") + ") of " + name;
}
void CGTownInstance::deserializationFix()
@ -2448,6 +2448,8 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::recreateBuildingsBonuses()
{
static TPropagatorPtr playerProp(new CPropagatorNodeType(PLAYER));
BonusList bl;
getExportedBonusList().getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
BOOST_FOREACH(Bonus *b, bl)
@ -2459,13 +2461,13 @@ void CGTownInstance::recreateBuildingsBonuses()
if(subID == ETownType::CASTLE) //castle
{
addBonusIfBuilt(BuildingID::LIGHTHOUSE, Bonus::SEA_MOVEMENT, +500, make_shared<CPropagatorNodeType>(PLAYER));
addBonusIfBuilt(BuildingID::GRAIL, Bonus::MORALE, +2, make_shared<CPropagatorNodeType>(PLAYER)); //colossus
addBonusIfBuilt(BuildingID::LIGHTHOUSE, Bonus::SEA_MOVEMENT, +500, playerProp);
addBonusIfBuilt(BuildingID::GRAIL, Bonus::MORALE, +2, playerProp); //colossus
}
else if(subID == ETownType::RAMPART) //rampart
{
addBonusIfBuilt(BuildingID::FOUNTAIN_OF_FORTUNE, Bonus::LUCK, +2); //fountain of fortune
addBonusIfBuilt(BuildingID::GRAIL, Bonus::LUCK, +2, make_shared<CPropagatorNodeType>(PLAYER)); //guardian spirit
addBonusIfBuilt(BuildingID::GRAIL, Bonus::LUCK, +2, playerProp); //guardian spirit
}
else if(subID == ETownType::TOWER) //tower
{
@ -2478,8 +2480,8 @@ void CGTownInstance::recreateBuildingsBonuses()
else if(subID == ETownType::NECROPOLIS) //necropolis
{
addBonusIfBuilt(BuildingID::COVER_OF_DARKNESS, Bonus::DARKNESS, +20);
addBonusIfBuilt(BuildingID::NECROMANCY_AMPLIFIER, Bonus::SECONDARY_SKILL_PREMY, +10, make_shared<CPropagatorNodeType>(PLAYER), SecondarySkill::NECROMANCY); //necromancy amplifier
addBonusIfBuilt(BuildingID::GRAIL, Bonus::SECONDARY_SKILL_PREMY, +20, make_shared<CPropagatorNodeType>(PLAYER), SecondarySkill::NECROMANCY); //Soul prison
addBonusIfBuilt(BuildingID::NECROMANCY_AMPLIFIER, Bonus::SECONDARY_SKILL_PREMY, +10, playerProp, SecondarySkill::NECROMANCY); //necromancy amplifier
addBonusIfBuilt(BuildingID::GRAIL, Bonus::SECONDARY_SKILL_PREMY, +20, playerProp, SecondarySkill::NECROMANCY); //Soul prison
}
else if(subID == ETownType::DUNGEON) //Dungeon
{
@ -2504,10 +2506,11 @@ void CGTownInstance::recreateBuildingsBonuses()
bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, int subtype /*= -1*/)
{
return addBonusIfBuilt(building, type, val, TPropagatorPtr(), subtype);
static auto emptyPropagator = TPropagatorPtr();
return addBonusIfBuilt(building, type, val, emptyPropagator, subtype);
}
bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr prop, int subtype /*= -1*/)
bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr & prop, int subtype /*= -1*/)
{
if(hasBuilt(building))
{
@ -2595,7 +2598,7 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
bool CGTownInstance::hasBuilt(BuildingID buildingID, int townID) const
{
if (townID == town->typeID || townID == ETownType::ANY)
if (townID == town->faction->index || townID == ETownType::ANY)
return hasBuilt(buildingID);
return false;
}
@ -2675,7 +2678,7 @@ void CGVisitableOPH::initObj()
case 2:
treePrice[Res::GEMS] = 10;
break;
default:
default:
break;
}
}
@ -2968,8 +2971,8 @@ void CGVisitableOPH::blockingDialogAnswered(const CGHeroInstance *hero, ui32 ans
case Obj::SCHOOL_OF_WAR:
schoolSelected(id, answer);
default:
assert(0);
default:
assert(0);
break;
}
}
@ -3100,9 +3103,11 @@ const std::string & CGCreature::getHoverText() const
{
if(stacks.empty())
{
static const std::string errorValue("!!!INVALID_STACK!!!");
//should not happen...
logGlobal->errorStream() << "Invalid stack at tile " << pos << ": subID=" << subID << "; id=" << id;
return "!!!INVALID_STACK!!!";
return errorValue; // references to temporary are illegal - use pre-constructed string
}
MetaString ms;
@ -6980,7 +6985,7 @@ void CArmedInstance::randomizeArmy(int type)
{
int level = (randID-VLC->creh->creatures.size()) / 2 -1;
bool upgrade = !(randID % 2);
j->second->setType(VLC->townh->towns[type].creatures[level][upgrade]);
j->second->setType(VLC->townh->factions[type]->town->creatures[level][upgrade]);
randID = -1;
}
@ -7035,7 +7040,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
BOOST_FOREACH(TFaction f, factions)
{
if (VLC->townh->factions[f].alignment != EAlignment::EVIL)
if (VLC->townh->factions[f]->alignment != EAlignment::EVIL)
mixableFactions++;
}
if (mixableFactions > 0)
@ -7397,7 +7402,7 @@ GrowthInfo::Entry::Entry(const std::string &format, int _count)
GrowthInfo::Entry::Entry(int subID, BuildingID building, int _count)
: count(_count)
{
description = boost::str(boost::format("%s %+d") % VLC->townh->towns[subID].buildings[building]->Name() % count);
description = boost::str(boost::format("%s %+d") % VLC->townh->factions[subID]->town->buildings[building]->Name() % count);
}
CTownAndVisitingHero::CTownAndVisitingHero()