2
0
Эх сурвалжийг харах

Remove most of non-const access to VLC entities

Ivan Savenko 1 жил өмнө
parent
commit
d5c4478816
55 өөрчлөгдсөн 237 нэмэгдсэн , 306 устгасан
  1. 5 4
      AI/BattleAI/BattleEvaluator.cpp
  2. 1 3
      AI/Nullkiller/AIUtility.cpp
  3. 0 1
      AI/Nullkiller/AIUtility.h
  4. 8 8
      AI/Nullkiller/Analyzers/ArmyManager.cpp
  5. 2 2
      AI/Nullkiller/Goals/BuyArmy.cpp
  6. 2 2
      AI/Nullkiller/Pathfinding/Actors.cpp
  7. 0 3
      client/CGameInfo.cpp
  8. 15 14
      client/CGameInfo.h
  9. 2 2
      client/Client.cpp
  10. 3 3
      lib/ArtifactUtils.cpp
  11. 1 1
      lib/ArtifactUtils.h
  12. 3 3
      lib/CArtHandler.cpp
  13. 4 4
      lib/CArtHandler.h
  14. 3 3
      lib/CArtifactInstance.cpp
  15. 3 3
      lib/CArtifactInstance.h
  16. 1 12
      lib/CCreatureHandler.cpp
  17. 1 1
      lib/CCreatureHandler.h
  18. 3 4
      lib/CCreatureSet.cpp
  19. 1 1
      lib/CGameInfoCallback.cpp
  20. 13 6
      lib/CHeroHandler.cpp
  21. 4 4
      lib/CHeroHandler.h
  22. 1 1
      lib/CTownHandler.cpp
  23. 27 15
      lib/IHandlerBase.h
  24. 2 1
      lib/JsonRandom.cpp
  25. 1 1
      lib/RiverHandler.cpp
  26. 1 1
      lib/RoadHandler.cpp
  27. 20 92
      lib/VCMI_Lib.cpp
  28. 24 29
      lib/VCMI_Lib.h
  29. 10 0
      lib/constants/EntityIdentifiers.cpp
  30. 5 0
      lib/constants/EntityIdentifiers.h
  31. 1 1
      lib/gameState/CGameStateCampaign.cpp
  32. 1 1
      lib/mapObjectConstructors/CommonConstructors.cpp
  33. 2 2
      lib/mapObjectConstructors/CommonConstructors.h
  34. 1 1
      lib/mapObjectConstructors/DwellingInstanceConstructor.cpp
  35. 2 2
      lib/mapObjects/CGCreature.cpp
  36. 7 7
      lib/mapObjects/CGHeroInstance.cpp
  37. 1 1
      lib/mapObjects/CGHeroInstance.h
  38. 1 1
      lib/mapObjects/MiscObjects.cpp
  39. 1 1
      lib/mapping/CMapOperation.cpp
  40. 1 1
      lib/mapping/MapFormatH3M.cpp
  41. 14 14
      lib/modding/ContentTypeHandler.cpp
  42. 1 1
      lib/networkPacks/PacksForClient.h
  43. 1 1
      lib/networkPacks/PacksForClientBattle.h
  44. 10 10
      lib/rmg/modificators/TreasurePlacer.cpp
  45. 0 6
      lib/serializer/CSerializer.cpp
  46. 0 5
      lib/serializer/CSerializer.h
  47. 2 2
      lib/spells/CSpellHandler.cpp
  48. 1 1
      mapeditor/graphics.cpp
  49. 1 1
      mapeditor/inspector/inspector.cpp
  50. 1 1
      mapeditor/mapcontroller.cpp
  51. 1 1
      mapeditor/playerparams.cpp
  52. 1 1
      mapeditor/validator.cpp
  53. 11 11
      server/CGameHandler.cpp
  54. 3 3
      server/processors/HeroPoolProcessor.cpp
  55. 6 6
      server/processors/PlayerMessageProcessor.cpp

+ 5 - 4
AI/BattleAI/BattleEvaluator.cpp

@@ -350,10 +350,11 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
 	LOGL("Casting spells sounds like fun. Let's see...");
 	//Get all spells we can cast
 	std::vector<const CSpell*> possibleSpells;
-	vstd::copy_if(VLC->spellh->objects, std::back_inserter(possibleSpells), [hero, this](const CSpell *s) -> bool
-	{
-		return s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero);
-	});
+
+	for (auto const & s : VLC->spellh->objects)
+		if (s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero))
+			possibleSpells.push_back(s.get());
+
 	LOGFL("I can cast %d spells.", possibleSpells.size());
 
 	vstd::erase_if(possibleSpells, [](const CSpell *s)

+ 1 - 3
AI/Nullkiller/AIUtility.cpp

@@ -276,12 +276,10 @@ creInfo infoFromDC(const dwellingContent & dc)
 	ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed
 	if (ci.creID != CreatureID::NONE)
 	{
-		ci.cre = VLC->creatures()->getById(ci.creID);
-		ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
+		ci.level = ci.creID.toCreature()->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
 	}
 	else
 	{
-		ci.cre = nullptr;
 		ci.level = 0;
 	}
 	return ci;

+ 0 - 1
AI/Nullkiller/AIUtility.h

@@ -163,7 +163,6 @@ struct creInfo
 {
 	int count;
 	CreatureID creID;
-	const Creature * cre;
 	int level;
 };
 creInfo infoFromDC(const dwellingContent & dc);

+ 8 - 8
AI/Nullkiller/Analyzers/ArmyManager.cpp

@@ -63,9 +63,9 @@ std::vector<SlotInfo> ArmyManager::toSlotInfo(std::vector<creInfo> army) const
 	{
 		SlotInfo slot;
 
-		slot.creature = VLC->creh->objects[i.cre->getId()];
+		slot.creature = i.creID.toCreature();
 		slot.count = i.count;
-		slot.power = evaluateStackPower(i.cre, i.count);
+		slot.power = evaluateStackPower(i.creID.toCreature(), i.count);
 
 		result.push_back(slot);
 	}
@@ -259,7 +259,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
 		if(!ci.count || ci.creID == CreatureID::NONE)
 			continue;
 
-		vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
+		vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford
 
 		if(!ci.count)
 			continue;
@@ -270,7 +270,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
 			break;
 
 		army->setCreature(dst, ci.creID, ci.count);
-		availableRes -= ci.cre->getFullRecruitCost() * ci.count;
+		availableRes -= ci.creID.toCreature()->getFullRecruitCost() * ci.count;
 	}
 
 	return army;
@@ -287,7 +287,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(
 
 	for(const creInfo & ci : army)
 	{
-		aivalue += ci.count * ci.cre->getAIValue();
+		aivalue += ci.count * ci.creID.toCreature()->getAIValue();
 	}
 
 	return aivalue;
@@ -320,7 +320,7 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
 
 		if(i < GameConstants::CREATURES_PER_TOWN && countGrowth)
 		{
-			ci.count += town ? town->creatureGrowth(i) : ci.cre->getGrowth();
+			ci.count += town ? town->creatureGrowth(i) : ci.creID.toCreature()->getGrowth();
 		}
 
 		if(!ci.count) continue;
@@ -334,13 +334,13 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
 				freeHeroSlots--; //new slot will be occupied
 		}
 
-		vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
+		vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford
 
 		if(!ci.count) continue;
 
 		ci.level = i; //this is important for Dungeon Summoning Portal
 		creaturesInDwellings.push_back(ci);
-		availableRes -= ci.cre->getFullRecruitCost() * ci.count;
+		availableRes -= ci.creID.toCreature()->getFullRecruitCost() * ci.count;
 	}
 
 	return creaturesInDwellings;

+ 2 - 2
AI/Nullkiller/Goals/BuyArmy.cpp

@@ -54,12 +54,12 @@ void BuyArmy::accept(AIGateway * ai)
 		if(objid != CreatureID::NONE && ci.creID.getNum() != objid)
 			continue;
 
-		vstd::amin(ci.count, res / ci.cre->getFullRecruitCost());
+		vstd::amin(ci.count, res / ci.creID.toCreature()->getFullRecruitCost());
 
 		if(ci.count)
 		{
 			cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
-			valueBought += ci.count * ci.cre->getAIValue();
+			valueBought += ci.count * ci.creID.toCreature()->getAIValue();
 		}
 	}
 

