Browse Source

Removed pointer to VLC entity from CStackBasicDescriptor

Ivan Savenko 1 năm trước cách đây
mục cha
commit
d3af9f1c67
38 tập tin đã thay đổi với 140 bổ sung160 xóa
  1. 2 2
      AI/Nullkiller/AIGateway.cpp
  2. 2 2
      AI/Nullkiller/AIUtility.cpp
  3. 1 1
      AI/Nullkiller/Analyzers/ArmyManager.cpp
  4. 2 2
      AI/Nullkiller/Engine/PriorityEvaluator.cpp
  5. 1 1
      AI/VCAI/ArmyManager.cpp
  6. 1 1
      AI/VCAI/Goals/CompleteQuest.cpp
  7. 1 1
      AI/VCAI/VCAI.cpp
  8. 3 3
      client/widgets/CGarrisonInt.cpp
  9. 1 1
      client/widgets/MiscWidgets.cpp
  10. 6 6
      client/windows/CCreatureWindow.cpp
  11. 1 1
      client/windows/GUIClasses.cpp
  12. 0 5
      lib/CCreatureHandler.cpp
  13. 0 2
      lib/CCreatureHandler.h
  14. 57 61
      lib/CCreatureSet.cpp
  15. 7 16
      lib/CCreatureSet.h
  16. 5 5
      lib/CGameInfoCallback.cpp
  17. 2 2
      lib/CStack.cpp
  18. 1 1
      lib/bonuses/Limiters.cpp
  19. 2 2
      lib/gameState/CGameState.cpp
  20. 3 3
      lib/gameState/InfoAboutArmy.cpp
  21. 3 3
      lib/json/JsonRandom.cpp
  22. 1 1
      lib/mapObjectConstructors/DwellingInstanceConstructor.cpp
  23. 4 4
      lib/mapObjects/CBank.cpp
  24. 4 4
      lib/mapObjects/CGCreature.cpp
  25. 3 3
      lib/mapObjects/CGHeroInstance.cpp
  26. 3 3
      lib/mapObjects/CGTownInstance.cpp
  27. 1 1
      lib/mapObjects/CQuest.cpp
  28. 4 4
      lib/mapObjects/MiscObjects.cpp
  29. 1 1
      lib/mapping/MapFormatH3M.cpp
  30. 2 2
      lib/rewardable/Interface.cpp
  31. 2 2
      lib/rewardable/Limiter.cpp
  32. 1 1
      lib/rewardable/Reward.cpp
  33. 1 1
      lib/texts/MetaString.cpp
  34. 1 1
      mapeditor/inspector/questwidget.cpp
  35. 2 2
      mapeditor/inspector/rewardswidget.cpp
  36. 6 6
      server/CGameHandler.cpp
  37. 2 2
      server/battles/BattleResultProcessor.cpp
  38. 1 1
      server/processors/NewTurnProcessor.cpp

+ 2 - 2
AI/Nullkiller/AIGateway.cpp

