1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Reduced number of accesses to CGObjectInstance::subID

This commit is contained in:
Ivan Savenko
2023-10-24 17:11:25 +03:00
parent 455d8d4738
commit 03e1169781
27 changed files with 135 additions and 97 deletions

View File

@@ -274,17 +274,16 @@ void CampaignState::setCurrentMapAsConquered(std::vector<CGHeroInstance *> heroe
for (auto * hero : heroes) for (auto * hero : heroes)
{ {
HeroTypeID heroType(hero->subID);
JsonNode node = CampaignState::crossoverSerialize(hero); JsonNode node = CampaignState::crossoverSerialize(hero);
if (reservedHeroes.count(heroType)) if (reservedHeroes.count(hero->getHeroType()))
{ {
logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->subID, hero->getNameTranslated()); logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroType(), hero->getNameTranslated());
globalHeroPool[heroType] = node; globalHeroPool[hero->getHeroType()] = node;
} }
else else
{ {
logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->subID, hero->getNameTranslated()); logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->getHeroType(), hero->getNameTranslated());
scenarioHeroPool[*currentMap].push_back(node); scenarioHeroPool[*currentMap].push_back(node);
} }
} }

View File

@@ -407,7 +407,7 @@ public:
static std::string entityType(); static std::string entityType();
}; };
class ObjBase : public IdentifierBase class MapObjectBaseID : public IdentifierBase
{ {
public: public:
enum Type enum Type
@@ -552,15 +552,38 @@ public:
}; };
}; };
class DLL_LINKAGE Obj : public IdentifierWithEnum<Obj, ObjBase> class DLL_LINKAGE MapObjectID : public IdentifierWithEnum<MapObjectID, MapObjectBaseID>
{ {
public: public:
using IdentifierWithEnum<Obj, ObjBase>::IdentifierWithEnum; using IdentifierWithEnum<MapObjectID, MapObjectBaseID>::IdentifierWithEnum;
static std::string encode(int32_t index); static std::string encode(int32_t index);
static si32 decode(const std::string & identifier); static si32 decode(const std::string & identifier);
}; };
class MapObjectSubID : public Identifier<MapObjectSubID>
{
public:
constexpr MapObjectSubID(const IdentifierBase & value):
Identifier<MapObjectSubID>(value.getNum())
{}
constexpr MapObjectSubID(int32_t value):
Identifier<MapObjectSubID>(value)
{}
MapObjectSubID & operator =(int32_t value)
{
this->num = value;
return *this;
}
MapObjectSubID & operator =(const IdentifierBase & value)
{
this->num = value.getNum();
return *this;
}
};
class DLL_LINKAGE RoadId : public Identifier<RoadId> class DLL_LINKAGE RoadId : public Identifier<RoadId>
{ {
public: public:
@@ -966,6 +989,7 @@ public:
// Deprecated // Deprecated
// TODO: remove // TODO: remove
using Obj = MapObjectID;
using ETownType = FactionID; using ETownType = FactionID;
using EGameResID = GameResID; using EGameResID = GameResID;
using River = RiverId; using River = RiverId;

View File

@@ -77,7 +77,7 @@ public:
} }
}; };
static CGObjectInstance * createObject(const Obj & id, int subid, const int3 & pos, const PlayerColor & owner) static CGObjectInstance * createObject(MapObjectID id, MapObjectSubID subid, const int3 & pos, const PlayerColor & owner)
{ {
CGObjectInstance * nobj; CGObjectInstance * nobj;
switch(id) switch(id)
@@ -810,7 +810,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy
} }
} }
CGObjectInstance * hero = createObject(Obj::HERO, heroTypeId.getNum(), townPos, playerColor); CGObjectInstance * hero = createObject(Obj::HERO, heroTypeId, townPos, playerColor);
hero->pos += hero->getVisitableOffset(); hero->pos += hero->getVisitableOffset();
map->getEditManager()->insertObject(hero); map->getEditManager()->insertObject(hero);
} }
@@ -880,8 +880,6 @@ void CGameState::initHeroes()
CGBoat * boat = dynamic_cast<CGBoat*>(handler->create()); CGBoat * boat = dynamic_cast<CGBoat*>(handler->create());
handler->configureObject(boat, gs->getRandomGenerator()); handler->configureObject(boat, gs->getRandomGenerator());
boat->ID = Obj::BOAT;
boat->subID = hero->getBoatType().getNum();
boat->pos = hero->pos; boat->pos = hero->pos;
boat->appearance = handler->getTemplates().front(); boat->appearance = handler->getTemplates().front();
boat->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size())); boat->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size()));