+ 2 - 2
AI/Nullkiller/Pathfinding/Actors.cpp

@@ -373,10 +373,10 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
 
 		for(auto & creatureToBuy : buyArmy)
 		{
-			auto targetSlot = target->getSlotFor(dynamic_cast<const CCreature*>(creatureToBuy.cre));
+			auto targetSlot = target->getSlotFor(dynamic_cast<const CCreature*>(creatureToBuy.creID.toCreature()));
 
 			target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
-			target->armyCost += creatureToBuy.cre->getFullRecruitCost() * creatureToBuy.count;
+			target->armyCost += creatureToBuy.creID.toCreature()->getFullRecruitCost() * creatureToBuy.count;
 			target->requireBuyArmy = true;
 		}
 	}

+ 0 - 3
client/CGameInfo.cpp

@@ -19,9 +19,6 @@ CServerHandler * CSH;
 
 CGameInfo::CGameInfo()
 {
-	generaltexth = nullptr;
-	mh = nullptr;
-	townh = nullptr;
 	globalServices = nullptr;
 }
 

+ 15 - 14
client/CGameInfo.h

@@ -56,7 +56,7 @@ extern CClientState * CCS;
 
 /// CGameInfo class
 /// for allowing different functions for accessing game informations
-class CGameInfo : public Services
+class CGameInfo final : public Services
 {
 public:
 	const ArtifactService * artifacts() const override;
@@ -78,19 +78,20 @@ public:
 	const spells::effects::Registry * spellEffects() const override;
 	spells::effects::Registry * spellEffects() override;
 
-	ConstTransitivePtr<CModHandler> modh; //public?
-	ConstTransitivePtr<BattleFieldHandler> battleFieldHandler;
-	ConstTransitivePtr<CHeroHandler> heroh;
-	ConstTransitivePtr<CCreatureHandler> creh;
-	ConstTransitivePtr<CSpellHandler> spellh;
-	ConstTransitivePtr<CSkillHandler> skillh;
-	ConstTransitivePtr<CObjectHandler> objh;
-	ConstTransitivePtr<TerrainTypeHandler> terrainTypeHandler;
-	ConstTransitivePtr<CObjectClassesHandler> objtypeh;
-	ConstTransitivePtr<ObstacleHandler> obstacleHandler;
-	CGeneralTextHandler * generaltexth;
-	CMapHandler * mh;
-	CTownHandler * townh;
+	std::shared_ptr<const CModHandler> modh;
+	std::shared_ptr<const BattleFieldHandler> battleFieldHandler;
+	std::shared_ptr<const CHeroHandler> heroh;
+	std::shared_ptr<const CCreatureHandler> creh;
+	std::shared_ptr<const CSpellHandler> spellh;
+	std::shared_ptr<const CSkillHandler> skillh;
+	std::shared_ptr<const CObjectHandler> objh;
+	std::shared_ptr<const TerrainTypeHandler> terrainTypeHandler;
+	std::shared_ptr<const CObjectClassesHandler> objtypeh;
+	std::shared_ptr<const ObstacleHandler> obstacleHandler;
+	std::shared_ptr<const CGeneralTextHandler> generaltexth;
+	std::shared_ptr<const CTownHandler> townh;
+
+	std::shared_ptr<CMapHandler> mh;
 
 	void setFromLib();
 

+ 2 - 2
client/Client.cpp

@@ -370,7 +370,7 @@ void CClient::endGame()
 		logNetwork->info("Ending current game!");
 		removeGUI();
 
-		vstd::clear_pointer(const_cast<CGameInfo *>(CGI)->mh);
+		const_cast<CGameInfo *>(CGI)->mh.reset();
 		vstd::clear_pointer(gs);
 
 		logNetwork->info("Deleted mapHandler and gameState.");
@@ -392,7 +392,7 @@ void CClient::initMapHandler()
 	// During loading CPlayerInterface from serialized state it's depend on MH
 	if(!settings["session"]["headless"].Bool())
 	{
-		const_cast<CGameInfo *>(CGI)->mh = new CMapHandler(gs->map);
+		const_cast<CGameInfo *>(CGI)->mh = std::make_shared<CMapHandler>(gs->map);
 		logNetwork->trace("Creating mapHandler: %d ms", CSH->th->getDiff());
 	}
 

+ 3 - 3
lib/ArtifactUtils.cpp

@@ -187,14 +187,14 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
 
 DLL_LINKAGE CArtifactInstance * ArtifactUtils::createScroll(const SpellID & sid)
 {
-	auto ret = new CArtifactInstance(VLC->arth->objects[ArtifactID::SPELL_SCROLL]);
+	auto ret = new CArtifactInstance(ArtifactID(ArtifactID::SPELL_SCROLL).toArtifact());
 	auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELL,
 		BonusSource::ARTIFACT_INSTANCE, -1, BonusSourceID(ArtifactID(ArtifactID::SPELL_SCROLL)), BonusSubtypeID(sid));
 	ret->addNewBonus(bonus);
 	return ret;
 }
 
-DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifact * art)
+DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const CArtifact * art)
 {
 	assert(art);
 
@@ -216,7 +216,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa
 
 DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const ArtifactID & aid)
 {
-	return ArtifactUtils::createNewArtifactInstance((*VLC->arth)[aid]);
+	return ArtifactUtils::createNewArtifactInstance(aid.toArtifact());
 }
 
 DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID)

+ 1 - 1
lib/ArtifactUtils.h

@@ -40,7 +40,7 @@ namespace ArtifactUtils
 	DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1);
 	DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid);
 	DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid);
-	DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(CArtifact * art);
+	DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art);
 	DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid);
 	DLL_LINKAGE CArtifactInstance * createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID = SpellID::NONE);
 	DLL_LINKAGE void insertScrrollSpellName(std::string & description, const SpellID & sid);

+ 3 - 3
lib/CArtHandler.cpp

@@ -49,12 +49,12 @@ bool CCombinedArtifact::isCombined() const
 	return !(constituents.empty());
 }
 
-const std::vector<CArtifact*> & CCombinedArtifact::getConstituents() const
+const std::vector<const CArtifact*> & CCombinedArtifact::getConstituents() const
 {
 	return constituents;
 }
 
-const std::vector<CArtifact*> & CCombinedArtifact::getPartOf() const
+const std::vector<const CArtifact*> & CCombinedArtifact::getPartOf() const
 {
 	return partOf;
 }
@@ -597,7 +597,7 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
 			{
 				// when this code is called both combinational art as well as component are loaded
 				// so it is safe to access any of them
-				art->constituents.push_back(objects[id]);
+				art->constituents.push_back(ArtifactID(id).toArtifact());
 				objects[id]->partOf.push_back(art);
 			});
 		}

+ 4 - 4
lib/CArtHandler.h

@@ -47,12 +47,12 @@ class DLL_LINKAGE CCombinedArtifact
 protected:
 	CCombinedArtifact() = default;
 
-	std::vector<CArtifact*> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
-	std::vector<CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art
+	std::vector<const CArtifact*> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
+	std::vector<const CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art
 public:
 	bool isCombined() const;
-	const std::vector<CArtifact*> & getConstituents() const;
-	const std::vector<CArtifact*> & getPartOf() const;
+	const std::vector<const CArtifact*> & getConstituents() const;
+	const std::vector<const CArtifact*> & getPartOf() const;
 };
 
 class DLL_LINKAGE CScrollArtifact

+ 3 - 3
lib/CArtifactInstance.cpp

@@ -107,7 +107,7 @@ void CArtifactInstance::init()
 	setNodeType(ARTIFACT_INSTANCE);
 }
 
-CArtifactInstance::CArtifactInstance(CArtifact * art)
+CArtifactInstance::CArtifactInstance(const CArtifact * art)
 {
 	init();
 	setType(art);
@@ -118,10 +118,10 @@ CArtifactInstance::CArtifactInstance()
 	init();
 }
 
-void CArtifactInstance::setType(CArtifact * art)
+void CArtifactInstance::setType(const CArtifact * art)
 {
 	artType = art;
-	attachTo(*art);
+	attachTo(const_cast<CArtifact&>(*art));
 }
 
 std::string CArtifactInstance::nodeName() const