@@ -1129,10 +1129,10 @@ void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * re
 		{
 			for(auto stack : recruiter->Slots())
 			{
-				if(!stack.second->type)
+				if(!stack.second->getType())
 					continue;
 				
-				auto duplicatingSlot = recruiter->getSlotFor(stack.second->type);
+				auto duplicatingSlot = recruiter->getSlotFor(stack.second->getCreature());
 
 				if(duplicatingSlot != stack.first)
 				{

+ 2 - 2
AI/Nullkiller/AIUtility.cpp

@@ -312,7 +312,7 @@ int getDuplicatingSlots(const CArmedInstance * army)
 
 	for(auto stack : army->Slots())
 	{
-		if(stack.second->type && army->getSlotFor(stack.second->type) != stack.first)
+		if(stack.second->getCreature() && army->getSlotFor(stack.second->getCreature()) != stack.first)
 			duplicatingSlots++;
 	}
 
@@ -387,7 +387,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
 	{
 		for(auto slot : h->Slots())
 		{
-			if(slot.second->type->hasUpgrades())
+			if(slot.second->getType()->hasUpgrades())
 				return true; //TODO: check price?
 		}
 		return false;

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

@@ -90,7 +90,7 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
 	{
 		for(auto & i : armyPtr->Slots())
 		{
-			auto cre = dynamic_cast<const CCreature*>(i.second->type);
+			auto cre = dynamic_cast<const CCreature*>(i.second->getType());
 			auto & slotInfp = creToPower[cre];
 
 			slotInfp.creature = cre;

+ 2 - 2
AI/Nullkiller/Engine/PriorityEvaluator.cpp

@@ -155,10 +155,10 @@ uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHero
 	for (auto c : creatures)
 	{
 		//Only if hero has slot for this creature in the army
-		auto ccre = dynamic_cast<const CCreature*>(c.data.type);
+		auto ccre = dynamic_cast<const CCreature*>(c.data.getType());
 		if (hero->getSlotFor(ccre).validSlot() || duplicatingSlots > 0)
 		{
-			result += (c.data.type->getAIValue() * c.data.count) * c.chance;
+			result += (c.data.getType()->getAIValue() * c.data.count) * c.chance;
 		}
 		/*else
 		{

+ 1 - 1
AI/VCAI/ArmyManager.cpp

@@ -36,7 +36,7 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
 	{
 		for(auto & i : armyPtr->Slots())
 		{
-			auto cre = dynamic_cast<const CCreature*>(i.second->type);
+			auto cre = dynamic_cast<const CCreature*>(i.second->getType());
 			auto & slotInfp = creToPower[cre];
 
 			slotInfp.creature = cre;

+ 1 - 1
AI/VCAI/Goals/CompleteQuest.cpp

@@ -162,7 +162,7 @@ TGoalVec CompleteQuest::missionArmy() const
 
 	for(auto creature : q.quest->mission.creatures)
 	{
-		solutions.push_back(sptr(GatherTroops(creature.type->getId(), creature.count)));
+		solutions.push_back(sptr(GatherTroops(creature.getId(), creature.count)));
 	}
 
 	return solutions;

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -2818,7 +2818,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
 	{
 		for(auto slot : h->Slots())
 		{
-			if(slot.second->type->hasUpgrades())
+			if(slot.second->getType()->hasUpgrades())
 				return true; //TODO: check price?
 		}
 		return false;

+ 3 - 3
client/widgets/CGarrisonInt.cpp

@@ -373,7 +373,7 @@ void CGarrisonSlot::gesture(bool on, const Point & initialPosition, const Point
 	const auto * otherArmy = upg == EGarrisonType::UPPER ? owner->lowerArmy() : owner->upperArmy();
 
 	bool stackExists = myStack != nullptr;
-	bool hasSameUnit = stackExists && !owner->army(upg)->getCreatureSlots(myStack->type, ID).empty();
+	bool hasSameUnit = stackExists && !owner->army(upg)->getCreatureSlots(myStack->getCreature(), ID).empty();
 	bool hasOwnEmptySlots = stackExists && owner->army(upg)->getFreeSlot() != SlotID();
 	bool exchangeMode = stackExists && owner->upperArmy() && owner->lowerArmy();
 	bool hasOtherEmptySlots = exchangeMode && otherArmy->getFreeSlot() != SlotID();
@@ -398,7 +398,7 @@ void CGarrisonSlot::update()
 	{
 		addUsedEvents(LCLICK | SHOW_POPUP | GESTURE | HOVER);
 		myStack = getObj()->getStackPtr(ID);
-		creature = myStack ? myStack->type : nullptr;
+		creature = myStack ? myStack->getCreature() : nullptr;
 	}
 	else
 	{
@@ -426,7 +426,7 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, EGa
 	: ID(IID),
 	owner(Owner),
 	myStack(creature_),
-	creature(creature_ ? creature_->type : nullptr),
+	creature(creature_ ? creature_->getCreature() : nullptr),
 	upg(Upg)
 {
 	OBJECT_CONSTRUCTION;

+ 1 - 1
client/widgets/MiscWidgets.cpp

@@ -280,7 +280,7 @@ void CArmyTooltip::init(const InfoAboutArmy &army)
 			continue;
 		}
 
-		icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), slot.second.type->getIconIndex(), 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y));
+		icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), slot.second.getType()->getIconIndex(), 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y));
 
 		std::string subtitle;
 		if(army.army.isDetailed)

+ 6 - 6
client/windows/CCreatureWindow.cpp

@@ -89,7 +89,7 @@ public:
 	std::string getName() const
 	{
 		if(commander)
-			return commander->type->getNameSingularTranslated();
+			return commander->getType()->getNameSingularTranslated();
 		else
 			return creature->getNamePluralTranslated();
 	}
@@ -695,7 +695,7 @@ CStackWindow::CStackWindow(const CStackInstance * stack, bool popup)
 	info(new UnitView())
 {
 	info->stackNode = stack;
-	info->creature = stack->type;
+	info->creature = stack->getCreature();
 	info->creatureCount = stack->count;
 	info->popupWindow = popup;
 	info->owner = dynamic_cast<const CGHeroInstance *> (stack->armyObj);
@@ -707,7 +707,7 @@ CStackWindow::CStackWindow(const CStackInstance * stack, std::function<void()> d
 	info(new UnitView())
 {
 	info->stackNode = stack;
-	info->creature = stack->type;
+	info->creature = stack->getCreature();
 	info->creatureCount = stack->count;
 
 	info->upgradeInfo = std::make_optional(UnitView::StackUpgradeInfo());
@@ -724,7 +724,7 @@ CStackWindow::CStackWindow(const CCommanderInstance * commander, bool popup)
 	info(new UnitView())
 {
 	info->stackNode = commander;
-	info->creature = commander->type;
+	info->creature = commander->getCreature();
 	info->commander = commander;
 	info->creatureCount = 1;
 	info->popupWindow = popup;
@@ -737,7 +737,7 @@ CStackWindow::CStackWindow(const CCommanderInstance * commander, std::vector<ui3
 	info(new UnitView())
 {
 	info->stackNode = commander;
-	info->creature = commander->type;
+	info->creature = commander->getCreature();
 	info->commander = commander;
 	info->creatureCount = 1;
 	info->levelupInfo = std::make_optional(UnitView::CommanderLevelInfo());
@@ -869,7 +869,7 @@ std::string CStackWindow::generateStackExpDescription()
 	const CStackInstance * stack = info->stackNode;
 	const CCreature * creature = info->creature;
 
-	int tier = stack->type->getLevel();
+	int tier = stack->getType()->getLevel();
 	int rank = stack->getExpRank();
 	if (!vstd::iswithin(tier, 1, 7))
 		tier = 0;

+ 1 - 1
client/windows/GUIClasses.cpp

@@ -1056,7 +1056,7 @@ CGarrisonWindow::CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance
 		if(up->Slots().size() > 0)
 		{
 			titleText = CGI->generaltexth->allTexts[35];
-			boost::algorithm::replace_first(titleText, "%s", up->Slots().begin()->second->type->getNamePluralTranslated());
+			boost::algorithm::replace_first(titleText, "%s", up->Slots().begin()->second->getType()->getNamePluralTranslated());
 		}
 		else
 		{

+ 0 - 5
lib/CCreatureHandler.cpp

@@ -343,11 +343,6 @@ bool CCreature::isMyUpgrade(const CCreature *anotherCre) const
 	return vstd::contains(upgrades, anotherCre->getId());
 }
 
-bool CCreature::valid() const
-{
-	return this == (*VLC->creh)[idNumber];
-}
-
 std::string CCreature::nodeName() const
 {
 	return "\"" + getNamePluralTextID() + "\"";

+ 0 - 2
lib/CCreatureHandler.h

@@ -166,8 +166,6 @@ public:
 	static int estimateCreatureCount(ui32 countID); //reverse version of above function, returns middle of range
 	bool isMyUpgrade(const CCreature *anotherCre) const;
 
-	bool valid() const;
-
 	void addBonus(int val, BonusType type);
 	void addBonus(int val, BonusType type, BonusSubtypeID subtype);
 	std::string nodeName() const override;

+ 57 - 61
lib/CCreatureSet.cpp

@@ -48,7 +48,7 @@ const CCreature * CCreatureSet::getCreature(const SlotID & slot) const
 {
 	auto i = stacks.find(slot);
 	if (i != stacks.end())
-		return i->second->type;
+		return i->second->getCreature();
 	else
 		return nullptr;
 }
@@ -84,11 +84,10 @@ SlotID CCreatureSet::getSlotFor(const CreatureID & creature, ui32 slotsAmount) c
 
 SlotID CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount) const
 {
-	assert(c && c->valid());
+	assert(c);
 	for(const auto & elem : stacks)
 	{
-		assert(elem.second->type->valid());
-		if(elem.second->type == c)
+		if(elem.second->getType() == c)
 		{
 			return elem.first; //if there is already such creature we return its slot id
 		}
@@ -98,18 +97,16 @@ SlotID CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount) const
 
 bool CCreatureSet::hasCreatureSlots(const CCreature * c, const SlotID & exclude) const
 {
-	assert(c && c->valid());
+	assert(c);
 	for(const auto & elem : stacks) // elem is const
 	{
 		if(elem.first == exclude) // Check slot
 			continue;
 
-		if(!elem.second || !elem.second->type) // Check creature
+		if(!elem.second || !elem.second->getType()) // Check creature
 			continue;
 
-		assert(elem.second->type->valid());
-
-		if(elem.second->type == c)
+		if(elem.second->getType() == c)
 			return true;
 	}
 	return false;
@@ -117,7 +114,7 @@ bool CCreatureSet::hasCreatureSlots(const CCreature * c, const SlotID & exclude)
 
 std::vector<SlotID> CCreatureSet::getCreatureSlots(const CCreature * c, const SlotID & exclude, TQuantity ignoreAmount) const
 {
-	assert(c && c->valid());
+	assert(c);
 	std::vector<SlotID> result;
 
 	for(const auto & elem : stacks)
@@ -125,13 +122,12 @@ std::vector<SlotID> CCreatureSet::getCreatureSlots(const CCreature * c, const Sl
 		if(elem.first == exclude)
 			continue;
 
-		if(!elem.second || !elem.second->type || elem.second->type != c)
+		if(!elem.second || !elem.second->getType() || elem.second->getType() != c)
 			continue;
 
 		if(elem.second->count == ignoreAmount || elem.second->count < 1)
 			continue;
 
-		assert(elem.second->type->valid());
 		result.push_back(elem.first);
 	}
 	return result;
@@ -139,13 +135,13 @@ std::vector<SlotID> CCreatureSet::getCreatureSlots(const CCreature * c, const Sl
 
 bool CCreatureSet::isCreatureBalanced(const CCreature * c, TQuantity ignoreAmount) const
 {
-	assert(c && c->valid());
+	assert(c);
 	TQuantity max = 0;
 	auto min = std::numeric_limits<TQuantity>::max();
 
 	for(const auto & elem : stacks)
 	{
-		if(!elem.second || !elem.second->type || elem.second->type != c)
+		if(!elem.second || !elem.second->getType() || elem.second->getType() != c)
 			continue;
 
 		const auto count = elem.second->count;
@@ -153,7 +149,6 @@ bool CCreatureSet::isCreatureBalanced(const CCreature * c, TQuantity ignoreAmoun
 		if(count == ignoreAmount || count < 1)
 			continue;
 
-		assert(elem.second->type->valid());
 
 		if(count > max)
 			max = count;
@@ -214,7 +209,7 @@ TMapCreatureSlot CCreatureSet::getCreatureMap() const
 	// https://www.cplusplus.com/reference/map/map/key_comp/
 	for(const auto & pair : stacks)
 	{
-		const auto * creature = pair.second->type;
+		const auto * creature = pair.second->getCreature();
 		auto slot = pair.first;
 		auto lb = creatureMap.lower_bound(creature);
 
@@ -234,7 +229,7 @@ TCreatureQueue CCreatureSet::getCreatureQueue(const SlotID & exclude) const
 	{
 		if(pair.first == exclude)
 			continue;
-		creatureQueue.push(std::make_pair(pair.second->type, pair.first));
+		creatureQueue.push(std::make_pair(pair.second->getCreature(), pair.first));
 	}
 	return creatureQueue;
 }
@@ -262,10 +257,10 @@ bool CCreatureSet::mergeableStacks(std::pair<SlotID, SlotID> & out, const SlotID
 	//try to match creature to our preferred stack
 	if(preferable.validSlot() &&  vstd::contains(stacks, preferable))
 	{
-		const CCreature *cr = stacks.find(preferable)->second->type;
+		const CCreature *cr = stacks.find(preferable)->second->getCreature();
 		for(const auto & elem : stacks)
 		{
-			if(cr == elem.second->type && elem.first != preferable)
+			if(cr == elem.second->getType() && elem.first != preferable)
 			{
 				out.first = preferable;
 				out.second = elem.first;
@@ -278,7 +273,7 @@ bool CCreatureSet::mergeableStacks(std::pair<SlotID, SlotID> & out, const SlotID
 	{
 		for(const auto & elem : stacks)
 		{
-			if(stack.second->type == elem.second->type && stack.first != elem.first)
+			if(stack.second->getType() == elem.second->getType() && stack.first != elem.first)
 			{
 				out.first = stack.first;
 				out.second = elem.first;
@@ -328,7 +323,7 @@ void CCreatureSet::addToSlot(const SlotID & slot, CStackInstance * stack, bool a
 	{
 		putStack(slot, stack);
 	}
-	else if(allowMerging && stack->type == getCreature(slot))
+	else if(allowMerging && stack->getType() == getCreature(slot))
 	{
 		joinStack(slot, stack);
 	}
@@ -514,7 +509,7 @@ void CCreatureSet::putStack(const SlotID & slot, CStackInstance * stack)
 void CCreatureSet::joinStack(const SlotID & slot, CStackInstance * stack)
 {
 	[[maybe_unused]] const CCreature *c = getCreature(slot);
-	assert(c == stack->type);
+	assert(c == stack->getType());
 	assert(c);
 
 	//TODO move stuff
@@ -577,9 +572,9 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
 		std::set<const CCreature*> cresToAdd;
 		for(const auto & elem : cs.stacks)
 		{
-			SlotID dest = getSlotFor(elem.second->type);
+			SlotID dest = getSlotFor(elem.second->getCreature());
 			if(!dest.validSlot() || hasStackAtSlot(dest))
-				cresToAdd.insert(elem.second->type);
+				cresToAdd.insert(elem.second->getCreature());
 		}
 		return cresToAdd.size() <= freeSlots;
 	}
@@ -590,13 +585,13 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
 
 		//get types of creatures that need their own slot
 		for(const auto & elem : cs.stacks)
-			if ((j = cres.getSlotFor(elem.second->type)).validSlot())
-				cres.addToSlot(j, elem.second->type->getId(), 1, true);  //merge if possible
+			if ((j = cres.getSlotFor(elem.second->getCreature())).validSlot())
+				cres.addToSlot(j, elem.second->getId(), 1, true);  //merge if possible
 			//cres.addToSlot(elem.first, elem.second->type->getId(), 1, true);
 		for(const auto & elem : stacks)
 		{
-			if ((j = cres.getSlotFor(elem.second->type)).validSlot())
-				cres.addToSlot(j, elem.second->type->getId(), 1, true);  //merge if possible
+			if ((j = cres.getSlotFor(elem.second->getCreature())).validSlot())
+				cres.addToSlot(j, elem.second->getId(), 1, true);  //merge if possible
 			else
 				return false; //no place found
 		}
@@ -693,7 +688,7 @@ void CStackInstance::init()
 {
 	experience = 0;
 	count = 0;
-	type = nullptr;
+	setType(nullptr);
 	_armyObj = nullptr;
 	setNodeType(STACK_INSTANCE);
 }
@@ -707,7 +702,7 @@ int CStackInstance::getExpRank() const
 {
 	if (!VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
 		return 0;
-	int tier = type->getLevel();
+	int tier = getType()->getLevel();
 	if (vstd::iswithin(tier, 1, 7))
 	{
 		for(int i = static_cast<int>(VLC->creh->expRanks[tier].size()) - 2; i > -1; --i) //sic!
@@ -730,12 +725,12 @@ int CStackInstance::getExpRank() const
 
 int CStackInstance::getLevel() const
 {
-	return std::max(1, static_cast<int>(type->getLevel()));
+	return std::max(1, static_cast<int>(getType()->getLevel()));
 }
 
 void CStackInstance::giveStackExp(TExpType exp)
 {
-	int level = type->getLevel();
+	int level = getType()->getLevel();
 	if (!vstd::iswithin(level, 1, 7))
 		level = 0;
 
@@ -756,17 +751,17 @@ void CStackInstance::setType(const CreatureID & creID)
 
 void CStackInstance::setType(const CCreature *c)
 {
-	if(type)
+	if(getCreature())
 	{
-		detachFromSource(*type);
-		if (type->isMyUpgrade(c) && VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
+		detachFromSource(*getCreature());
+		if (getCreature()->isMyUpgrade(c) && VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
 			experience = static_cast<TExpType>(experience * VLC->creh->expAfterUpgrade / 100.0);
 	}
 
 	CStackBasicDescriptor::setType(c);
 
-	if(type)
-		attachToSource(*type);
+	if(getCreature())
+		attachToSource(*getCreature());
 }
 std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const
 {
@@ -808,7 +803,7 @@ bool CStackInstance::valid(bool allowUnrandomized) const
 {
 	if(!randomStack)
 	{
-		return (type && type == type->getId().toEntity(VLC));
+		return (getType() && getType() == getId().toEntity(VLC));
 	}
 	else
 		return allowUnrandomized;
@@ -818,8 +813,8 @@ std::string CStackInstance::nodeName() const
 {
 	std::ostringstream oss;
 	oss << "Stack of " << count << " of ";
-	if(type)
-		oss << type->getNamePluralTextID();
+	if(getType())
+		oss << getType()->getNamePluralTextID();
 	else
 		oss << "[UNDEFINED TYPE]";
 
@@ -841,21 +836,21 @@ void CStackInstance::deserializationFix()
 
 CreatureID CStackInstance::getCreatureID() const
 {
-	if(type)
-		return type->getId();
+	if(getType())
+		return getType()->getId();
 	else
 		return CreatureID::NONE;
 }
 
 std::string CStackInstance::getName() const
 {
-	return (count > 1) ? type->getNamePluralTranslated() : type->getNameSingularTranslated();
+	return (count > 1) ? getType()->getNamePluralTranslated() : getType()->getNameSingularTranslated();
 }
 
 ui64 CStackInstance::getPower() const
 {
-	assert(type);
-	return static_cast<ui64>(type->getAIValue()) * count;
+	assert(getType());
+	return static_cast<ui64>(getType()->getAIValue()) * count;
 }
 
 ArtBearer::ArtBearer CStackInstance::bearerType() const
@@ -899,7 +894,7 @@ void CStackInstance::serializeJson(JsonSerializeFormat & handler)
 	else
 	{
 		//type set by CStackBasicDescriptor::serializeJson
-		if(type == nullptr)
+		if(getType() == nullptr)
 		{
 			uint8_t level = 0;
 			uint8_t upgrade = 0;
@@ -914,8 +909,8 @@ void CStackInstance::serializeJson(JsonSerializeFormat & handler)
 
 FactionID CStackInstance::getFactionID() const
 {
-	if(type)
-		return type->getFactionID();
+	if(getType())
+		return getType()->getFactionID();
 		
 	return FactionID::NEUTRAL;
 }
@@ -943,7 +938,7 @@ void CCommanderInstance::init()
 	experience = 0;
 	level = 1;
 	count = 1;
-	type = nullptr;
+	setType(nullptr);
 	_armyObj = nullptr;
 	setNodeType (CBonusSystemNode::COMMANDER);
 	secondarySkills.resize (ECommander::SPELL_POWER + 1);
@@ -998,24 +993,29 @@ bool CCommanderInstance::gainsLevel() const
 CStackBasicDescriptor::CStackBasicDescriptor() = default;
 
 CStackBasicDescriptor::CStackBasicDescriptor(const CreatureID & id, TQuantity Count):
-	type(id.toCreature()),
+	typeID(id),
 	count(Count)
 {
 }
 
 CStackBasicDescriptor::CStackBasicDescriptor(const CCreature *c, TQuantity Count)
-	: type(c), count(Count)
+	: typeID(c ? c->getId() : CreatureID()), count(Count)
 {
 }
 
+const CCreature * CStackBasicDescriptor::getCreature() const
+{
+	return typeID.toCreature();
+}
+
 const Creature * CStackBasicDescriptor::getType() const
 {
-	return type;
+	return typeID.toEntity(VLC);
 }
 
 CreatureID CStackBasicDescriptor::getId() const
 {
-	return type->getId();
+	return typeID;
 }
 
 TQuantity CStackBasicDescriptor::getCount() const
@@ -1023,18 +1023,14 @@ TQuantity CStackBasicDescriptor::getCount() const
 	return count;
 }
 
-
 void CStackBasicDescriptor::setType(const CCreature * c)
 {
-	type = c;
+	typeID = c ? c->getId() : CreatureID();
 }
 
 bool operator== (const CStackBasicDescriptor & l, const CStackBasicDescriptor & r)
 {
-	return (!l.type && !r.type)
-	|| (l.type && r.type
-		&& l.type->getId() == r.type->getId()
-		&& l.count == r.count);
+	return l.typeID == r.typeID && l.count == r.count;
 }
 
 void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
@@ -1043,9 +1039,9 @@ void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
 
 	if(handler.saving)
 	{
-		if(type)
+		if(typeID.hasValue())
 		{
-			std::string typeName = type->getJsonKey();
+			std::string typeName = typeID.toEntity(VLC)->getJsonKey();
 			handler.serializeString("type", typeName);
 		}
 	}

+ 7 - 16
lib/CCreatureSet.h

@@ -31,8 +31,8 @@ class JsonSerializeFormat;
 
 class DLL_LINKAGE CStackBasicDescriptor
 {
+	CreatureID typeID;
 public:
-	const CCreature *type = nullptr;
 	TQuantity count = -1; //exact quantity or quantity ID from CCreature::getQuantityID when getting info about enemy army
 
 	CStackBasicDescriptor();
@@ -41,29 +41,20 @@ public:
 	virtual ~CStackBasicDescriptor() = default;
 
 	const Creature * getType() const;
+	const CCreature * getCreature() const;
 	CreatureID getId() const;
 	TQuantity getCount() const;
 
 	virtual void setType(const CCreature * c);
-	
+
 	friend bool operator== (const CStackBasicDescriptor & l, const CStackBasicDescriptor & r);
 
 	template <typename Handler> void serialize(Handler &h)
 	{
-		if(h.saving)
-		{
-			auto idNumber = type ? type->getId() : CreatureID(CreatureID::NONE);
-			h & idNumber;
-		}
-		else
-		{
-			CreatureID idNumber;
-			h & idNumber;
-			if(idNumber != CreatureID::NONE)
-				setType(dynamic_cast<const CCreature*>(VLC->creatures()->getById(idNumber)));
-			else
-				type = nullptr;
-		}
+		h & typeID;
+		if(!h.saving)
+			setType(typeID.toCreature());
+
 		h & count;
 	}
 

+ 5 - 5
lib/CGameInfoCallback.cpp

@@ -345,10 +345,10 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 
 			for(auto & elem : info.army)
 			{
-				if(static_cast<int>(elem.second.type->getAIValue()) > maxAIValue)
+				if(static_cast<int>(elem.second.getCreature()->getAIValue()) > maxAIValue)
 				{
-					maxAIValue = elem.second.type->getAIValue();
-					mostStrong = elem.second.type;
+					maxAIValue = elem.second.getCreature()->getAIValue();
+					mostStrong = elem.second.getCreature();
 				}
 			}
 
@@ -357,7 +357,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 			else
 				for(auto & elem : info.army)
 				{
-					elem.second.type = mostStrong;
+					elem.second.setType(mostStrong);
 				}
 		};
 
@@ -390,7 +390,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 
 			if(nullptr != mostStrong) //possible, faction may have no creatures at all
 				for(auto & elem : info.army)
-					elem.second.type = mostStrong;
+					elem.second.setType(mostStrong);
 		};
 
 

+ 2 - 2
lib/CStack.cpp

@@ -28,7 +28,7 @@ CStack::CStack(const CStackInstance * Base, const PlayerColor & O, int I, Battle
 	CBonusSystemNode(STACK_BATTLE),
 	base(Base),
 	ID(I),
-	type(Base->type),
+	type(Base->getCreature()),
 	baseAmount(Base->count),
 	owner(O),
 	slot(S),
@@ -48,7 +48,7 @@ CStack::CStack():
 CStack::CStack(const CStackBasicDescriptor * stack, const PlayerColor & O, int I, BattleSide Side, const SlotID & S):
 	CBonusSystemNode(STACK_BATTLE),
 	ID(I),
-	type(stack->type),
+	type(stack->getCreature()),
 	baseAmount(stack->count),
 	owner(O),
 	slot(S),

+ 1 - 1
lib/bonuses/Limiters.cpp

@@ -75,7 +75,7 @@ static const CCreature * retrieveCreature(const CBonusSystemNode *node)
 	default:
 		const CStackInstance * csi = retrieveStackInstance(node);
 		if(csi)
-			return csi->type;
+			return csi->getCreature();
 		return nullptr;
 	}
 }

+ 2 - 2
lib/gameState/CGameState.cpp

@@ -1091,7 +1091,7 @@ void CGameState::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, Upg
 UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
 {
 	UpgradeInfo ret;
-	const CCreature *base = stack.type;
+	const CCreature *base = stack.getCreature();
 
 	if (stack.armyObj->ID == Obj::HERO)
 	{
@@ -1571,7 +1571,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
 			{
 				for(const auto & it : elem->Slots())
 				{
-					CreatureID toCmp = it.second->type->getId(); //ID of creature we should compare with the best one
+					CreatureID toCmp = it.second->getId(); //ID of creature we should compare with the best one
 					if(bestCre == CreatureID::NONE || bestCre.toEntity(VLC)->getAIValue() < toCmp.toEntity(VLC)->getAIValue())
 					{
 						bestCre = toCmp;

+ 3 - 3
lib/gameState/InfoAboutArmy.cpp

@@ -26,7 +26,7 @@ ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed)
 		if(detailed)
 			(*this)[elem.first] = *elem.second;
 		else
-			(*this)[elem.first] = CStackBasicDescriptor(elem.second->type, (int)elem.second->getQuantityID());
+			(*this)[elem.first] = CStackBasicDescriptor(elem.second->getCreature(), (int)elem.second->getQuantityID());
 	}
 }
 
@@ -42,12 +42,12 @@ int ArmyDescriptor::getStrength() const
 	if(isDetailed)
 	{
 		for(const auto & elem : *this)
-			ret += elem.second.type->getAIValue() * elem.second.count;
+			ret += elem.second.getType()->getAIValue() * elem.second.count;
 	}
 	else
 	{
 		for(const auto & elem : *this)
-			ret += elem.second.type->getAIValue() * CCreature::estimateCreatureCount(elem.second.count);
+			ret += elem.second.getType()->getAIValue() * CCreature::estimateCreatureCount(elem.second.count);
 	}
 	return static_cast<int>(ret);
 }

+ 3 - 3
lib/json/JsonRandom.cpp

@@ -485,13 +485,13 @@ VCMI_LIB_NAMESPACE_BEGIN
 		else
 			logMod->warn("Failed to select suitable random creature!");
 
-		stack.type = pickedCreature.toCreature();
+		stack.setType(pickedCreature.toCreature());
 		stack.count = loadValue(value, rng, variables);
-		if (!value["upgradeChance"].isNull() && !stack.type->upgrades.empty())
+		if (!value["upgradeChance"].isNull() && !stack.getCreature()->upgrades.empty())
 		{
 			if (int(value["upgradeChance"].Float()) > rng.nextInt(99)) // select random upgrade
 			{
-				stack.type = RandomGeneratorUtil::nextItem(stack.type->upgrades, rng)->toCreature();
+				stack.setType(RandomGeneratorUtil::nextItem(stack.getCreature()->upgrades, rng)->toCreature());
 			}
 		}
 		return stack;

+ 1 - 1
lib/mapObjectConstructors/DwellingInstanceConstructor.cpp

@@ -102,7 +102,7 @@ void DwellingInstanceConstructor::randomizeObject(CGDwelling * dwelling, vstd::R
 		JsonRandom::Variables emptyVariables;
 		for(auto & stack : randomizer.loadCreatures(guards, rng, emptyVariables))
 		{
-			dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count));
+			dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.getId(), stack.count));
 		}
 	}
 	else //default condition - creatures are of level 5 or higher

+ 4 - 4
lib/mapObjects/CBank.cpp

@@ -94,7 +94,7 @@ void CBank::setConfig(const BankConfig & config)
 	clearSlots(); // remove all stacks, if any
 
 	for(const auto & stack : config.guards)
-		setCreature (SlotID(stacksCount()), stack.type->getId(), stack.count);
+		setCreature (SlotID(stacksCount()), stack.getId(), stack.count);
 
 	daycounter = 1; //yes, 1 since "today" daycounter won't be incremented
 }
@@ -190,8 +190,8 @@ void CBank::doVisit(const CGHeroInstance * hero) const
 			iw.text.appendLocalString(EMetaText::ADVOB_TXT, 34);
 			const auto * strongest = boost::range::max_element(bankConfig->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b)
 			{
-				return a.type->getFightValue() < b.type->getFightValue();
-			})->type;
+				return a.getType()->getFightValue() < b.getType()->getFightValue();
+			})->getType();
 
 			iw.text.replaceNamePlural(strongest->getId());
 			iw.text.replaceRawString(loot.buildList());
@@ -244,7 +244,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
 		CCreatureSet ourArmy;
 		for(const auto & slot : bankConfig->creatures)
 		{
-			ourArmy.addToSlot(ourArmy.getSlotFor(slot.type->getId()), slot.type->getId(), slot.count);
+			ourArmy.addToSlot(ourArmy.getSlotFor(slot.getId()), slot.getId(), slot.count);
 		}
 
 		for(const auto & elem : ourArmy.Slots())

+ 4 - 4
lib/mapObjects/CGCreature.cpp

@@ -359,7 +359,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
 	for(const auto & elem : h->Slots())
 	{
 		bool isOurUpgrade = vstd::contains(getCreature()->upgrades, elem.second->getCreatureID());
-		bool isOurDowngrade = vstd::contains(elem.second->type->upgrades, getCreatureID());
+		bool isOurDowngrade = vstd::contains(elem.second->getCreature()->upgrades, getCreatureID());
 
 		if(isOurUpgrade || isOurDowngrade)
 			count += elem.second->count;
@@ -480,7 +480,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const
 		if (containsUpgradedStack()) //upgrade
 		{
 			SlotID slotID = SlotID(static_cast<si32>(std::floor(static_cast<float>(stacks.size()) / 2.0f)));
-			const auto & upgrades = getStack(slotID).type->upgrades;
+			const auto & upgrades = getStack(slotID).getCreature()->upgrades;
 			if(!upgrades.empty())
 			{
 				auto it = RandomGeneratorUtil::nextItem(upgrades, cb->gameState()->getRandomGenerator());
@@ -521,7 +521,7 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
 		const CCreature * cre = getCreature();
 		for(i = stacks.begin(); i != stacks.end(); i++)
 		{
-			if(cre->isMyUpgrade(i->second->type))
+			if(cre->isMyUpgrade(i->second->getCreature()))
 			{
 				cb->changeStackType(StackLocation(this, i->first), cre); //un-upgrade creatures
 			}
@@ -536,7 +536,7 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
 			// TODO it's either overcomplicated (if we assume there'll be only one stack) or buggy (if we allow multiple stacks... but that'll also cause troubles elsewhere)
 			i = stacks.end();
 			i--;
-			SlotID slot = getSlotFor(i->second->type);
+			SlotID slot = getSlotFor(i->second->getCreature());
 			if(slot == i->first) //no reason to move stack to its own slot
 				break;
 			else

+ 3 - 3
lib/mapObjects/CGHeroInstance.cpp

@@ -1806,14 +1806,14 @@ bool CGHeroInstance::isMissionCritical() const
 
 void CGHeroInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const
 {
-	TConstBonusListPtr lista = getBonuses(Selector::typeSubtype(BonusType::SPECIAL_UPGRADE, BonusSubtypeID(stack.type->getId())));
+	TConstBonusListPtr lista = getBonuses(Selector::typeSubtype(BonusType::SPECIAL_UPGRADE, BonusSubtypeID(stack.getId())));
 	for(const auto & it : *lista)
 	{
 		auto nid = CreatureID(it->additionalInfo[0]);
-		if (nid != stack.type->getId()) //in very specific case the upgrade is available by default (?)
+		if (nid != stack.getId()) //in very specific case the upgrade is available by default (?)
 		{
 			info.newID.push_back(nid);
-			info.cost.push_back(nid.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost());
+			info.cost.push_back(nid.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
 		}
 	}
 }

+ 3 - 3
lib/mapObjects/CGTownInstance.cpp

@@ -1227,14 +1227,14 @@ void CGTownInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &s
 {
 	for(const CGTownInstance::TCreaturesSet::value_type & dwelling : creatures)
 	{
-		if (vstd::contains(dwelling.second, stack.type->getId())) //Dwelling with our creature
+		if (vstd::contains(dwelling.second, stack.getId())) //Dwelling with our creature
 		{
 			for(const auto & upgrID : dwelling.second)
 			{
-				if(vstd::contains(stack.type->upgrades, upgrID)) //possible upgrade
+				if(vstd::contains(stack.getCreature()->upgrades, upgrID)) //possible upgrade
 				{
 					info.newID.push_back(upgrID);
-					info.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost());
+					info.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
 				}
 			}
 		}

+ 1 - 1
lib/mapObjects/CQuest.cpp

@@ -110,7 +110,7 @@ bool CQuest::checkMissionArmy(const CQuest * q, const CCreatureSet * army)
 	{
 		for(count = 0, it = army->Slots().begin(); it != army->Slots().end(); ++it)
 		{
-			if(it->second->type == cre->type)
+			if(it->second->getType() == cre->getType())
 			{
 				count += it->second->count;
 				slotsCount++;

+ 4 - 4
lib/mapObjects/MiscObjects.cpp

@@ -1152,7 +1152,7 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
 			if(drown)
 			{
 				cb->changeStackCount(StackLocation(h, i->first), -drown);
-				xp += drown * i->second->type->getMaxHealth();
+				xp += drown * i->second->getType()->getMaxHealth();
 			}
 		}
 
@@ -1318,7 +1318,7 @@ void HillFort::onHeroVisit(const CGHeroInstance * h) const
 
 void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const
 {
-	int32_t level = stack.type->getLevel();
+	int32_t level = stack.getType()->getLevel();
 	int32_t index = std::clamp<int32_t>(level - 1, 0, upgradeCostPercentage.size() - 1);
 
 	int costModifier = upgradeCostPercentage[index];
@@ -1326,10 +1326,10 @@ void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack)
 	if (costModifier < 0)
 		return; // upgrade not allowed
 
-	for(const auto & nid : stack.type->upgrades)
+	for(const auto & nid : stack.getCreature()->upgrades)
 	{
 		info.newID.push_back(nid);
-		info.cost.push_back((nid.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost()) * costModifier / 100);
+		info.cost.push_back((nid.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost()) * costModifier / 100);
 	}
 }
 

+ 1 - 1
lib/mapping/MapFormatH3M.cpp

@@ -2116,7 +2116,7 @@ EQuestMission CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & positi
 			guard->quest->mission.creatures.resize(typeNumber);
 			for(size_t hh = 0; hh < typeNumber; ++hh)
 			{
-				guard->quest->mission.creatures[hh].type = reader->readCreature().toCreature();
+				guard->quest->mission.creatures[hh].setType(reader->readCreature().toCreature());
 				guard->quest->mission.creatures[hh].count = reader->readUInt16();
 			}
 			break;

+ 2 - 2
lib/rewardable/Interface.cpp

@@ -185,7 +185,7 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 
 			for(const auto & change : info.reward.creaturesChange)
 			{
-				if (heroStack->type->getId() == change.first)
+				if (heroStack->getId() == change.first)
 				{
 					StackLocation location(hero, slot.first);
 					cb->changeStackType(location, change.second.toCreature());
@@ -199,7 +199,7 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 	{
 		CCreatureSet creatures;
 		for(const auto & crea : info.reward.creatures)
-			creatures.addToSlot(creatures.getFreeSlot(), new CStackInstance(crea.type, crea.count));
+			creatures.addToSlot(creatures.getFreeSlot(), new CStackInstance(crea.getCreature(), crea.count));
 
 		if(auto * army = dynamic_cast<const CArmedInstance*>(this)) //TODO: to fix that, CArmedInstance must be split on map instance part and interface part
 			cb->giveCreatures(army, hero, creatures, false);

+ 2 - 2
lib/rewardable/Limiter.cpp

@@ -84,7 +84,7 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 		for(const auto & slot : hero->Slots())
 		{
 			const CStackInstance * heroStack = slot.second;
-			if (heroStack->type == reqStack.type)
+			if (heroStack->getType() == reqStack.getType())
 				count += heroStack->count;
 		}
 		if (count < reqStack.count) //not enough creatures of this kind
@@ -233,7 +233,7 @@ void Rewardable::Limiter::loadComponents(std::vector<Component> & comps,
 		comps.emplace_back(ComponentType::SPELL, entry);
 
 	for(const auto & entry : creatures)
-		comps.emplace_back(ComponentType::CREATURE, entry.type->getId(), entry.count);
+		comps.emplace_back(ComponentType::CREATURE, entry.getId(), entry.count);
 	
 	for(const auto & entry : players)
 		comps.emplace_back(ComponentType::FLAG, entry);

+ 1 - 1
lib/rewardable/Reward.cpp

@@ -121,7 +121,7 @@ void Rewardable::Reward::loadComponents(std::vector<Component> & comps, const CG
 	}
 
 	for(const auto & entry : creatures)
-		comps.emplace_back(ComponentType::CREATURE, entry.type->getId(), entry.count);
+		comps.emplace_back(ComponentType::CREATURE, entry.getId(), entry.count);
 
 	for (size_t i=0; i<resources.size(); i++)
 	{

+ 1 - 1
lib/texts/MetaString.cpp

@@ -438,7 +438,7 @@ void MetaString::replaceName(const CreatureID & id, TQuantity count) //adds sing
 
 void MetaString::replaceName(const CStackBasicDescriptor & stack)
 {
-	replaceName(stack.type->getId(), stack.count);
+	replaceName(stack.getId(), stack.count);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
mapeditor/inspector/questwidget.cpp

@@ -169,7 +169,7 @@ void QuestWidget::obtainData()
 	}
 	for(auto & i : quest.mission.creatures)
 	{
-		int index = i.type->getIndex();
+		int index = i.getType()->getIndex();
 		ui->lCreatureId->setCurrentIndex(index);
 		ui->lCreatureAmount->setValue(i.count);
 		onCreatureAdd(ui->lCreatures, ui->lCreatureId, ui->lCreatureAmount);

+ 2 - 2
mapeditor/inspector/rewardswidget.cpp

@@ -459,7 +459,7 @@ void RewardsWidget::loadCurrentVisitInfo(int index)
 	}
 	for(auto & i : vinfo.reward.creatures)
 	{
-		int index = i.type->getIndex();
+		int index = i.getType()->getIndex();
 		ui->rCreatureId->setCurrentIndex(index);
 		ui->rCreatureAmount->setValue(i.count);
 		onCreatureAdd(ui->rCreatures, ui->rCreatureId, ui->rCreatureAmount);
@@ -527,7 +527,7 @@ void RewardsWidget::loadCurrentVisitInfo(int index)
 	}
 	for(auto & i : vinfo.limiter.creatures)
 	{
-		int index = i.type->getIndex();
+		int index = i.getType()->getIndex();
 		ui->lCreatureId->setCurrentIndex(index);
 		ui->lCreatureAmount->setValue(i.count);
 		onCreatureAdd(ui->lCreatures, ui->lCreatureId, ui->lCreatureAmount);

+ 6 - 6
server/CGameHandler.cpp

@@ -1139,7 +1139,7 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance
 	//first we move creatures to give to make them army of object-source
 	for (auto & elem : creatures.Slots())
 	{
-		addToSlot(StackLocation(obj, obj->getSlotFor(elem.second->type)), elem.second->type, elem.second->count);
+		addToSlot(StackLocation(obj, obj->getSlotFor(elem.second->getCreature())), elem.second->getCreature(), elem.second->count);
 	}
 
 	tryJoiningArmy(obj, h, remove, true);
@@ -1160,7 +1160,7 @@ void CGameHandler::takeCreatures(ObjectInstanceID objid, const std::vector<CStac
 			bool foundSth = false;
 			for (auto i = obj->Slots().begin(); i != obj->Slots().end(); i++)
 			{
-				if (i->second->type == sbd.type)
+				if (i->second->getType() == sbd.getType())
 				{
 					TQuantity take = std::min(sbd.count - collected, i->second->count); //collect as much cres as we can
 					changeStackCount(StackLocation(obj, i->first), -take, false);
@@ -2455,7 +2455,7 @@ void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst
 		auto i = src->Slots().begin(); //iterator to stack to move
 		StackLocation sl(src, i->first); //location of stack to move
 
-		SlotID pos = dst->getSlotFor(i->second->type);
+		SlotID pos = dst->getSlotFor(i->second->getCreature());
 		if (!pos.validSlot())
 		{
 			//try to merge two other stacks to make place
@@ -3137,7 +3137,7 @@ bool CGameHandler::sellCreatures(ui32 count, const IMarket *market, const CGHero
 
 	int b1; //base quantities for trade
 	int b2;
-	market->getOffer(s.type->getId(), resourceID, b1, b2, EMarketMode::CREATURE_RESOURCE);
+	market->getOffer(s.getId(), resourceID, b1, b2, EMarketMode::CREATURE_RESOURCE);
 	int units = count / b1; //how many base quantities we trade
 
 	if (count%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
@@ -3648,7 +3648,7 @@ bool CGameHandler::sacrificeCreatures(const IMarket * market, const CGHeroInstan
 			COMPLAIN_RET("Cannot sacrifice last creature!");
 		}
 
-		int crid = hero->getStack(slot[i]).type->getId();
+		int crid = hero->getStack(slot[i]).getId();
 
 		changeStackCount(StackLocation(hero, slot[i]), -(TQuantity)count[i]);
 
@@ -3801,7 +3801,7 @@ void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstanc
 			{
 				for (auto i = src->stacks.begin(); i != src->stacks.end(); i++)//while there are unmoved creatures
 				{
-					SlotID pos = dst->getSlotFor(i->second->type);
+					SlotID pos = dst->getSlotFor(i->second->getCreature());
 					if (pos.validSlot())
 					{
 						moveStack(StackLocation(src, i->first), StackLocation(dst, pos));

+ 2 - 2
server/battles/BattleResultProcessor.cpp

@@ -556,12 +556,12 @@ void BattleResultProcessor::battleAfterLevelUp(const BattleID & battleID, const
 	const CStackBasicDescriptor raisedStack = finishingBattle->winnerHero ? finishingBattle->winnerHero->calculateNecromancy(result) : CStackBasicDescriptor();
 	// Give raised units to winner and show dialog, if any were raised,
 	// units will be given after casualties are taken
-	const SlotID necroSlot = raisedStack.type ? finishingBattle->winnerHero->getSlotFor(raisedStack.type) : SlotID();
+	const SlotID necroSlot = raisedStack.getCreature() ? finishingBattle->winnerHero->getSlotFor(raisedStack.getCreature()) : SlotID();
 
 	if (necroSlot != SlotID() && !finishingBattle->isDraw())
 	{
 		finishingBattle->winnerHero->showNecromancyDialog(raisedStack, gameHandler->getRandomGenerator());
-		gameHandler->addToSlot(StackLocation(finishingBattle->winnerHero, necroSlot), raisedStack.type, raisedStack.count);
+		gameHandler->addToSlot(StackLocation(finishingBattle->winnerHero, necroSlot), raisedStack.getCreature(), raisedStack.count);
 	}
 
 	BattleResultsApplied resultsApplied;

+ 1 - 1
server/processors/NewTurnProcessor.cpp

@@ -345,7 +345,7 @@ void NewTurnProcessor::updateNeutralTownGarrison(const CGTownInstance * t, int c
 	// Check if town garrison already has unit of specified tier
 	for(const auto & slot : t->Slots())
 	{
-		const auto * creature = slot.second->type;
+		const auto * creature = slot.second->getCreature();
 
 		if (creature->getFactionID() != t->getFactionID())
 			continue;