1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +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)
{
HeroTypeID heroType(hero->subID);
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());
globalHeroPool[heroType] = node;
logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroType(), hero->getNameTranslated());
globalHeroPool[hero->getHeroType()] = node;
}
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);
}
}

View File

@ -407,7 +407,7 @@ public:
static std::string entityType();
};
class ObjBase : public IdentifierBase
class MapObjectBaseID : public IdentifierBase
{
public:
enum Type
@ -552,15 +552,38 @@ public:
};
};
class DLL_LINKAGE Obj : public IdentifierWithEnum<Obj, ObjBase>
class DLL_LINKAGE MapObjectID : public IdentifierWithEnum<MapObjectID, MapObjectBaseID>
{
public:
using IdentifierWithEnum<Obj, ObjBase>::IdentifierWithEnum;
using IdentifierWithEnum<MapObjectID, MapObjectBaseID>::IdentifierWithEnum;
static std::string encode(int32_t index);
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>
{
public:
@ -966,6 +989,7 @@ public:
// Deprecated
// TODO: remove
using Obj = MapObjectID;
using ETownType = FactionID;
using EGameResID = GameResID;
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;
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();
map->getEditManager()->insertObject(hero);
}
@ -880,8 +880,6 @@ void CGameState::initHeroes()
CGBoat * boat = dynamic_cast<CGBoat*>(handler->create());
handler->configureObject(boat, gs->getRandomGenerator());
boat->ID = Obj::BOAT;
boat->subID = hero->getBoatType().getNum();
boat->pos = hero->pos;
boat->appearance = handler->getTemplates().front();
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();
for(auto & campaignHeroReplacement : campaignHeroReplacements)
heroesToRemove.insert(HeroTypeID(campaignHeroReplacement.hero->subID));
heroesToRemove.insert(campaignHeroReplacement.hero->getHeroType());
for(auto & heroID : heroesToRemove)
{
@ -339,7 +339,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders(const std::vector<CampaignHer
if(heroPlaceholder->tempOwner.isValidPlayer())
heroToPlace->tempOwner = heroPlaceholder->tempOwner;
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();
gameState->map->removeBlockVisTiles(heroPlaceholder, true);
@ -396,7 +396,7 @@ std::vector<CampaignHeroReplacement> CGameStateCampaign::generateCampaignHeroesT
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);
}
@ -422,7 +422,7 @@ std::vector<CampaignHeroReplacement> CGameStateCampaign::generateCampaignHeroesT
CGHeroInstance * hero = CampaignState::crossoverDeserialize(*nodeListIter, gameState->map);
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);
}
@ -468,7 +468,7 @@ void CGameStateCampaign::initHeroes()
{
for (auto & heroe : heroes)
{
if (heroe->subID == chosenBonus->info1)
if (heroe->getHeroType().getNum() == chosenBonus->info1)
{
giveCampaignBonusToHero(heroe);
break;
@ -557,7 +557,7 @@ void CGameStateCampaign::initTowns()
if(gameState->scenarioOps->campState->formatVCMI())
newBuilding = BuildingID(chosenBonus->info1);
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
while(true)

View File

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

View File

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

View File

@ -28,7 +28,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
if(stacks.empty())
{
//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";
}
@ -41,7 +41,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
else
ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex);
ms.appendRawString(" ");
ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID);
ms.appendLocalString(EMetaText::CRE_PL_NAMES, getCreature());
hoverName = ms.toString();
return hoverName;
}
@ -54,7 +54,7 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
MetaString ms;
ms.appendNumber(stacks.begin()->second->count);
ms.appendRawString(" ");
ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID);
ms.appendLocalString(EMetaText::CRE_PL_NAMES, getCreature());
ms.appendRawString("\n\n");
@ -132,7 +132,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false);
ynd.player = h->tempOwner;
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);
break;
}
@ -146,7 +146,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
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(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);
cb->showBlockingDialog(&ynd);
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)
{
blockVisit = true;
@ -177,16 +182,16 @@ void CGCreature::initObj(CRandomGenerator & rand)
break;
}
stacks[SlotID(0)]->setType(CreatureID(subID));
stacks[SlotID(0)]->setType(getCreature());
TQuantity &amount = stacks[SlotID(0)]->count;
CCreature &c = *VLC->creh->objects[subID];
const Creature * c = VLC->creatures()->getById(getCreature());
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
{
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;
}
}
@ -252,7 +257,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
powerFactor = -3;
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->upgrades.begin(), myCreature->upgrades.end()); //our upgrades
@ -290,7 +295,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
return JOIN_FOR_FREE;
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
@ -404,7 +409,7 @@ void CGCreature::flee( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false);
ynd.player = h->tempOwner;
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);
}

View File

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

View File

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