+ 3 - 3
lib/CArtifactInstance.h

@@ -73,11 +73,11 @@ protected:
 
 	ArtifactInstanceID id;
 public:
-	ConstTransitivePtr<CArtifact> artType;
+	const CArtifact * artType;
 
-	CArtifactInstance(CArtifact * art);
+	CArtifactInstance(const CArtifact * art);
 	CArtifactInstance();
-	void setType(CArtifact * art);
+	void setType(const CArtifact * art);
 	std::string nodeName() const override;
 	std::string getDescription() const;
 	ArtifactID getTypeId() const;

+ 1 - 12
lib/CCreatureHandler.cpp

@@ -407,20 +407,9 @@ void CCreature::serializeJson(JsonSerializeFormat & handler)
 CCreatureHandler::CCreatureHandler()
 	: expAfterUpgrade(0)
 {
-	VLC->creh = this;
 	loadCommanders();
 }
 
-const CCreature * CCreatureHandler::getCreature(const std::string & scope, const std::string & identifier) const
-{
-	std::optional<si32> index = VLC->identifiers()->getIdentifier(scope, "creature", identifier);
-
-	if(!index)
-		throw std::runtime_error("Creature not found "+identifier);
-
-	return objects[*index];
-}
-
 void CCreatureHandler::loadCommanders()
 {
 	auto configResource = JsonPath::builtin("config/commanders.json");
@@ -797,7 +786,7 @@ void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects)
 			bl.clear();
 			loadStackExp(b, bl, parser);
 			for(const auto & b : bl)
-				(*this)[sid]->addNewBonus(b); //add directly to CCreature Node
+				objects[sid.getNum()]->addNewBonus(b); //add directly to CCreature Node
 		}
 		while (parser.endLine());
 

+ 1 - 1
lib/CCreatureHandler.h

@@ -222,7 +222,7 @@ public:
 	std::vector< std::vector <ui8> > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE
 	std::vector <std::pair <std::shared_ptr<Bonus>, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
 
-	const CCreature * getCreature(const std::string & scope, const std::string & identifier) const;
+	//const CCreature * getCreature(const std::string & scope, const std::string & identifier) const;
 
 	CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
 

+ 3 - 4
lib/CCreatureSet.cpp

@@ -739,11 +739,10 @@ void CStackInstance::giveStackExp(TExpType exp)
 	if (!vstd::iswithin(level, 1, 7))
 		level = 0;
 
-	CCreatureHandler * creh = VLC->creh;
-	ui32 maxExp = creh->expRanks[level].back();
+	ui32 maxExp = VLC->creh->expRanks[level].back();
 
 	vstd::amin(exp, static_cast<TExpType>(maxExp)); //prevent exp overflow due to different types
-	vstd::amin(exp, (maxExp * creh->maxExpPerBattle[level])/100);
+	vstd::amin(exp, (maxExp * VLC->creh->maxExpPerBattle[level])/100);
 	vstd::amin(experience += exp, maxExp); //can't get more exp than this limit
 }
 
@@ -1055,7 +1054,7 @@ void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
 		std::string typeName;
 		handler.serializeString("type", typeName);
 		if(!typeName.empty())
-			setType(VLC->creh->getCreature(ModScope::scopeMap(), typeName));
+			setType(CreatureID(CreatureID::decode(typeName)).toCreature());
 	}
 }
 

+ 1 - 1
lib/CGameInfoCallback.cpp

@@ -382,7 +382,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 				if(creature->getFaction() == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
 				{
 					maxAIValue = creature->getAIValue();
-					mostStrong = creature;
+					mostStrong = creature.get();
 				}
 			}
 

+ 13 - 6
lib/CHeroHandler.cpp

@@ -155,6 +155,13 @@ bool CHeroClass::isMagicHero() const
 	return affinity == MAGIC;
 }
 
+int CHeroClass::tavernProbability(FactionID faction) const
+{
+	if (selectionProbability.count(faction))
+		return selectionProbability.at(faction);
+	return 0;
+}
+
 EAlignment CHeroClass::getAlignment() const
 {
 	return VLC->factions()->getById(faction)->getAlignment();
@@ -292,7 +299,7 @@ CHeroClass * CHeroClassHandler::loadFromJson(const std::string & scope, const Js
 	VLC->identifiers()->requestIdentifier ("creature", node["commander"],
 	[=](si32 commanderID)
 	{
-		heroClass->commander = VLC->creh->objects[commanderID];
+		heroClass->commander = CreatureID(commanderID).toCreature();
 	});
 
 	heroClass->defaultTavernChance = static_cast<ui32>(node["defaultTavern"].Float());
@@ -369,9 +376,9 @@ std::vector<JsonNode> CHeroClassHandler::loadLegacyData()
 void CHeroClassHandler::afterLoadFinalization()
 {
 	// for each pair <class, town> set selection probability if it was not set before in tavern entries
-	for(CHeroClass * heroClass : objects)
+	for(auto & heroClass : objects)
 	{
-		for(CFaction * faction : VLC->townh->objects)
+		for(auto & faction : VLC->townh->objects)
 		{
 			if (!faction->town)
 				continue;
@@ -394,7 +401,7 @@ void CHeroClassHandler::afterLoadFinalization()
 		}
 	}
 
-	for(CHeroClass * hc : objects)
+	for(auto const & hc : objects)
 	{
 		if (!hc->imageMapMale.empty())
 		{
@@ -454,7 +461,7 @@ CHero * CHeroHandler::loadFromJson(const std::string & scope, const JsonNode & n
 	VLC->identifiers()->requestIdentifier("heroClass", node["class"],
 	[=](si32 classID)
 	{
-		hero->heroClass = classes[HeroClassID(classID)];
+		hero->heroClass = HeroClassID(classID).toHeroClass();
 	});
 
 	return hero;
@@ -790,7 +797,7 @@ std::set<HeroTypeID> CHeroHandler::getDefaultAllowed() const
 {
 	std::set<HeroTypeID> result;
 
-	for(const CHero * hero : objects)
+	for(auto & hero : objects)
 		if (hero && !hero->special)
 			result.insert(hero->getId());
 

+ 4 - 4
lib/CHeroHandler.h

@@ -57,7 +57,7 @@ public:
 
 	std::vector<InitialArmyStack> initialArmy;
 
-	CHeroClass * heroClass{};
+	const CHeroClass * heroClass = nullptr;
 	std::vector<std::pair<SecondarySkill, ui8> > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert)
 	BonusList specialty;
 	std::set<SpellID> spells;
@@ -121,7 +121,7 @@ public:
 	// resulting chance = sqrt(town.chance * heroClass.chance)
 	ui32 defaultTavernChance;
 
-	CCreature * commander;
+	const CCreature * commander;
 
 	std::vector<int> primarySkillInitial;  // initial primary skills
 	std::vector<int> primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level
@@ -154,6 +154,8 @@ public:
 	void serializeJson(JsonSerializeFormat & handler);
 
 	EAlignment getAlignment() const;
+
+	int tavernProbability(FactionID faction) const;
 };
 
 class DLL_LINKAGE CHeroClassHandler : public CHandlerBase<HeroClassID, HeroClass, CHeroClass, HeroClassService>
@@ -189,8 +191,6 @@ class DLL_LINKAGE CHeroHandler : public CHandlerBase<HeroTypeID, HeroType, CHero
 	std::vector<std::function<void()>> callAfterLoadFinalization;
 
 public:
-	CHeroClassHandler classes;
-
 	ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount
 	TExpType reqExp(ui32 level) const; //calculates experience required for given level
 	ui32 maxSupportedLevel() const;

+ 1 - 1
lib/CTownHandler.cpp

@@ -991,7 +991,7 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
 
 		VLC->identifiers()->requestIdentifier(node.second.meta, "heroClass",node.first, [=](si32 classID)
 		{
-			VLC->heroh->classes[HeroClassID(classID)]->selectionProbability[town->faction->getId()] = chance;
+			VLC->heroclassesh->objects[classID]->selectionProbability[town->faction->getId()] = chance;
 		});
 	}
 

+ 27 - 15
lib/IHandlerBase.h

@@ -44,11 +44,21 @@ public:
 	/// allows handler to do post-loading step for validation or integration of loaded data
 	virtual void afterLoadFinalization(){};
 
-	virtual ~IHandlerBase(){}
+	virtual ~IHandlerBase() = default;
 };
 
 template <class _ObjectID, class _ObjectBase, class _Object, class _ServiceBase> class CHandlerBase : public _ServiceBase, public IHandlerBase
 {
+	const _Object * getObjectImpl(const int32_t index) const
+	{
+		if(index < 0 || index >= objects.size())
+		{
+			logMod->error("%s id %d is invalid", getTypeNames()[0], index);
+			throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front());
+		}
+		return objects[index].get();
+	}
+
 public:
 	virtual ~CHandlerBase()
 	{
@@ -56,22 +66,31 @@ public:
 		{
 			o.dellNull();
 		}
+	}
 
+	_Object * getObjectWriteable(const int32_t index)
+	{
+		if(index < 0 || index >= objects.size())
+		{
+			logMod->error("%s id %d is invalid", getTypeNames()[0], index);
+			throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front());
+		}
+		return objects[index].get();
 	}
 
 	const Entity * getBaseByIndex(const int32_t index) const override
 	{
-		return getByIndex(index);
+		return getObjectImpl(index);
 	}
 
 	const _ObjectBase * getById(const _ObjectID & id) const override
 	{
-		return (*this)[id].get();
+		return getObjectImpl(id.getNum());
 	}
 
 	const _ObjectBase * getByIndex(const int32_t index) const override
 	{
-		return (*this)[_ObjectID(index)].get();
+		return getObjectImpl(index);
 	}
 
 	void forEachBase(const std::function<void(const Entity * entity, bool & stop)> & cb) const override
@@ -105,21 +124,14 @@ public:
 			registerObject(scope, type_name, name, object->getIndex());
 	}
 
-	ConstTransitivePtr<_Object> operator[] (const _ObjectID id) const
+	const _Object * operator[] (const _ObjectID id) const
 	{
-		const int32_t raw_id = id.getNum();
-		return operator[](raw_id);
+		return getObjectImpl(id.getNum());
 	}
 
-	ConstTransitivePtr<_Object> operator[] (int32_t index) const
+	const _Object * operator[] (int32_t index) const
 	{
-		if(index < 0 || index >= objects.size())
-		{
-			logMod->error("%s id %d is invalid", getTypeNames()[0], index);
-			throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front());
-		}
-
-		return objects[index];
+		return getObjectImpl(index);
 	}
 
 	void updateEntity(int32_t index, const JsonNode & data)