View File

@@ -213,7 +213,7 @@ void CGameStateCampaign::placeCampaignHeroes()
std::set<HeroTypeID> heroesToRemove = campaignState->getReservedHeroes(); std::set<HeroTypeID> heroesToRemove = campaignState->getReservedHeroes();
for(auto & campaignHeroReplacement : campaignHeroReplacements) for(auto & campaignHeroReplacement : campaignHeroReplacements)
heroesToRemove.insert(HeroTypeID(campaignHeroReplacement.hero->subID)); heroesToRemove.insert(campaignHeroReplacement.hero->getHeroType());
for(auto & heroID : heroesToRemove) for(auto & heroID : heroesToRemove)
{ {
@@ -339,7 +339,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders(const std::vector<CampaignHer
if(heroPlaceholder->tempOwner.isValidPlayer()) if(heroPlaceholder->tempOwner.isValidPlayer())
heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->tempOwner = heroPlaceholder->tempOwner;
heroToPlace->pos = heroPlaceholder->pos; heroToPlace->pos = heroPlaceholder->pos;
heroToPlace->type = VLC->heroh->objects[heroToPlace->subID]; heroToPlace->type = VLC->heroh->objects[heroToPlace->getHeroType().getNum()];
heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front(); heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front();
gameState->map->removeBlockVisTiles(heroPlaceholder, true); gameState->map->removeBlockVisTiles(heroPlaceholder, true);
@@ -396,7 +396,7 @@ std::vector<CampaignHeroReplacement> CGameStateCampaign::generateCampaignHeroesT
CGHeroInstance * hero = CampaignState::crossoverDeserialize(node, gameState->map); CGHeroInstance * hero = CampaignState::crossoverDeserialize(node, gameState->map);
logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->subID, hero->getNameTranslated()); logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->getHeroType(), hero->getNameTranslated());
campaignHeroReplacements.emplace_back(hero, placeholder->id); campaignHeroReplacements.emplace_back(hero, placeholder->id);
} }
@@ -422,7 +422,7 @@ std::vector<CampaignHeroReplacement> CGameStateCampaign::generateCampaignHeroesT
CGHeroInstance * hero = CampaignState::crossoverDeserialize(*nodeListIter, gameState->map); CGHeroInstance * hero = CampaignState::crossoverDeserialize(*nodeListIter, gameState->map);
nodeListIter++; nodeListIter++;
logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->subID, hero->getNameTranslated()); logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->getHeroType(), hero->getNameTranslated());
campaignHeroReplacements.emplace_back(hero, placeholder->id); campaignHeroReplacements.emplace_back(hero, placeholder->id);
} }
@@ -468,7 +468,7 @@ void CGameStateCampaign::initHeroes()
{ {
for (auto & heroe : heroes) for (auto & heroe : heroes)
{ {
if (heroe->subID == chosenBonus->info1) if (heroe->getHeroType().getNum() == chosenBonus->info1)
{ {
giveCampaignBonusToHero(heroe); giveCampaignBonusToHero(heroe);
break; break;
@@ -557,7 +557,7 @@ void CGameStateCampaign::initTowns()
if(gameState->scenarioOps->campState->formatVCMI()) if(gameState->scenarioOps->campState->formatVCMI())
newBuilding = BuildingID(chosenBonus->info1); newBuilding = BuildingID(chosenBonus->info1);
else else
newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->subID, town->builtBuildings); newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFaction(), town->builtBuildings);
// Build granted building & all prerequisites - e.g. Mages Guild Lvl 3 should also give Mages Guild Lvl 1 & 2 // Build granted building & all prerequisites - e.g. Mages Guild Lvl 3 should also give Mages Guild Lvl 1 & 2
while(true) while(true)

View File

@@ -25,7 +25,7 @@ std::map<HeroTypeID, CGHeroInstance*> TavernHeroesPool::unusedHeroesFromPool() c
{ {
std::map<HeroTypeID, CGHeroInstance*> pool = heroesPool; std::map<HeroTypeID, CGHeroInstance*> pool = heroesPool;
for(const auto & slot : currentTavern) for(const auto & slot : currentTavern)
pool.erase(HeroTypeID(slot.hero->subID)); pool.erase(slot.hero->getHeroType());
return pool; return pool;
} }
@@ -34,7 +34,7 @@ TavernSlotRole TavernHeroesPool::getSlotRole(HeroTypeID hero) const
{ {
for (auto const & slot : currentTavern) for (auto const & slot : currentTavern)
{ {
if (HeroTypeID(slot.hero->subID) == hero) if (slot.hero->getHeroType() == hero)
return slot.role; return slot.role;
} }
return TavernSlotRole::NONE; return TavernSlotRole::NONE;
@@ -132,7 +132,7 @@ void TavernHeroesPool::onNewDay()
void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero) void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero)
{ {
heroesPool[HeroTypeID(hero->subID)] = hero; heroesPool[hero->getHeroType()] = hero;
} }
void TavernHeroesPool::setAvailability(HeroTypeID hero, std::set<PlayerColor> mask) void TavernHeroesPool::setAvailability(HeroTypeID hero, std::set<PlayerColor> mask)

View File

@@ -46,7 +46,7 @@ void CBank::initObj(CRandomGenerator & rand)
{ {
daycounter = 0; daycounter = 0;
resetDuration = 0; resetDuration = 0;
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); getObjectHandler()->configureObject(this, rand);
} }
bool CBank::isCoastVisitable() const bool CBank::isCoastVisitable() const

View File

@@ -28,7 +28,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
if(stacks.empty()) if(stacks.empty())
{ {
//should not happen... //should not happen...
logGlobal->error("Invalid stack at tile %s: subID=%d; id=%d", pos.toString(), subID, id.getNum()); logGlobal->error("Invalid stack at tile %s: subID=%d; id=%d", pos.toString(), getCreature(), id.getNum());
return "INVALID_STACK"; return "INVALID_STACK";
} }
@@ -41,7 +41,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
else else
ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex); ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex);
ms.appendRawString(" "); ms.appendRawString(" ");
ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID); ms.appendLocalString(EMetaText::CRE_PL_NAMES, getCreature());
hoverName = ms.toString(); hoverName = ms.toString();
return hoverName; return hoverName;
} }
@@ -54,7 +54,7 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
MetaString ms; MetaString ms;
ms.appendNumber(stacks.begin()->second->count); ms.appendNumber(stacks.begin()->second->count);
ms.appendRawString(" "); ms.appendRawString(" ");
ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID); ms.appendLocalString(EMetaText::CRE_PL_NAMES, getCreature());
ms.appendRawString("\n\n"); ms.appendRawString("\n\n");
@@ -132,7 +132,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
ynd.text.appendLocalString(EMetaText::ADVOB_TXT, 86); ynd.text.appendLocalString(EMetaText::ADVOB_TXT, 86);
ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, subID); ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, getCreature());
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
break; break;
} }
@@ -146,7 +146,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
std::string tmp = VLC->generaltexth->advobtxt[90]; std::string tmp = VLC->generaltexth->advobtxt[90];
boost::algorithm::replace_first(tmp, "%d", std::to_string(getStackCount(SlotID(0)))); boost::algorithm::replace_first(tmp, "%d", std::to_string(getStackCount(SlotID(0))));
boost::algorithm::replace_first(tmp, "%d", std::to_string(action)); boost::algorithm::replace_first(tmp, "%d", std::to_string(action));
boost::algorithm::replace_first(tmp,"%s",VLC->creh->objects[subID]->getNamePluralTranslated()); boost::algorithm::replace_first(tmp,"%s",VLC->creatures()->getById(getCreature())->getNamePluralTranslated());
ynd.text.appendRawString(tmp); ynd.text.appendRawString(tmp);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
break; break;
@@ -155,6 +155,11 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
} }
CreatureID CGCreature::getCreature() const
{
return CreatureID(getObjTypeIndex().getNum());
}
void CGCreature::initObj(CRandomGenerator & rand) void CGCreature::initObj(CRandomGenerator & rand)
{ {
blockVisit = true; blockVisit = true;
@@ -177,16 +182,16 @@ void CGCreature::initObj(CRandomGenerator & rand)
break; break;
} }
stacks[SlotID(0)]->setType(CreatureID(subID)); stacks[SlotID(0)]->setType(getCreature());
TQuantity &amount = stacks[SlotID(0)]->count; TQuantity &amount = stacks[SlotID(0)]->count;
CCreature &c = *VLC->creh->objects[subID]; const Creature * c = VLC->creatures()->getById(getCreature());
if(amount == 0) if(amount == 0)
{ {
amount = rand.nextInt(c.ammMin, c.ammMax); amount = rand.nextInt(c->getAdvMapAmountMin(), c->getAdvMapAmountMax());
if(amount == 0) //armies with 0 creatures are illegal if(amount == 0) //armies with 0 creatures are illegal
{ {
logGlobal->warn("Stack %s cannot have 0 creatures. Check properties of %s", nodeName(), c.nodeName()); logGlobal->warn("Stack cannot have 0 creatures. Check properties of %s", c->getJsonKey());
amount = 1; amount = 1;
} }
} }
@@ -252,7 +257,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
powerFactor = -3; powerFactor = -3;
std::set<CreatureID> myKindCres; //what creatures are the same kind as we std::set<CreatureID> myKindCres; //what creatures are the same kind as we
const CCreature * myCreature = VLC->creh->objects[subID]; const CCreature * myCreature = VLC->creh->objects[getCreature().getNum()];
myKindCres.insert(myCreature->getId()); //we myKindCres.insert(myCreature->getId()); //we
myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades
@@ -290,7 +295,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
return JOIN_FOR_FREE; return JOIN_FOR_FREE;
else if(diplomacy * 2 + sympathy + 1 >= character) else if(diplomacy * 2 + sympathy + 1 >= character)
return VLC->creatures()->getByIndex(subID)->getRecruitCost(EGameResID::GOLD) * getStackCount(SlotID(0)); //join for gold return VLC->creatures()->getById(getCreature())->getRecruitCost(EGameResID::GOLD) * getStackCount(SlotID(0)); //join for gold
} }
//we are still here - creatures have not joined hero, flee or fight //we are still here - creatures have not joined hero, flee or fight
@@ -404,7 +409,7 @@ void CGCreature::flee( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
ynd.text.appendLocalString(EMetaText::ADVOB_TXT,91); ynd.text.appendLocalString(EMetaText::ADVOB_TXT,91);
ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, subID); ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, getCreature());
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
} }