View File

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

View File

@ -25,7 +25,7 @@ VCMI_LIB_NAMESPACE_BEGIN
void CGMarket::initObj(CRandomGenerator & rand)
{
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);
getObjectHandler()->configureObject(this, rand);
}
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
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;
}
@ -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 )
{}

View File

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

View File

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

View File

@ -763,7 +763,7 @@ void CGTownInstance::updateAppearance()
{
auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId();
//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)
appearance = app;
}

View File

@ -28,14 +28,4 @@ CObjectHandler::CObjectHandler()
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

View File

@ -16,17 +16,6 @@ VCMI_LIB_NAMESPACE_BEGIN
class CGObjectInstance;
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
{
public:

View File

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

View File

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

View File

@ -85,7 +85,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
{
BlockingDialog ynd(true,false);
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);
return;
}
@ -119,19 +119,19 @@ void CGMine::initObj(CRandomGenerator & rand)
}
else
{
producedResource = GameResID(subID);
producedResource = GameResID(getObjTypeIndex());
}
producedQuantity = defaultResProduction();
}
bool CGMine::isAbandoned() const
{
return (subID >= 7);
return (getObjTypeIndex() >= 7);
}
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
@ -206,7 +206,7 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
if(handler.saving)
{
JsonNode node(JsonNode::JsonType::DATA_VECTOR);
for(auto const & resID : abandonedMineResources)
for(const auto & resID : abandonedMineResources)
{
JsonNode one(JsonNode::JsonType::DATA_STRING);
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
{
return VLC->generaltexth->restypes[subID];
return VLC->generaltexth->restypes[resourceID()];
}
void CGResource::initObj(CRandomGenerator & rand)
@ -248,7 +253,7 @@ void CGResource::initObj(CRandomGenerator & rand)
if(amount == CGResource::RANDOM_AMOUNT)
{
switch(static_cast<EGameResID>(subID))
switch(resourceID())
{
case EGameResID::GOLD:
amount = rand.nextInt(5, 10) * 100;
@ -285,7 +290,7 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const
void CGResource::collectRes(const PlayerColor & player) const
{
cb->giveResource(player, static_cast<EGameResID>(subID), amount);
cb->giveResource(player, resourceID(), amount);
InfoWindow sii;
sii.player = player;
if(!message.empty())
@ -297,9 +302,9 @@ void CGResource::collectRes(const PlayerColor & player) const
{
sii.type = EInfoWindowMode::INFO;
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);
cb->showInfoDialog(&sii);
cb->removeObject(this, player);
@ -688,6 +693,14 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h)
|| (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)
{
blockVisit = true;
@ -700,7 +713,7 @@ void CGArtifact::initObj(CRandomGenerator & rand)
storedArtifact = a;
}
if(!storedArtifact->artType)
storedArtifact->setType(VLC->arth->objects[subID]);
storedArtifact->setType(VLC->arth->objects[getArtifact()]);
}
if(ID == Obj::SPELL_SCROLL)
subID = 1;
@ -713,7 +726,7 @@ void CGArtifact::initObj(CRandomGenerator & rand)
std::string CGArtifact::getObjectName() const
{
return VLC->artifacts()->getByIndex(subID)->getNameTranslated();
return VLC->artifacts()->getByIndex(getArtifact())->getNameTranslated();
}
void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
@ -730,11 +743,11 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
{
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())
iw.text = message;
else
iw.text.appendLocalString(EMetaText::ART_EVNTS, subID);
iw.text.appendLocalString(EMetaText::ART_EVNTS, getArtifact());
}
break;
case Obj::SPELL_SCROLL:

View File

@ -93,6 +93,8 @@ public:
void afterAddToMap(CMap * map) override;
BattleField getBattlefield() const override;
ArtifactID getArtifact() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArmedInstance&>(*this);
@ -118,6 +120,7 @@ public:
std::string getHoverText(PlayerColor player) const override;
void collectRes(const PlayerColor & player) const;
GameResID resourceID() const;
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)
if(elem->subID == heroID)
if(elem->getObjTypeIndex() == heroID.getNum())
return elem;
return nullptr;
}

View File

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

View File

@ -1229,7 +1229,7 @@ void CMapLoaderJson::MapObjectLoader::configure()
else if(art->ID == Obj::ARTIFACT)
{
//specific artifact
artID = ArtifactID(art->subID);
artID = art->getArtifact();
}
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)
{
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates();
auto templates = dObject.getObjectHandler()->getTemplates();
if(templates.empty())
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)
{
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain);
auto templates = dObject.getObjectHandler()->getTemplates(terrain);
if (templates.empty())
{
auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated();
@ -335,7 +335,7 @@ void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng)
if (!dObject.appearance)
{
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())
{
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));