+ 2 - 1
lib/JsonRandom.cpp

@@ -519,7 +519,8 @@ namespace JsonRandom
 				info.minAmount = static_cast<si32>(node["min"].Float());
 				info.maxAmount = static_cast<si32>(node["max"].Float());
 			}
-			const CCreature * crea = VLC->creh->objects[VLC->identifiers()->getIdentifier("creature", node["type"]).value()];
+			CreatureID creatureID(VLC->identifiers()->getIdentifier("creature", node["type"]).value());
+			const CCreature * crea = creatureID.toCreature();
 			info.allowedCreatures.push_back(crea);
 			if (node["upgradeChance"].Float() > 0)
 			{

+ 1 - 1
lib/RiverHandler.cpp

@@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 RiverTypeHandler::RiverTypeHandler()
 {
-	objects.push_back(new RiverType);
+	objects.push_back(new RiverType());
 
 	VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), "");
 }

+ 1 - 1
lib/RoadHandler.cpp

@@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 RoadTypeHandler::RoadTypeHandler()
 {
-	objects.push_back(new RoadType);
+	objects.push_back(new RoadType());
 
 	VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), "");
 }

+ 20 - 92
lib/VCMI_Lib.cpp

@@ -65,27 +65,27 @@ DLL_LINKAGE void loadDLLClasses(bool onlyEssential)
 
 const ArtifactService * LibClasses::artifacts() const
 {
-	return arth;
+	return arth.get();
 }
 
 const CreatureService * LibClasses::creatures() const
 {
-	return creh;
+	return creh.get();
 }
 
 const FactionService * LibClasses::factions() const
 {
-	return townh;
+	return townh.get();
 }
 
 const HeroClassService * LibClasses::heroClasses() const
 {
-	return &heroh->classes;
+	return heroclassesh.get();
 }
 
 const HeroTypeService * LibClasses::heroTypes() const
 {
-	return heroh;
+	return heroh.get();
 }
 
 #if SCRIPTING_ENABLED
@@ -97,22 +97,22 @@ const scripting::Service * LibClasses::scripts() const
 
 const spells::Service * LibClasses::spells() const
 {
-	return spellh;
+	return spellh.get();
 }
 
 const SkillService * LibClasses::skills() const
 {
-	return skillh;
+	return skillh.get();
 }
 
 const IBonusTypeHandler * LibClasses::getBth() const
 {
-	return bth;
+	return bth.get();
 }
 
 const CIdentifierStorage * LibClasses::identifiers() const
 {
-	return identifiersHandler;
+	return identifiersHandler.get();
 }
 
 const spells::effects::Registry * LibClasses::spellEffects() const
@@ -127,17 +127,17 @@ spells::effects::Registry * LibClasses::spellEffects()
 
 const BattleFieldService * LibClasses::battlefields() const
 {
-	return battlefieldsHandler;
+	return battlefieldsHandler.get();
 }
 
 const ObstacleService * LibClasses::obstacles() const
 {
-	return obstacleHandler;
+	return obstacleHandler.get();
 }
 
 const IGameSettings * LibClasses::settings() const
 {
-	return settingsHandler;
+	return settingsHandler.get();
 }
 
 void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode & data)
@@ -154,7 +154,7 @@ void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode &
 		townh->updateEntity(index, data);
 		break;
 	case Metatype::HERO_CLASS:
-		heroh->classes.updateEntity(index, data);
+		heroclassesh->updateEntity(index, data);
 		break;
 	case Metatype::HERO_TYPE:
 		heroh->updateEntity(index, data);
@@ -185,8 +185,8 @@ void LibClasses::loadFilesystem(bool extractArchives)
 void LibClasses::loadModFilesystem()
 {
 	CStopWatch loadTime;
-	modh = new CModHandler();
-	identifiersHandler = new CIdentifierStorage();
+	modh = std::make_unique<CModHandler>();
+	identifiersHandler = std::make_unique<CIdentifierStorage>();
 	modh->loadMods();
 	logGlobal->info("\tMod handler: %d ms", loadTime.getDiff());
 
@@ -199,9 +199,9 @@ static void logHandlerLoaded(const std::string & name, CStopWatch & timer)
 	logGlobal->info("\t\t %s handler: %d ms", name, timer.getDiff());
 }
 
-template <class Handler> void createHandler(Handler *&handler, const std::string &name, CStopWatch &timer)
+template <class Handler> void createHandler(std::shared_ptr<Handler> & handler, const std::string &name, CStopWatch &timer)
 {
-	handler = new Handler();
+	handler = std::make_shared<Handler>();
 	logHandlerLoaded(name, timer);
 }
 
@@ -219,6 +219,7 @@ void LibClasses::init(bool onlyEssential)
 	createHandler(riverTypeHandler, "River", pomtime);
 	createHandler(terrainTypeHandler, "Terrain", pomtime);
 	createHandler(heroh, "Hero", pomtime);
+	createHandler(heroclassesh, "Hero classes", pomtime);
 	createHandler(arth, "Artifact", pomtime);
 	createHandler(creh, "Creature", pomtime);
 	createHandler(townh, "Town", pomtime);
@@ -239,77 +240,6 @@ void LibClasses::init(bool onlyEssential)
 	modh->afterLoad(onlyEssential);
 }
 