View File

@@ -44,6 +44,7 @@ public:
void newTurn(CRandomGenerator & rand) const override; void newTurn(CRandomGenerator & rand) const override;
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
CreatureID getCreature() const;
//stack formation depends on position, //stack formation depends on position,
bool containsUpgradedStack() const; bool containsUpgradedStack() const;

View File

@@ -95,7 +95,7 @@ void CGDwelling::initObj(CRandomGenerator & rand)
case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR1:
case Obj::CREATURE_GENERATOR4: case Obj::CREATURE_GENERATOR4:
{ {
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); getObjectHandler()->configureObject(this, rand);
if (getOwner() != PlayerColor::NEUTRAL) if (getOwner() != PlayerColor::NEUTRAL)
cb->gameState()->players[getOwner()].dwellings.emplace_back(this); cb->gameState()->players[getOwner()].dwellings.emplace_back(this);

View File

@@ -285,6 +285,11 @@ PlayerColor CGHeroInstance::getOwner() const
return tempOwner; return tempOwner;
} }
HeroTypeID CGHeroInstance::getHeroType() const
{
return HeroTypeID(getObjTypeIndex().getNum());
}
void CGHeroInstance::initHero(CRandomGenerator & rand, const HeroTypeID & SUBID) void CGHeroInstance::initHero(CRandomGenerator & rand, const HeroTypeID & SUBID)
{ {
subID = SUBID.getNum(); subID = SUBID.getNum();
@@ -305,7 +310,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
{ {
assert(validTypes(true)); assert(validTypes(true));
if(!type) if(!type)
type = VLC->heroh->objects[subID]; type = VLC->heroh->objects[getHeroType().getNum()];
if (ID == Obj::HERO) if (ID == Obj::HERO)
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
@@ -1050,7 +1055,7 @@ HeroTypeID CGHeroInstance::getPortraitSource() const
if (customPortraitSource.isValid()) if (customPortraitSource.isValid())
return customPortraitSource; return customPortraitSource;
else else
return HeroTypeID(subID); return getHeroType();
} }
int32_t CGHeroInstance::getIconIndex() const int32_t CGHeroInstance::getIconIndex() const
@@ -1502,7 +1507,7 @@ std::string CGHeroInstance::getHeroTypeName() const
} }
else else
{ {
return VLC->heroh->objects[subID]->getJsonKey(); return VLC->heroh->objects[getHeroType()]->getJsonKey();
} }
} }
return ""; return "";
@@ -1736,7 +1741,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler)
if(!appearance) if(!appearance)
{ {
// crossoverDeserialize // crossoverDeserialize
type = VLC->heroh->objects[subID]; type = VLC->heroh->objects[getHeroType()];
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
} }