-void LibClasses::clear()
-{
-	delete heroh;
-	delete arth;
-	delete creh;
-	delete townh;
-	delete objh;
-	delete objtypeh;
-	delete spellh;
-	delete skillh;
-	delete modh;
-	delete bth;
-	delete tplh;
-	delete terviewh;
-#if SCRIPTING_ENABLED
-	delete scriptHandler;
-#endif
-	delete battlefieldsHandler;
-	delete generaltexth;
-	delete identifiersHandler;
-	delete obstacleHandler;
-	delete terrainTypeHandler;
-	delete riverTypeHandler;
-	delete roadTypeHandler;
-	delete settingsHandler;
-	makeNull();
-}
-
-void LibClasses::makeNull()
-{
-	generaltexth = nullptr;
-	heroh = nullptr;
-	arth = nullptr;
-	creh = nullptr;
-	townh = nullptr;
-	objh = nullptr;
-	objtypeh = nullptr;
-	spellh = nullptr;
-	skillh = nullptr;
-	modh = nullptr;
-	bth = nullptr;
-	tplh = nullptr;
-	terviewh = nullptr;
-#if SCRIPTING_ENABLED
-	scriptHandler = nullptr;
-#endif
-	battlefieldsHandler = nullptr;
-	identifiersHandler = nullptr;
-	obstacleHandler = nullptr;
-	terrainTypeHandler = nullptr;
-	riverTypeHandler = nullptr;
-	roadTypeHandler = nullptr;
-	settingsHandler = nullptr;
-}
-
-LibClasses::LibClasses()
-{
-	//init pointers to handlers
-	makeNull();
-}
-
-void LibClasses::callWhenDeserializing()
-{
-	//FIXME: check if any of these are needed
-	//generaltexth = new CGeneralTextHandler();
-	//generaltexth->load();
-	//arth->load(true);
-	//modh->recreateHandlers();
-	//modh->loadConfigFromFile ("defaultMods"); //TODO: remember last saved config
-}
-
 #if SCRIPTING_ENABLED
 void LibClasses::scriptsLoaded()
 {
@@ -317,10 +247,8 @@ void LibClasses::scriptsLoaded()
 }
 #endif
 
-LibClasses::~LibClasses()
-{
-	clear();
-}
+LibClasses::LibClasses() = default;
+LibClasses::~LibClasses() = default;
 
 std::shared_ptr<CContentHandler> LibClasses::getContent() const
 {

+ 24 - 29
lib/VCMI_Lib.h

@@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class CConsoleHandler;
 class CArtHandler;
 class CHeroHandler;
+class CHeroClassHandler;
 class CCreatureHandler;
 class CSpellHandler;
 class CSkillHandler;
@@ -47,20 +48,15 @@ namespace scripting
 }
 #endif
 
-
 /// Loads and constructs several handlers
-class DLL_LINKAGE LibClasses : public Services
+class DLL_LINKAGE LibClasses final : public Services
 {
-	CBonusTypeHandler * bth;
+	std::shared_ptr<CBonusTypeHandler> bth;
 
-	void callWhenDeserializing(); //should be called only by serialize !!!
-	void makeNull(); //sets all handler pointers to null
 	std::shared_ptr<CContentHandler> getContent() const;
 	void setContent(std::shared_ptr<CContentHandler> content);
 
 public:
-	bool IS_AI_ENABLED = false; //unused?
-
 	const ArtifactService * artifacts() const override;
 	const CreatureService * creatures() const override;
 	const FactionService * factions() const override;
@@ -83,27 +79,27 @@ public:
 	const IBonusTypeHandler * getBth() const; //deprecated
 	const CIdentifierStorage * identifiers() const;
 
-	CArtHandler * arth;
-	CHeroHandler * heroh;
-	CCreatureHandler * creh;
-	CSpellHandler * spellh;
-	CSkillHandler * skillh;
-	CObjectHandler * objh;
-	CObjectClassesHandler * objtypeh;
-	CTownHandler * townh;
-	CGeneralTextHandler * generaltexth;
-	CModHandler * modh;
-
-	TerrainTypeHandler * terrainTypeHandler;
-	RoadTypeHandler * roadTypeHandler;
-	RiverTypeHandler * riverTypeHandler;
-	CIdentifierStorage * identifiersHandler;
-
-	CTerrainViewPatternConfig * terviewh;
-	CRmgTemplateStorage * tplh;
-	BattleFieldHandler * battlefieldsHandler;
-	ObstacleHandler * obstacleHandler;
-	GameSettings * settingsHandler;
+	std::shared_ptr<CArtHandler> arth;
+	std::shared_ptr<CHeroHandler> heroh;
+	std::shared_ptr<CHeroClassHandler> heroclassesh;
+	std::shared_ptr<CCreatureHandler> creh;
+	std::shared_ptr<CSpellHandler> spellh;
+	std::shared_ptr<CSkillHandler> skillh;
+	std::shared_ptr<CObjectHandler> objh;
+	std::shared_ptr<CObjectClassesHandler> objtypeh;
+	std::shared_ptr<CTownHandler> townh;
+	std::shared_ptr<CGeneralTextHandler> generaltexth;
+	std::shared_ptr<CModHandler> modh;
+	std::shared_ptr<TerrainTypeHandler> terrainTypeHandler;
+	std::shared_ptr<RoadTypeHandler> roadTypeHandler;
+	std::shared_ptr<RiverTypeHandler> riverTypeHandler;
+	std::shared_ptr<CIdentifierStorage> identifiersHandler;
+	std::shared_ptr<CTerrainViewPatternConfig> terviewh;
+	std::shared_ptr<CRmgTemplateStorage> tplh;
+	std::shared_ptr<BattleFieldHandler> battlefieldsHandler;
+	std::shared_ptr<ObstacleHandler> obstacleHandler;
+	std::shared_ptr<GameSettings> settingsHandler;
+
 #if SCRIPTING_ENABLED
 	scripting::ScriptHandler * scriptHandler;
 #endif
@@ -111,7 +107,6 @@ public:
 	LibClasses(); //c-tor, loads .lods and NULLs handlers
 	~LibClasses();
 	void init(bool onlyEssential); //uses standard config file
-	void clear(); //deletes all handlers and its data
 
 	// basic initialization. should be called before init(). Can also extract original H3 archives
 	void loadFilesystem(bool extractArchives);

+ 10 - 0
lib/constants/EntityIdentifiers.cpp

@@ -151,6 +151,16 @@ std::string HeroClassID::entityType()
 	return "heroClass";
 }
 
+const CHeroClass * HeroClassID::toHeroClass() const
+{
+	return dynamic_cast<const CHeroClass*>(toEntity(VLC));
+}
+
+const HeroClass * HeroClassID::toEntity(const Services * services) const
+{
+	return services->heroClasses()->getByIndex(num);
+}
+
 si32 ObjectInstanceID::decode(const std::string & identifier)
 {
 	return std::stoi(identifier);

+ 5 - 0
lib/constants/EntityIdentifiers.h

@@ -21,6 +21,8 @@ class Creature;
 class CreatureService;
 class HeroType;
 class CHero;
+class CHeroClass;
+class HeroClass;
 class HeroTypeService;
 class Faction;
 class Skill;
@@ -81,6 +83,9 @@ public:
 	DLL_LINKAGE static si32 decode(const std::string & identifier);
 	DLL_LINKAGE static std::string encode(const si32 index);
 	static std::string entityType();
+
+	const CHeroClass * toHeroClass() const;
+	const HeroClass * toEntity(const Services * services) const;
 };
 
 class DLL_LINKAGE HeroTypeID : public EntityIdentifier<HeroTypeID>

+ 1 - 1
lib/gameState/CGameStateCampaign.cpp

@@ -347,7 +347,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->getHeroType().getNum()];
+		heroToPlace->type = heroToPlace->getHeroType().toHeroType();
 		heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front();
 
 		gameState->map->removeBlockVisTiles(heroPlaceholder, true);

+ 1 - 1
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -122,7 +122,7 @@ void CHeroInstanceConstructor::initTypeData(const JsonNode & input)
 	VLC->identifiers()->requestIdentifier(
 		"heroClass",
 		input["heroClass"],
-		[&](si32 index) { heroClass = VLC->heroh->classes[index]; });
+		[&](si32 index) { heroClass = HeroClassID(index).toHeroClass(); });
 
 	filtersJson = input["filters"];
 }

+ 2 - 2
lib/mapObjectConstructors/CommonConstructors.h

@@ -57,7 +57,7 @@ protected:
 	void initTypeData(const JsonNode & input) override;
 
 public:
-	CFaction * faction = nullptr;
+	const CFaction * faction = nullptr;
 	std::map<std::string, LogicalExpression<BuildingID>> filters;
 
 	void initializeObject(CGTownInstance * object) const override;