View File

@@ -231,6 +231,7 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
HeroTypeID getHeroType() const;
void setType(si32 ID, si32 subID) override; void setType(si32 ID, si32 subID) override;
void initHero(CRandomGenerator & rand); void initHero(CRandomGenerator & rand);

View File

@@ -25,7 +25,7 @@ VCMI_LIB_NAMESPACE_BEGIN
void CGMarket::initObj(CRandomGenerator & rand) void CGMarket::initObj(CRandomGenerator & rand)
{ {
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); getObjectHandler()->configureObject(this, rand);
} }
void CGMarket::onHeroVisit(const CGHeroInstance * h) const void CGMarket::onHeroVisit(const CGHeroInstance * h) const

View File

@@ -40,12 +40,12 @@ CGObjectInstance::CGObjectInstance():
//must be instantiated in .cpp file for access to complete types of all member fields //must be instantiated in .cpp file for access to complete types of all member fields
CGObjectInstance::~CGObjectInstance() = default; CGObjectInstance::~CGObjectInstance() = default;
int32_t CGObjectInstance::getObjGroupIndex() const MapObjectID CGObjectInstance::getObjGroupIndex() const
{ {
return ID.num; return ID;
} }
int32_t CGObjectInstance::getObjTypeIndex() const MapObjectSubID CGObjectInstance::getObjTypeIndex() const
{ {
return subID; return subID;
} }
@@ -197,6 +197,11 @@ void CGObjectInstance::setProperty( ui8 what, ui32 val )
} }
} }
TObjectTypeHandler CGObjectInstance::getObjectHandler() const
{
return VLC->objtypeh->getHandlerFor(ID, subID);
}
void CGObjectInstance::setPropertyDer( ui8 what, ui32 val ) void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
{} {}