@@ -76,7 +76,7 @@ protected:
 	void initTypeData(const JsonNode & input) override;
 
 public:
-	CHeroClass * heroClass = nullptr;
+	const CHeroClass * heroClass = nullptr;
 	std::map<std::string, LogicalExpression<HeroTypeID>> filters;
 
 	void initializeObject(CGHeroInstance * object) const override;

+ 1 - 1
lib/mapObjectConstructors/DwellingInstanceConstructor.cpp

@@ -45,7 +45,7 @@ void DwellingInstanceConstructor::initTypeData(const JsonNode & input)
 		{
 			VLC->identifiers()->requestIdentifier("creature", creaturesOnLevel[currentCreature], [=] (si32 index)
 			{
-				availableCreatures[currentLevel][currentCreature] = VLC->creh->objects[index];
+				availableCreatures[currentLevel][currentCreature] = CreatureID(index).toCreature();
 			});
 		}
 		assert(!availableCreatures[currentLevel].empty());

+ 2 - 2
lib/mapObjects/CGCreature.cpp

@@ -313,11 +313,11 @@ 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[getCreature().getNum()];
+	const CCreature * myCreature = getCreature().toCreature();
 	myKindCres.insert(myCreature->getId()); //we
 	myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades
 
-	for(ConstTransitivePtr<CCreature> &crea : VLC->creh->objects)
+	for(auto const & crea : VLC->creh->objects)
 	{
 		if(vstd::contains(crea->upgrades, myCreature->getId())) //it's our base creatures
 			myKindCres.insert(crea->getId());

+ 7 - 7
lib/mapObjects/CGHeroInstance.cpp

@@ -316,7 +316,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
 {
 	assert(validTypes(true));
 	if(!type)
-		type = VLC->heroh->objects[getHeroType().getNum()];
+		type = getHeroType().toHeroType();
 
 	if (ID == Obj::HERO)
 		appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
@@ -590,11 +590,11 @@ void CGHeroInstance::pickRandomObject(CRandomGenerator & rand)
 	{
 		ID = Obj::HERO;
 		subID = cb->gameState()->pickNextHeroType(getOwner());
-		type = VLC->heroh->objects[getHeroType().getNum()];
+		type = getHeroType().toHeroType();
 		randomizeArmy(type->heroClass->faction);
 	}
 	else
-		type = VLC->heroh->objects[getHeroType().getNum()];
+		type = getHeroType().toHeroType();
 
 	auto oldSubID = subID;
 
@@ -879,7 +879,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
 		double necromancySkill = valOfBonuses(BonusType::UNDEAD_RAISE_PERCENTAGE) / 100.0;
 		const ui8 necromancyLevel = valOfBonuses(BonusType::IMPROVED_NECROMANCY);
 		vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all...
-		const std::map<ui32,si32> &casualties = battleResult.casualties[!battleResult.winner];
+		const std::map<CreatureID,si32> &casualties = battleResult.casualties[!battleResult.winner];
 		// figure out what to raise - pick strongest creature meeting requirements
 		CreatureID creatureTypeRaised = CreatureID::NONE; //now we always have IMPROVED_NECROMANCY, no need for hardcode
 		int requiredCasualtyLevel = 1;
@@ -888,7 +888,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
 		{
 			int maxCasualtyLevel = 1;
 			for(const auto & casualty : casualties)
-				vstd::amax(maxCasualtyLevel, VLC->creatures()->getByIndex(casualty.first)->getLevel());
+				vstd::amax(maxCasualtyLevel, VLC->creatures()->getById(casualty.first)->getLevel());
 			// pick best bonus available
 			std::shared_ptr<Bonus> topPick;
 			for(const std::shared_ptr<Bonus> & newPick : *improvedNecromancy)
@@ -936,7 +936,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
 		double raisedUnits = 0;
 		for(const auto & casualty : casualties)
 		{
-			const CCreature * c = VLC->creh->objects[casualty.first];
+			const CCreature * c = casualty.first.toCreature();
 			double raisedFromCasualty = std::min(c->getMaxHealth() / raisedUnitHealth, 1.0) * casualty.second * necromancySkill;
 			if(c->getLevel() < requiredCasualtyLevel)
 				raisedFromCasualty *= 0.5;
@@ -1742,7 +1742,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler)
 			if(!appearance)
 			{
 				// crossoverDeserialize
-				type = VLC->heroh->objects[getHeroType().getNum()];
+				type = getHeroType().toHeroType();
 				appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
 			}
 

+ 1 - 1
lib/mapObjects/CGHeroInstance.h

@@ -69,7 +69,7 @@ public:
 
 	//////////////////////////////////////////////////////////////////////////
 
-	ConstTransitivePtr<CHero> type;
+	const CHero * type;
 	TExpType exp; //experience points
 	ui32 level; //current level of hero
 

+ 1 - 1
lib/mapObjects/MiscObjects.cpp

@@ -769,7 +769,7 @@ void CGArtifact::initObj(CRandomGenerator & rand)
 			storedArtifact = a;
 		}
 		if(!storedArtifact->artType)
-			storedArtifact->setType(VLC->arth->objects[getArtifact().getNum()]);
+			storedArtifact->setType(getArtifact().toArtifact());
 	}
 	if(ID == Obj::SPELL_SCROLL)
 		subID = 1;

+ 1 - 1
lib/mapping/CMapOperation.cpp

@@ -510,7 +510,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
 		{
 			if(map->isInTheMap(pos))
 			{
-				auto * ptrConfig = VLC->terviewh;
+				const auto & ptrConfig = VLC->terviewh;
 				const auto * terType = map->getTile(pos).terType;
 				auto valid = validateTerrainView(pos, ptrConfig->getTerrainTypePatternById("n1")).result;
 

+ 1 - 1
lib/mapping/MapFormatH3M.cpp

@@ -760,7 +760,7 @@ void CMapLoaderH3M::readAllowedArtifacts()
 	// ban combo artifacts
 	if(!features.levelSOD)
 	{
-		for(CArtifact * artifact : VLC->arth->objects)
+		for(auto const & artifact : VLC->arth->objects)
 			if(artifact->isCombined())
 				map->allowedArtifact.erase(artifact->getId());
 	}

+ 14 - 14
lib/modding/ContentTypeHandler.cpp

@@ -189,23 +189,23 @@ void ContentTypeHandler::afterLoadFinalization()
 
 void CContentHandler::init()
 {
-	handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(&VLC->heroh->classes, "heroClass")));
-	handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth, "artifact")));
-	handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh, "creature")));
-	handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh, "faction")));
-	handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh, "object")));
-	handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh, "hero")));
-	handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell")));
-	handlers.insert(std::make_pair("skills", ContentTypeHandler(VLC->skillh, "skill")));
-	handlers.insert(std::make_pair("templates", ContentTypeHandler(VLC->tplh, "template")));
+	handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(VLC->heroclassesh.get(), "heroClass")));
+	handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth.get(), "artifact")));
+	handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh.get(), "creature")));
+	handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh.get(), "faction")));
+	handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh.get(), "object")));
+	handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh.get(), "hero")));
+	handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh.get(), "spell")));
+	handlers.insert(std::make_pair("skills", ContentTypeHandler(VLC->skillh.get(), "skill")));
+	handlers.insert(std::make_pair("templates", ContentTypeHandler(VLC->tplh.get(), "template")));
 #if SCRIPTING_ENABLED
 	handlers.insert(std::make_pair("scripts", ContentTypeHandler(VLC->scriptHandler, "script")));
 #endif
-	handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler, "battlefield")));
-	handlers.insert(std::make_pair("terrains", ContentTypeHandler(VLC->terrainTypeHandler, "terrain")));
-	handlers.insert(std::make_pair("rivers", ContentTypeHandler(VLC->riverTypeHandler, "river")));
-	handlers.insert(std::make_pair("roads", ContentTypeHandler(VLC->roadTypeHandler, "road")));
-	handlers.insert(std::make_pair("obstacles", ContentTypeHandler(VLC->obstacleHandler, "obstacle")));
+	handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler.get(), "battlefield")));
+	handlers.insert(std::make_pair("terrains", ContentTypeHandler(VLC->terrainTypeHandler.get(), "terrain")));
+	handlers.insert(std::make_pair("rivers", ContentTypeHandler(VLC->riverTypeHandler.get(), "river")));
+	handlers.insert(std::make_pair("roads", ContentTypeHandler(VLC->roadTypeHandler.get(), "road")));
+	handlers.insert(std::make_pair("obstacles", ContentTypeHandler(VLC->obstacleHandler.get(), "obstacle")));
 	//TODO: any other types of moddables?
 }
 