View File

@@ -21,6 +21,8 @@ struct Component;
class JsonSerializeFormat; class JsonSerializeFormat;
class ObjectTemplate; class ObjectTemplate;
class CMap; class CMap;
class AObjectTypeHandler;
using TObjectTypeHandler = std::shared_ptr<AObjectTypeHandler>;
class DLL_LINKAGE CGObjectInstance : public IObjectInterface class DLL_LINKAGE CGObjectInstance : public IObjectInterface
{ {
@@ -28,9 +30,9 @@ public:
/// Position of bottom-right corner of object on map /// Position of bottom-right corner of object on map
int3 pos; int3 pos;
/// Type of object, e.g. town, hero, creature. /// Type of object, e.g. town, hero, creature.
Obj ID; MapObjectID ID;
/// Subtype of object, depends on type /// Subtype of object, depends on type
si32 subID; MapObjectSubID subID;
/// Current owner of an object (when below PLAYER_LIMIT) /// Current owner of an object (when below PLAYER_LIMIT)
PlayerColor tempOwner; PlayerColor tempOwner;
/// Index of object in map's list of objects /// Index of object in map's list of objects
@@ -45,8 +47,8 @@ public:
CGObjectInstance(); //TODO: remove constructor CGObjectInstance(); //TODO: remove constructor
~CGObjectInstance() override; ~CGObjectInstance() override;
int32_t getObjGroupIndex() const override; MapObjectID getObjGroupIndex() const override;
int32_t getObjTypeIndex() const override; MapObjectSubID getObjTypeIndex() const override;
/// "center" tile from which the sight distance is calculated /// "center" tile from which the sight distance is calculated
int3 getSightCenter() const; int3 getSightCenter() const;
@@ -94,6 +96,8 @@ public:
std::optional<AudioPath> getVisitSound() const; std::optional<AudioPath> getVisitSound() const;
std::optional<AudioPath> getRemovalSound() const; std::optional<AudioPath> getRemovalSound() const;
TObjectTypeHandler getObjectHandler() const;
/** VIRTUAL METHODS **/ /** VIRTUAL METHODS **/
/// Returns true if player can pass through visitable tiles of this object /// Returns true if player can pass through visitable tiles of this object

View File

@@ -24,12 +24,12 @@ PlayerColor CGTownBuilding::getOwner() const
return town->getOwner(); return town->getOwner();
} }
int32_t CGTownBuilding::getObjGroupIndex() const MapObjectID CGTownBuilding::getObjGroupIndex() const
{ {
return -1; return -1;
} }
int32_t CGTownBuilding::getObjTypeIndex() const MapObjectSubID CGTownBuilding::getObjTypeIndex() const
{ {
return 0; return 0;
} }

View File

@@ -45,8 +45,8 @@ public:
} }
PlayerColor getOwner() const override; PlayerColor getOwner() const override;
int32_t getObjGroupIndex() const override; MapObjectID getObjGroupIndex() const override;
int32_t getObjTypeIndex() const override; MapObjectSubID getObjTypeIndex() const override;
int3 visitablePos() const override; int3 visitablePos() const override;
int3 getPosition() const override; int3 getPosition() const override;

View File

@@ -763,7 +763,7 @@ void CGTownInstance::updateAppearance()
{ {
auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId(); auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId();
//FIXME: not the best way to do this //FIXME: not the best way to do this
auto app = VLC->objtypeh->getHandlerFor(ID, subID)->getOverride(terrain, this); auto app = getObjectHandler()->getOverride(terrain, this);
if (app) if (app)
appearance = app; appearance = app;
} }

View File

@@ -28,14 +28,4 @@ CObjectHandler::CObjectHandler()
logGlobal->trace("\t\tDone loading resource prices!"); logGlobal->trace("\t\tDone loading resource prices!");
} }
CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)
{
}
bool CGObjectInstanceBySubIdFinder::operator()(CGObjectInstance * obj) const
{
return this->obj->subID == obj->subID;
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@@ -16,17 +16,6 @@ VCMI_LIB_NAMESPACE_BEGIN
class CGObjectInstance; class CGObjectInstance;
class int3; class int3;
/// function object which can be used to find an object with an specific sub ID
class CGObjectInstanceBySubIdFinder
{
public:
CGObjectInstanceBySubIdFinder(CGObjectInstance * obj);
bool operator()(CGObjectInstance * obj) const;
private:
CGObjectInstance * obj;
};
class DLL_LINKAGE CObjectHandler class DLL_LINKAGE CObjectHandler
{ {
public: public:

View File

@@ -373,7 +373,7 @@ void CRewardableObject::newTurn(CRandomGenerator & rand) const
void CRewardableObject::initObj(CRandomGenerator & rand) void CRewardableObject::initObj(CRandomGenerator & rand)
{ {
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); getObjectHandler()->configureObject(this, rand);
} }
CRewardableObject::CRewardableObject() CRewardableObject::CRewardableObject()

View File

@@ -10,6 +10,7 @@
#pragma once #pragma once
#include "../networkPacks/EInfoWindowMode.h" #include "../networkPacks/EInfoWindowMode.h"
#include "../constants/EntityIdentifiers.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -33,8 +34,8 @@ public:
virtual ~IObjectInterface() = default; virtual ~IObjectInterface() = default;
virtual int32_t getObjGroupIndex() const = 0; virtual MapObjectID getObjGroupIndex() const = 0;
virtual int32_t getObjTypeIndex() const = 0; virtual MapObjectSubID getObjTypeIndex() const = 0;
virtual PlayerColor getOwner() const = 0; virtual PlayerColor getOwner() const = 0;
virtual int3 visitablePos() const = 0; virtual int3 visitablePos() const = 0;

View File

@@ -85,7 +85,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
{ {
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
ynd.text.appendLocalString(EMetaText::ADVOB_TXT, subID == 7 ? 84 : 187); ynd.text.appendLocalString(EMetaText::ADVOB_TXT, isAbandoned() ? 84 : 187);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
return; return;
} }
@@ -119,19 +119,19 @@ void CGMine::initObj(CRandomGenerator & rand)
} }
else else
{ {
producedResource = GameResID(subID); producedResource = GameResID(getObjTypeIndex());
} }
producedQuantity = defaultResProduction(); producedQuantity = defaultResProduction();
} }
bool CGMine::isAbandoned() const bool CGMine::isAbandoned() const
{ {
return (subID >= 7); return (getObjTypeIndex() >= 7);
} }
std::string CGMine::getObjectName() const std::string CGMine::getObjectName() const
{ {
return VLC->generaltexth->translate("core.minename", subID); return VLC->generaltexth->translate("core.minename", getObjTypeIndex());
} }
std::string CGMine::getHoverText(PlayerColor player) const std::string CGMine::getHoverText(PlayerColor player) const
@@ -206,7 +206,7 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
if(handler.saving) if(handler.saving)
{ {
JsonNode node(JsonNode::JsonType::DATA_VECTOR); JsonNode node(JsonNode::JsonType::DATA_VECTOR);
for(auto const & resID : abandonedMineResources) for(const auto & resID : abandonedMineResources)
{ {
JsonNode one(JsonNode::JsonType::DATA_STRING); JsonNode one(JsonNode::JsonType::DATA_STRING);
one.String() = GameConstants::RESOURCE_NAMES[resID]; one.String() = GameConstants::RESOURCE_NAMES[resID];
@@ -237,9 +237,14 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
} }
} }
GameResID CGResource::resourceID() const
{
return getObjTypeIndex().getNum();
}
std::string CGResource::getHoverText(PlayerColor player) const std::string CGResource::getHoverText(PlayerColor player) const
{ {
return VLC->generaltexth->restypes[subID]; return VLC->generaltexth->restypes[resourceID()];
} }
void CGResource::initObj(CRandomGenerator & rand) void CGResource::initObj(CRandomGenerator & rand)
@@ -248,7 +253,7 @@ void CGResource::initObj(CRandomGenerator & rand)
if(amount == CGResource::RANDOM_AMOUNT) if(amount == CGResource::RANDOM_AMOUNT)
{ {
switch(static_cast<EGameResID>(subID)) switch(resourceID())
{ {
case EGameResID::GOLD: case EGameResID::GOLD:
amount = rand.nextInt(5, 10) * 100; amount = rand.nextInt(5, 10) * 100;
@@ -285,7 +290,7 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const
void CGResource::collectRes(const PlayerColor & player) const void CGResource::collectRes(const PlayerColor & player) const
{ {
cb->giveResource(player, static_cast<EGameResID>(subID), amount); cb->giveResource(player, resourceID(), amount);
InfoWindow sii; InfoWindow sii;
sii.player = player; sii.player = player;
if(!message.empty()) if(!message.empty())
@@ -297,9 +302,9 @@ void CGResource::collectRes(const PlayerColor & player) const
{ {
sii.type = EInfoWindowMode::INFO; sii.type = EInfoWindowMode::INFO;
sii.text.appendLocalString(EMetaText::ADVOB_TXT,113); sii.text.appendLocalString(EMetaText::ADVOB_TXT,113);
sii.text.replaceLocalString(EMetaText::RES_NAMES, subID); sii.text.replaceLocalString(EMetaText::RES_NAMES, resourceID());
} }
sii.components.emplace_back(Component::EComponentType::RESOURCE,subID,amount,0); sii.components.emplace_back(Component::EComponentType::RESOURCE, resourceID(), amount, 0);
sii.soundID = soundBase::pickup01 + CRandomGenerator::getDefault().nextInt(6); sii.soundID = soundBase::pickup01 + CRandomGenerator::getDefault().nextInt(6);
cb->showInfoDialog(&sii); cb->showInfoDialog(&sii);
cb->removeObject(this, player); cb->removeObject(this, player);
@@ -688,6 +693,14 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h)
|| (h->stacksCount() == 1 && h->Slots().begin()->second->count == 1); || (h->stacksCount() == 1 && h->Slots().begin()->second->count == 1);
} }
ArtifactID CGArtifact::getArtifact() const
{
if(ID == Obj::SPELL_SCROLL)
return ArtifactID::SPELL_SCROLL;
else
return getObjTypeIndex().getNum();
}
void CGArtifact::initObj(CRandomGenerator & rand) void CGArtifact::initObj(CRandomGenerator & rand)
{ {
blockVisit = true; blockVisit = true;
@@ -700,7 +713,7 @@ void CGArtifact::initObj(CRandomGenerator & rand)
storedArtifact = a; storedArtifact = a;
} }
if(!storedArtifact->artType) if(!storedArtifact->artType)
storedArtifact->setType(VLC->arth->objects[subID]); storedArtifact->setType(VLC->arth->objects[getArtifact()]);
} }
if(ID == Obj::SPELL_SCROLL) if(ID == Obj::SPELL_SCROLL)
subID = 1; subID = 1;
@@ -713,7 +726,7 @@ void CGArtifact::initObj(CRandomGenerator & rand)
std::string CGArtifact::getObjectName() const std::string CGArtifact::getObjectName() const
{ {
return VLC->artifacts()->getByIndex(subID)->getNameTranslated(); return VLC->artifacts()->getByIndex(getArtifact())->getNameTranslated();
} }
void CGArtifact::onHeroVisit(const CGHeroInstance * h) const void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
@@ -730,11 +743,11 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
{ {
case Obj::ARTIFACT: case Obj::ARTIFACT:
{ {
iw.components.emplace_back(Component::EComponentType::ARTIFACT, subID, 0, 0); iw.components.emplace_back(Component::EComponentType::ARTIFACT, getArtifact(), 0, 0);
if(!message.empty()) if(!message.empty())
iw.text = message; iw.text = message;
else else
iw.text.appendLocalString(EMetaText::ART_EVNTS, subID); iw.text.appendLocalString(EMetaText::ART_EVNTS, getArtifact());
} }
break; break;
case Obj::SPELL_SCROLL: case Obj::SPELL_SCROLL:

View File

@@ -93,6 +93,8 @@ public:
void afterAddToMap(CMap * map) override; void afterAddToMap(CMap * map) override;
BattleField getBattlefield() const override; BattleField getBattlefield() const override;
ArtifactID getArtifact() const;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & static_cast<CArmedInstance&>(*this); h & static_cast<CArmedInstance&>(*this);
@@ -118,6 +120,7 @@ public:
std::string getHoverText(PlayerColor player) const override; std::string getHoverText(PlayerColor player) const override;
void collectRes(const PlayerColor & player) const; void collectRes(const PlayerColor & player) const;
GameResID resourceID() const;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {

View File

@@ -250,10 +250,10 @@ void CMap::calculateGuardingGreaturePositions()
} }
} }
CGHeroInstance * CMap::getHero(int heroID) CGHeroInstance * CMap::getHero(HeroTypeID heroID)
{ {
for(auto & elem : heroesOnMap) for(auto & elem : heroesOnMap)
if(elem->subID == heroID) if(elem->getObjTypeIndex() == heroID.getNum())
return elem; return elem;
return nullptr; return nullptr;
} }