+ 1 - 1
lib/networkPacks/PacksForClient.h

@@ -1118,7 +1118,7 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
 struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack
 {
 	ArtifactLocation al; //where assembly will be put
-	CArtifact * builtArt;
+	const CArtifact * builtArt;
 
 	void applyGs(CGameState * gs);
 

+ 1 - 1
lib/networkPacks/PacksForClientBattle.h

@@ -128,7 +128,7 @@ struct DLL_LINKAGE BattleResult : public Query
 	BattleID battleID = BattleID::NONE;
 	EBattleResult result = EBattleResult::NORMAL;
 	ui8 winner = 2; //0 - attacker, 1 - defender, [2 - draw (should be possible?)]
-	std::map<ui32, si32> casualties[2]; //first => casualties of attackers - map crid => number
+	std::map<CreatureID, si32> casualties[2]; //first => casualties of attackers - map crid => number
 	TExpType exp[2] = {0, 0}; //exp for attacker and defender
 	std::set<ArtifactInstanceID> artifacts; //artifacts taken from loser to winner - currently unused
 

+ 10 - 10
lib/rmg/modificators/TreasurePlacer.cpp

@@ -159,12 +159,12 @@ void TreasurePlacer::addAllPossibleObjects()
 	//all following objects are unlimited
 	oi.maxPerZone = std::numeric_limits<ui32>::max();
 
-	std::vector<CCreature *> creatures; //native creatures for this zone
+	std::vector<const CCreature *> creatures; //native creatures for this zone
 	for(auto cre : VLC->creh->objects)
 	{
 		if(!cre->special && cre->getFaction() == zone.getTownType())
 		{
-			creatures.push_back(cre);
+			creatures.push_back(cre.get());
 		}
 	}
 	
@@ -283,7 +283,7 @@ void TreasurePlacer::addAllPossibleObjects()
 	//pandora box with creatures
 	const std::vector<int> & tierValues = generator.getConfig().pandoraCreatureValues;
 	
-	auto creatureToCount = [tierValues](CCreature * creature) -> int
+	auto creatureToCount = [tierValues](const CCreature * creature) -> int
 	{
 		if(!creature->getAIValue() || tierValues.empty()) //bug #2681
 			return 0; //this box won't be generated
@@ -350,11 +350,11 @@ void TreasurePlacer::addAllPossibleObjects()
 			auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
 			auto * obj = dynamic_cast<CGPandoraBox *>(factory->create());
 
-			std::vector <CSpell *> spells;
+			std::vector <const CSpell *> spells;
 			for(auto spell : VLC->spellh->objects)
 			{
 				if(map.isAllowedSpell(spell->id) && spell->getLevel() == i)
-					spells.push_back(spell);
+					spells.push_back(spell.get());
 			}
 			
 			RandomGeneratorUtil::randomShuffle(spells, zone.getRand());
@@ -383,11 +383,11 @@ void TreasurePlacer::addAllPossibleObjects()
 			auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
 			auto * obj = dynamic_cast<CGPandoraBox *>(factory->create());
 
-			std::vector <CSpell *> spells;
+			std::vector <const CSpell *> spells;
 			for(auto spell : VLC->spellh->objects)
 			{
-				if(map.isAllowedSpell(spell->id) && spell->school[SpellSchool(i)])
-					spells.push_back(spell);
+				if(map.isAllowedSpell(spell->id) && spell->hasSchool(SpellSchool(i)))
+					spells.push_back(spell.get());
 			}
 			
 			RandomGeneratorUtil::randomShuffle(spells, zone.getRand());
@@ -415,11 +415,11 @@ void TreasurePlacer::addAllPossibleObjects()
 		auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
 		auto * obj = dynamic_cast<CGPandoraBox *>(factory->create());
 
-		std::vector <CSpell *> spells;
+		std::vector <const CSpell *> spells;
 		for(auto spell : VLC->spellh->objects)
 		{
 			if(map.isAllowedSpell(spell->id))
-				spells.push_back(spell);
+				spells.push_back(spell.get());
 		}
 		
 		RandomGeneratorUtil::randomShuffle(spells, zone.getRand());

+ 0 - 6
lib/serializer/CSerializer.cpp

@@ -24,14 +24,8 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
 {
 	registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
 		[](const CGObjectInstance &obj){ return obj.id; });
-	registerVectoredType<CHero, HeroTypeID>(&lib->heroh->objects,
-		[](const CHero &h){ return h.getId(); });
 	registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
 		[](const CGHeroInstance &h){ return h.type->getId(); });
-	registerVectoredType<CCreature, CreatureID>(&lib->creh->objects,
-		[](const CCreature &cre){ return cre.getId(); });
-	registerVectoredType<CArtifact, ArtifactID>(&lib->arth->objects,
-		[](const CArtifact &art){ return art.getId(); });
 	registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
 		[](const CArtifactInstance &artInst){ return artInst.getId(); });
 	registerVectoredType<CQuest, si32>(&gs->map->quests,

+ 0 - 5
lib/serializer/CSerializer.h

@@ -65,11 +65,6 @@ class DLL_LINKAGE CSerializer
 		return t.getNum();
 	}
 