View File

@@ -118,7 +118,7 @@ public:
/// Gets object of specified type on requested position /// Gets object of specified type on requested position
const CGObjectInstance * getObjectiveObjectFrom(const int3 & pos, Obj type); const CGObjectInstance * getObjectiveObjectFrom(const int3 & pos, Obj type);
CGHeroInstance * getHero(int heroId); CGHeroInstance * getHero(HeroTypeID heroId);
/// Sets the victory/loss condition objectives ?? /// Sets the victory/loss condition objectives ??
void checkForObjectives(); void checkForObjectives();

View File

@@ -1229,7 +1229,7 @@ void CMapLoaderJson::MapObjectLoader::configure()
else if(art->ID == Obj::ARTIFACT) else if(art->ID == Obj::ARTIFACT)
{ {
//specific artifact //specific artifact
artID = ArtifactID(art->subID); artID = art->getArtifact();
} }
art->storedArtifact = ArtifactUtils::createArtifact(owner->map, artID, spellID.getNum()); art->storedArtifact = ArtifactUtils::createArtifact(owner->map, artID, spellID.getNum());

View File

@@ -113,7 +113,7 @@ void Object::Instance::setPositionRaw(const int3 & position)
void Object::Instance::setAnyTemplate(CRandomGenerator & rng) void Object::Instance::setAnyTemplate(CRandomGenerator & rng)
{ {
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(); auto templates = dObject.getObjectHandler()->getTemplates();
if(templates.empty()) if(templates.empty())
throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID)); throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID));
@@ -124,7 +124,7 @@ void Object::Instance::setAnyTemplate(CRandomGenerator & rng)
void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng) void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng)
{ {
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain); auto templates = dObject.getObjectHandler()->getTemplates(terrain);
if (templates.empty()) if (templates.empty())
{ {
auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated(); auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated();
@@ -335,7 +335,7 @@ void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng)
if (!dObject.appearance) if (!dObject.appearance)
{ {
const auto * terrainType = map.getTile(getPosition(true)).terType; const auto * terrainType = map.getTile(getPosition(true)).terType;
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType->getId()); auto templates = dObject.getObjectHandler()->getTemplates(terrainType->getId());
if (templates.empty()) if (templates.empty())
{ {
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.subID % getPosition(true).toString() % terrainType)); throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.subID % getPosition(true).toString() % terrainType));