-	template <typename T, typename U>
-	void registerVectoredType(const std::vector<T*> *Vector, const std::function<U(const T&)> &idRetriever)
-	{
-		vectors[&typeid(T)] = VectorizedObjectInfo<T, U>(Vector, idRetriever);
-	}
 	template <typename T, typename U>
 	void registerVectoredType(const std::vector<ConstTransitivePtr<T> > *Vector, const std::function<U(const T&)> &idRetriever)
 	{

+ 2 - 2
lib/spells/CSpellHandler.cpp

@@ -969,7 +969,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
 
 void CSpellHandler::afterLoadFinalization()
 {
-	for(auto spell : objects)
+	for(auto & spell : objects)
 	{
 		spell->setupMechanics();
 	}
@@ -997,7 +997,7 @@ std::set<SpellID> CSpellHandler::getDefaultAllowed() const
 {
 	std::set<SpellID> allowedSpells;
 
-	for(const CSpell * s : objects)
+	for(auto const & s : objects)
 		if (!s->isSpecial() && !s->isCreatureAbility())
 			allowedSpells.insert(s->getId());
 

+ 1 - 1
mapeditor/graphics.cpp

@@ -125,7 +125,7 @@ void Graphics::load()
 
 void Graphics::loadHeroAnimations()
 {
-	for(auto & elem : VLC->heroh->classes.objects)
+	for(auto & elem : VLC->heroclassesh->objects)
 	{
 		for(auto templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->getIndex())->getTemplates())
 		{

+ 1 - 1
mapeditor/inspector/inspector.cpp

@@ -142,7 +142,7 @@ void Initializer::initialize(CGHeroInstance * o)
 		{
 			if(t->heroClass->getId() == HeroClassID(o->subID))
 			{
-				o->type = t;
+				o->type = t.get();
 				break;
 			}
 		}

+ 1 - 1
mapeditor/mapcontroller.cpp

@@ -153,7 +153,7 @@ void MapController::repairMap(CMap * map) const
 			}
 			
 			if(obj->ID != Obj::RANDOM_HERO)
-				nih->type = type;
+				nih->type = type.get();
 			
 			if(nih->ID == Obj::HERO) //not prison
 				nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();

+ 1 - 1
mapeditor/playerparams.cpp

@@ -48,7 +48,7 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent)
 	//load factions
 	for(auto idx : VLC->townh->getAllowedFactions())
 	{
-		CFaction * faction = VLC->townh->objects.at(idx);
+		const CFaction * faction = VLC->townh->objects.at(idx);
 		auto * item = new QListWidgetItem(QString::fromStdString(faction->getNameTranslated()));
 		item->setData(Qt::UserRole, QVariant::fromValue(idx.getNum()));
 		item->setFlags(item->flags() | Qt::ItemIsUserCheckable);

+ 1 - 1
mapeditor/validator.cpp

@@ -78,7 +78,7 @@ std::list<Validator::Issue> Validator::validate(const CMap * map)
 		if(!hplayers)
 			issues.emplace_back(tr("No human players allowed to play this map"), true);
 
-		std::set<CHero*> allHeroesOnMap; //used to find hero duplicated
+		std::set<const CHero*> allHeroesOnMap; //used to find hero duplicated
 		
 		//checking all objects in the map
 		for(auto o : map->objects)

+ 11 - 11
server/CGameHandler.cpp

@@ -826,7 +826,7 @@ void CGameHandler::onNewTurn()
 				if (!t->creatures.at(k).second.empty()) // there are creatures at this level
 				{
 					ui32 &availableCount = sac.creatures.at(k).first;
-					const CCreature *cre = VLC->creh->objects.at(t->creatures.at(k).second.back());
+					const CCreature *cre = t->creatures.at(k).second.back().toCreature();
 
 					if (n.specialWeek == NewTurn::PLAGUE)
 						availableCount = t->creatures.at(k).first / 2; //halve their number, no growth
@@ -2327,7 +2327,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
 				return;
 			}
 
-			CCreature * crea = VLC->creh->objects.at(t->town->creatures.at(level).at(upgradeNumber));
+			const CCreature * crea = t->town->creatures.at(level).at(upgradeNumber).toCreature();
 
 			SetAvailableCreatures ssi;
 			ssi.tid = t->id;
@@ -2461,7 +2461,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
 	const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(getObj(objid));
 	const CArmedInstance * army = dynamic_cast<const CArmedInstance *>(getObj(dstid));
 	const CGHeroInstance * hero = dynamic_cast<const CGHeroInstance *>(getObj(dstid));
-	const CCreature * c = VLC->creh->objects.at(crid);
+	const CCreature * c = crid.toCreature();
 
 	const bool warMachine = c->warMachine != ArtifactID::NONE;
 
@@ -2568,7 +2568,7 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI
 	giveResources(player, -totalCost);
 
 	//upgrade creature
-	changeStackType(StackLocation(obj, pos), VLC->creh->objects.at(upgID));
+	changeStackType(StackLocation(obj, pos), upgID.toCreature());
 	return true;
 }
 
@@ -2756,7 +2756,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
 
 	auto hero = getHero(dst.artHolder);
 	if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstSlot))
-		giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
+		giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK);
 
 	ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot));
 	if(src.artHolder != dst.artHolder)
@@ -2795,7 +2795,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
 			slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
 
 			if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact->getTypeId(), dstSlot))
-				giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
+				giveHeroNewArtifact(dstHero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK);
 		}
 	};
 
@@ -2883,7 +2883,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
 	const auto dstLoc = ArtifactLocation(hero->id, artifactSlot);
 	if(assemble)
 	{
-		CArtifact * combinedArt = VLC->arth->objects[assembleTo];
+		const CArtifact * combinedArt = assembleTo.toArtifact();
 		if(!combinedArt->isCombined())
 			COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!");
 		if(!vstd::contains(ArtifactUtils::assemblyPossibilities(hero, destArtifact->getTypeId()), combinedArt))
@@ -2897,7 +2897,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
 		}
 		
 		if(ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot))
-			giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
+			giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK);
 
 		AssembledArtifact aa;
 		aa.al = dstLoc;
@@ -2954,7 +2954,7 @@ bool CGameHandler::buyArtifact(ObjectInstanceID hid, ArtifactID aid)
 			return false;
 
 		giveResource(hero->getOwner(),EGameResID::GOLD,-GameConstants::SPELLBOOK_GOLD_COST);
-		giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
+		giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK);
 		assert(hero->getArt(ArtifactPosition::SPELLBOOK));
 		giveSpells(town,hero);
 		return true;
@@ -3025,7 +3025,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe
 		COMPLAIN_RET("Cannot find selected artifact on the list");
 
 	sendAndApply(&saa);
-	giveHeroNewArtifact(h, VLC->arth->objects[aid], ArtifactPosition::FIRST_AVAILABLE);
+	giveHeroNewArtifact(h, aid.toArtifact(), ArtifactPosition::FIRST_AVAILABLE);
 	return true;
 }
 
@@ -4080,7 +4080,7 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
 
 	RandomGeneratorUtil::randomShuffle(tiles, getRandomGenerator());
 	logGlobal->trace("Spawning wandering monsters. Found %d free tiles. Creature type: %d", tiles.size(), creatureID.num);
-	const CCreature *cre = VLC->creh->objects.at(creatureID);
+	const CCreature *cre = creatureID.toCreature();
 	for (int i = 0; i < (int)amount; ++i)
 	{
 		tile = tiles.begin();

+ 3 - 3
server/processors/HeroPoolProcessor.cpp

@@ -253,7 +253,7 @@ std::vector<const CHeroClass *> HeroPoolProcessor::findAvailableClassesFor(const
 			continue;
 
 		bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, player);
-		bool heroClassBanned = elem.second->type->heroClass->selectionProbability[factionID] == 0;
+		bool heroClassBanned = elem.second->type->heroClass->tavernProbability(factionID) == 0;
 
 		if(heroAvailable && !heroClassBanned)
 			result.push_back(elem.second->type->heroClass);
@@ -326,13 +326,13 @@ const CHeroClass * HeroPoolProcessor::pickClassFor(bool isNative, const PlayerCo
 
 	int totalWeight = 0;
 	for(const auto & heroClass : possibleClasses)
-		totalWeight += heroClass->selectionProbability.at(factionID);
+		totalWeight += heroClass->tavernProbability(factionID);
 
 	int roll = getRandomGenerator(player).nextInt(totalWeight - 1);
 
 	for(const auto & heroClass : possibleClasses)
 	{
-		roll -= heroClass->selectionProbability.at(factionID);
+		roll -= heroClass->tavernProbability(factionID);
 		if(roll < 0)
 			return heroClass;
 	}

+ 6 - 6
server/processors/PlayerMessageProcessor.cpp

@@ -137,7 +137,7 @@ void PlayerMessageProcessor::cheatGiveSpells(PlayerColor player, const CGHeroIns
 
 	///Give hero spellbook
 	if (!hero->hasSpellbook())
-		gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
+		gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK);
 
 	///Give all spells with bonus (to allow banned spells)
 	GiveBonus giveBonus(GiveBonus::ETarget::OBJECT);
@@ -215,11 +215,11 @@ void PlayerMessageProcessor::cheatGiveMachines(PlayerColor player, const CGHeroI
 		return;
 
 	if (!hero->getArt(ArtifactPosition::MACH1))
-		gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::BALLISTA], ArtifactPosition::MACH1);
+		gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::BALLISTA).toArtifact(), ArtifactPosition::MACH1);
 	if (!hero->getArt(ArtifactPosition::MACH2))
-		gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::AMMO_CART], ArtifactPosition::MACH2);
+		gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::AMMO_CART).toArtifact(), ArtifactPosition::MACH2);
 	if (!hero->getArt(ArtifactPosition::MACH3))
-		gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3);
+		gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::FIRST_AID_TENT).toArtifact(), ArtifactPosition::MACH3);
 }
 
 void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words)
@@ -233,7 +233,7 @@ void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHero
 		{
 			auto artID = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "artifact", word, false);
 			if(artID &&  VLC->arth->objects[*artID])
-				gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[*artID], ArtifactPosition::FIRST_AVAILABLE);
+				gameHandler->giveHeroNewArtifact(hero, ArtifactID(*artID).toArtifact(), ArtifactPosition::FIRST_AVAILABLE);
 		}
 	}
 	else
@@ -241,7 +241,7 @@ void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHero
 		for(int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods
 		{
 			if(VLC->arth->objects[g]->canBePutAt(hero))
-				gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[g], ArtifactPosition::FIRST_AVAILABLE);
+				gameHandler->giveHeroNewArtifact(hero, ArtifactID(g).toArtifact(), ArtifactPosition::FIRST_AVAILABLE);
 		}
 	}
 }