2
0
Ivan Savenko 6 сар өмнө
parent
commit
912c2eae94

+ 1 - 1
AI/Nullkiller/AIGateway.cpp

@@ -1332,7 +1332,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
 		{
 			auto tile = cb->getTile(coord, false);
 			assert(tile);
-			return cb->getObj(tile->topVisitableObj(ignoreHero));
+			return cb->getObj(tile->topVisitableObj(ignoreHero), false);
 		};
 
 		auto isTeleportAction = [&](EPathNodeAction action) -> bool

+ 1 - 0
AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp

@@ -214,6 +214,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
 			CRandomGenerator rng;
 			auto visitablePos = town->visitablePos();
 			
+			townHero->id = town->id;
 			townHero->setOwner(ai->playerID); // lets avoid having multiple colors
 			townHero->initHero(rng, static_cast<HeroTypeID>(0));
 			townHero->pos = townHero->convertFromVisitablePos(visitablePos);

+ 2 - 2
AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp

@@ -31,8 +31,8 @@ namespace AIPathfinding
 
 	bool QuestAction::canAct(const Nullkiller * ai, const CGHeroInstance * hero) const
 	{
-		auto object = questInfo.getObject(cb);
-		auto quest = questInfo.getQuest(cb);
+		auto object = questInfo.getObject(ai->cb.get());
+		auto quest = questInfo.getQuest(ai->cb.get());
 		if(object->ID == Obj::BORDER_GATE || object->ID == Obj::BORDERGUARD)
 		{
 			return dynamic_cast<const IQuestObject *>(object)->checkQuest(hero);

+ 3 - 1
client/Client.cpp

@@ -371,8 +371,10 @@ int CClient::sendRequest(const CPackForServer & request, PlayerColor player)
 	return requestID;
 }
 
-void CClient::battleStarted(const BattleInfo * info)
+void CClient::battleStarted(const BattleID & battleID)
 {
+	const BattleInfo * info = gameState()->getBattle(battleID);
+
 	std::shared_ptr<CPlayerInterface> att;
 	std::shared_ptr<CPlayerInterface> def;
 	const auto & leftSide = info->getSide(BattleSide::LEFT_SIDE);

+ 1 - 1
client/Client.h

@@ -164,7 +164,7 @@ public:
 	void handlePack(CPackForClient & pack); //applies the given pack and deletes it
 	int sendRequest(const CPackForServer & request, PlayerColor player); //returns ID given to that request
 
-	void battleStarted(const BattleInfo * info);
+	void battleStarted(const BattleID & battle);
 	void battleFinished(const BattleID & battleID);
 	void startPlayerBattleAction(const BattleID & battleID, PlayerColor color);
 

+ 1 - 1
client/NetPacksClient.cpp

@@ -754,7 +754,7 @@ void ApplyFirstClientNetPackVisitor::visitBattleStart(BattleStart & pack)
 
 void ApplyClientNetPackVisitor::visitBattleStart(BattleStart & pack)
 {
-	cl.battleStarted(pack.info.get());
+	cl.battleStarted(pack.battleID);
 }
 
 void ApplyFirstClientNetPackVisitor::visitBattleNextRound(BattleNextRound & pack)

+ 1 - 0
lib/CCreatureSet.cpp

@@ -516,6 +516,7 @@ void CCreatureSet::putStack(const SlotID & slot, std::unique_ptr<CStackInstance>
 {
 	assert(slot.getNum() < GameConstants::ARMY_SIZE);
 	assert(!hasStackAtSlot(slot));
+
 	stacks[slot] = std::move(stack);
 	stacks[slot]->setArmy(getArmy());
 	armyChanged();

+ 3 - 11
lib/CGameInfoCallback.cpp

@@ -443,16 +443,6 @@ bool CGameInfoCallback::isVisible(const CGObjectInstance *obj) const
 {
 	return isVisible(obj, getPlayerID());
 }
-// const CCreatureSet* CInfoCallback::getGarrison(const CGObjectInstance *obj) const
-// {
-// 	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
-// 	if()
-// 	const CArmedInstance *armi = dynamic_cast<const CArmedInstance*>(obj);
-// 	if(!armi)
-// 		return nullptr;
-// 	else
-// 		return armi;
-// }
 
 std::vector <const CGObjectInstance *> CGameInfoCallback::getBlockingObjs( int3 pos ) const
 {
@@ -473,7 +463,9 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getVisitableObjs(int3
 
 	for(const auto & objID : t->visitableObjects)
 	{
-		const auto & object = getObj(objID);
+		const auto & object = getObj(objID, false);
+		if (!object)
+			continue; // event - visitable, but not visible
 
 		if(!getPlayerID().has_value() || object->ID != Obj::EVENT) //hide events from players
 			ret.push_back(object);

+ 9 - 12
lib/gameState/CGameState.cpp

@@ -577,7 +577,6 @@ void CGameState::removeHeroPlaceholders()
 	for(auto obj : map->getObjects<CGHeroPlaceholder>())
 	{
 		map->removeBlockVisTiles(obj, true);
-		map->instanceNames.erase(obj->instanceName);
 		map->eraseObject(obj->id);
 	}
 }
@@ -623,20 +622,18 @@ void CGameState::initHeroes()
 
 	for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool
 	{
-		auto vhi = map->tryTakeFromHeroPool(htype);
+		CGHeroInstance * heroInPool = map->tryGetFromHeroPool(htype);
 
-		if (vhi)
+		// some heroes are created as part of map loading (sod+ h3m maps)
+		// instances for h3 heroes from roe/ab h3m maps and heroes from mods at this point don't exist -> create them
+		if (!heroInPool)
 		{
-			vhi->initHero(getRandomGenerator());
+			auto newHeroPtr = std::make_shared<CGHeroInstance>(cb);
+			newHeroPtr->subID = htype.getNum();
+			map->addToHeroPool(newHeroPtr);
+			heroInPool = newHeroPtr.get();
 		}
-		else
-		{
-			vhi = std::make_shared<CGHeroInstance>(cb);
-			vhi->initHero(getRandomGenerator(), htype);
-		}
-
-		map->addToHeroPool(vhi);
-		heroesPool->addHeroToPool(vhi->getHeroTypeID());
+		heroInPool->initHero(getRandomGenerator());
 	}
 
 	for(auto & elem : map->disposedHeroes)

+ 3 - 6
lib/mapObjects/CArmedInstance.cpp

@@ -155,13 +155,12 @@ CBonusSystemNode & CArmedInstance::whatShouldBeAttached()
 
 void CArmedInstance::attachToBonusSystem(CGameState * gs)
 {
-	CArmedInstance::restoreBonusSystem(gs);
+	whatShouldBeAttached().attachTo(whereShouldBeAttached(gs));
 }
 
 void CArmedInstance::restoreBonusSystem(CGameState * gs)
 {
 	whatShouldBeAttached().attachTo(whereShouldBeAttached(gs));
-
 	for(const auto & elem : stacks)
 		elem.second->artDeserializationFix(gs, elem.second.get());
 }
@@ -169,14 +168,12 @@ void CArmedInstance::restoreBonusSystem(CGameState * gs)
 void CArmedInstance::detachFromBonusSystem(CGameState * gs)
 {
 	whatShouldBeAttached().detachFrom(whereShouldBeAttached(gs));
-
-// TODO: the opposite
-//	for(const auto & elem : stacks)
-//		elem.second->artDeserializationFix(elem.second.get());
 }
 
 void CArmedInstance::attachUnitsToArmy()
 {
+	assert(getArmy() != nullptr);
+
 	for(const auto & elem : stacks)
 		elem.second->attachTo(*getArmy());
 }

+ 14 - 5
lib/mapObjects/CGHeroInstance.cpp

@@ -1317,10 +1317,19 @@ CGBoat * CGHeroInstance::getBoat()
 
 void CGHeroInstance::setBoat(CGBoat* newBoat)
 {
-	assert(newBoat);
-	boardedBoat = newBoat->id;
-	attachTo(*newBoat);
-	newBoat->setBoardedHero(this);
+	if (newBoat)
+	{
+		boardedBoat = newBoat->id;
+		attachTo(*newBoat);
+		newBoat->setBoardedHero(this);
+	}
+	else if (boardedBoat.hasValue())
+	{
+		auto oldBoat = getBoat();
+		boardedBoat = {};
+		detachFrom(*oldBoat);
+		oldBoat->setBoardedHero(nullptr);
+	}
 }
 
 void CGHeroInstance::restoreBonusSystem(CGameState * gs)
@@ -1348,7 +1357,7 @@ void CGHeroInstance::attachToBonusSystem(CGameState * gs)
 
 void CGHeroInstance::detachFromBonusSystem(CGameState * gs)
 {
-	CArmedInstance::attachToBonusSystem(gs);
+	CArmedInstance::detachFromBonusSystem(gs);
 	if (boardedBoat.hasValue())
 	{
 		auto boat = gs->getObjInstance(boardedBoat);

+ 11 - 17
lib/mapObjects/CGTownInstance.cpp

@@ -769,20 +769,17 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
 	
 	if(h)
 	{
-		PlayerState *p = cb->gameState()->getPlayerState(h->tempOwner);
-		assert(p);
-		h->detachFrom(*p);
-		h->attachTo(townAndVis);
+		h->detachFromBonusSystem(cb->gameState());
 		h->setVisitedTown(this, false);
+		h->attachToBonusSystem(cb->gameState());
 		visitingHero = h->id;
 	}
-	else
+	else if (visitingHero.hasValue())
 	{
 		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
-		PlayerState *p = cb->gameState()->getPlayerState(getVisitingHero()->tempOwner);
+		oldVisitor->detachFromBonusSystem(cb->gameState());
 		oldVisitor->setVisitedTown(nullptr, false);
-		oldVisitor->detachFrom(townAndVis);
-		oldVisitor->attachTo(*p);
+		oldVisitor->attachToBonusSystem(cb->gameState());
 		visitingHero = {};
 	}
 }
@@ -794,20 +791,17 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
 	
 	if(h)
 	{
-		PlayerState *p = cb->gameState()->getPlayerState(h->tempOwner);
-		assert(p);
-		h->detachFrom(*p);
-		h->attachTo(*this);
+		h->detachFromBonusSystem(cb->gameState());
 		h->setVisitedTown(this, true);
+		h->attachToBonusSystem(cb->gameState());
 		garrisonHero = h->id;
 	}
-	else
+	else if (garrisonHero.hasValue())
 	{
-		PlayerState *p = cb->gameState()->getPlayerState(getGarrisonHero()->tempOwner);
-		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
+		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(garrisonHero));
+		oldVisitor->detachFromBonusSystem(cb->gameState());
 		oldVisitor->setVisitedTown(nullptr, false);
-		oldVisitor->detachFrom(*this);
-		oldVisitor->attachTo(*p);
+		oldVisitor->attachToBonusSystem(cb->gameState());
 		garrisonHero = {};
 	}
 	updateMoraleBonusFromArmy(); //avoid giving morale bonus for same army twice

+ 8 - 0
lib/mapping/CMap.cpp

@@ -581,6 +581,7 @@ std::shared_ptr<CGObjectInstance> CMap::eraseObject(ObjectInstanceID oldObjectID
 {
 	auto oldObject = objects.at(oldObjectID.getNum());
 
+	instanceNames.erase(oldObject->instanceName);
 	objects.at(oldObjectID) = nullptr;
 	removeBlockVisTiles(oldObject.get(), true);
 	oldObject->afterRemoveFromMap(this);
@@ -849,6 +850,13 @@ void CMap::addToHeroPool(std::shared_ptr<CGHeroInstance> hero)
 	assert(heroesPool.at(hero->getHeroTypeID().getNum()) == nullptr);
 
 	heroesPool.at(hero->getHeroTypeID().getNum()) = hero;
+
+	if (!hero->id.hasValue())
+	{
+		// reserve ID for this new hero, if needed (but don't actually add it since hero is not present on map)
+		hero->id = ObjectInstanceID(objects.size());
+		objects.push_back(nullptr);
+	}
 }
 
 CGHeroInstance * CMap::tryGetFromHeroPool(HeroTypeID hero)

+ 26 - 29
lib/mapping/MapFormatH3M.cpp

@@ -1104,7 +1104,7 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readPandora(const int3 & mapPos
 
 void CMapLoaderH3M::readBoxContent(CGPandoraBox * object, const int3 & mapPosition, const ObjectInstanceID & idToBeGiven)
 {
-	readMessageAndGuards(object->message, object, mapPosition);
+	readMessageAndGuards(object->message, object, mapPosition, idToBeGiven);
 	Rewardable::VisitInfo vinfo;
 	auto & reward = vinfo.reward;
 
@@ -1182,6 +1182,7 @@ void CMapLoaderH3M::readBoxHotaContent(CGPandoraBox * object, const int3 & mapPo
 std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readMonster(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
 {
 	auto object = std::make_shared<CGCreature>(map->cb);
+	object->id = objectInstanceID;
 
 	if(features.levelAB)
 	{
@@ -1369,12 +1370,12 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readScholar(const int3 & positi
 	return object;
 }
 
-std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readGarrison(const int3 & mapPosition)
+std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readGarrison(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven)
 {
 	auto object = std::make_shared<CGGarrison>(map->cb);
 
 	setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer32());
-	readCreatureSet(object.get(), 7);
+	readCreatureSet(object.get(), idToBeGiven);
 	if(features.levelAB)
 		object->removableUnits = reader->readBool();
 	else
@@ -1384,12 +1385,12 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readGarrison(const int3 & mapPo
 	return object;
 }
 
-std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
+std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate, const ObjectInstanceID & idToBeGiven)
 {
 	ArtifactID artID = ArtifactID::NONE; //random, set later
 	auto object = std::make_shared<CGArtifact>(map->cb);
 
-	readMessageAndGuards(object->message, object.get(), mapPosition);
+	readMessageAndGuards(object->message, object.get(), mapPosition, idToBeGiven);
 
 	//specific artifact
 	if(objectTemplate->id == Obj::ARTIFACT)
@@ -1410,21 +1411,21 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readArtifact(const int3 & mapPo
 	return object;
 }
 
-std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readScroll(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
+std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readScroll(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate, const ObjectInstanceID & idToBeGiven)
 {
 	auto object = std::make_shared<CGArtifact>(map->cb);
-	readMessageAndGuards(object->message, object.get(), mapPosition);
+	readMessageAndGuards(object->message, object.get(), mapPosition, idToBeGiven);
 	SpellID spellID = reader->readSpell32();
 
 	object->setArtifactInstance(map->createArtifact(ArtifactID::SPELL_SCROLL, spellID.getNum()));
 	return object;
 }
 
-std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readResource(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
+std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readResource(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate, const ObjectInstanceID & idToBeGiven)
 {
 	auto object = std::make_shared<CGResource>(map->cb);
 
-	readMessageAndGuards(object->message, object.get(), mapPosition);
+	readMessageAndGuards(object->message, object.get(), mapPosition, idToBeGiven);
 
 	object->amount = reader->readUInt32();
 
@@ -1798,7 +1799,7 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readObject(MapObjectID id, MapO
 
 		case Obj::GARRISON:
 		case Obj::GARRISON2:
-			return readGarrison(mapPosition);
+			return readGarrison(mapPosition, objectInstanceID);
 
 		case Obj::ARTIFACT:
 		case Obj::RANDOM_ART:
@@ -1806,16 +1807,16 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readObject(MapObjectID id, MapO
 		case Obj::RANDOM_MINOR_ART:
 		case Obj::RANDOM_MAJOR_ART:
 		case Obj::RANDOM_RELIC_ART:
-			return readArtifact(mapPosition, objectTemplate);
+			return readArtifact(mapPosition, objectTemplate, objectInstanceID);
 		case Obj::SPELL_SCROLL:
-			return readScroll(mapPosition, objectTemplate);
+			return readScroll(mapPosition, objectTemplate, objectInstanceID);
 
 		case Obj::RANDOM_RESOURCE:
 		case Obj::RESOURCE:
-			return readResource(mapPosition, objectTemplate);
+			return readResource(mapPosition, objectTemplate, objectInstanceID);
 		case Obj::RANDOM_TOWN:
 		case Obj::TOWN:
-			return readTown(mapPosition, objectTemplate);
+			return readTown(mapPosition, objectTemplate, objectInstanceID);
 
 		case Obj::MINE:
 		case Obj::ABANDONED_MINE:
@@ -1952,14 +1953,7 @@ void CMapLoaderH3M::readObjects()
 		if (newObject->isVisitable() && !map->isInTheMap(newObject->visitablePos()))
 			logGlobal->error("Map '%s': Object at %s - outside of map borders!", mapName, mapPosition.toString());
 
-		{
-			//TODO: define valid typeName and subtypeName for H3M maps
-			//boost::format fmt("%s_%d");
-			//fmt % nobj->typeName % nobj->id.getNum();
-			boost::format fmt("obj_%d");
-			fmt % newObject->id.getNum();
-			newObject->instanceName = fmt.str();
-		}
+		map->generateUniqueInstanceName(newObject.get());
 		map->addNewObject(newObject);
 		nextObjectID.num += 1;
 	}
@@ -1967,9 +1961,12 @@ void CMapLoaderH3M::readObjects()
 	map->postInitialize();
 }
 
-void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number)
+void CMapLoaderH3M::readCreatureSet(CArmedInstance * out, const ObjectInstanceID & idToBeGiven)
 {
-	for(int index = 0; index < number; ++index)
+	constexpr int unitsToRead = 7;
+	out->id = idToBeGiven;
+
+	for(int index = 0; index < unitsToRead; ++index)
 	{
 		CreatureID creatureID = reader->readCreature();
 		int count = reader->readUInt16();
@@ -2106,7 +2103,7 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readHero(const int3 & mapPositi
 
 	bool hasGarison = reader->readBool();
 	if(hasGarison)
-		readCreatureSet(object.get(), 7);
+		readCreatureSet(object.get(), objectInstanceID);
 
 	object->formation = static_cast<EArmyFormation>(reader->readInt8Checked(0, 1));
 	assert(object->formation == EArmyFormation::LOOSE || object->formation == EArmyFormation::TIGHT);
@@ -2494,7 +2491,7 @@ EQuestMission CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & positi
 	return missionId;
 }
 
-std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
+std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate, const ObjectInstanceID & idToBeGiven)
 {
 	auto object = std::make_shared<CGTownInstance>(map->cb);
 	if(features.levelAB)
@@ -2512,7 +2509,7 @@ std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readTown(const int3 & position,
 
 	bool hasGarrison = reader->readBool();
 	if(hasGarrison)
-		readCreatureSet(object.get(), 7);
+		readCreatureSet(object.get(), idToBeGiven);
 
 	object->formation = static_cast<EArmyFormation>(reader->readInt8Checked(0, 1));
 	assert(object->formation == EArmyFormation::LOOSE || object->formation == EArmyFormation::TIGHT);
@@ -2698,7 +2695,7 @@ void CMapLoaderH3M::readEvents()
 	}
 }
 
-void CMapLoaderH3M::readMessageAndGuards(MetaString & message, CCreatureSet * guards, const int3 & position)
+void CMapLoaderH3M::readMessageAndGuards(MetaString & message, CArmedInstance * guards, const int3 & position, const ObjectInstanceID & idToBeGiven)
 {
 	bool hasMessage = reader->readBool();
 	if(hasMessage)
@@ -2706,7 +2703,7 @@ void CMapLoaderH3M::readMessageAndGuards(MetaString & message, CCreatureSet * gu
 		message.appendTextID(readLocalizedString(TextIdentifier("guards", position.x, position.y, position.z, "message")));
 		bool hasGuards = reader->readBool();
 		if(hasGuards)
-			readCreatureSet(guards, 7);
+			readCreatureSet(guards, idToBeGiven);
 
 		reader->skipZero(4);
 	}

+ 8 - 7
lib/mapping/MapFormatH3M.h

@@ -20,6 +20,7 @@ class CGHeroInstance;
 class MapReaderH3M;
 class MetaString;
 class CArtifactInstance;
+class CArmedInstance;
 class CGObjectInstance;
 class CGSeerHut;
 class IQuestObject;
@@ -192,14 +193,14 @@ private:
 	std::shared_ptr<CGObjectInstance> readMonster(const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
 	std::shared_ptr<CGObjectInstance> readHero(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
 	std::shared_ptr<CGObjectInstance> readSeerHut(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
-	std::shared_ptr<CGObjectInstance> readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
+	std::shared_ptr<CGObjectInstance> readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl, const ObjectInstanceID & idToBeGiven);
 	std::shared_ptr<CGObjectInstance> readSign(const int3 & position);
 	std::shared_ptr<CGObjectInstance> readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
 	std::shared_ptr<CGObjectInstance> readScholar(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
-	std::shared_ptr<CGObjectInstance> readGarrison(const int3 & mapPosition);
-	std::shared_ptr<CGObjectInstance> readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
-	std::shared_ptr<CGObjectInstance> readScroll(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
-	std::shared_ptr<CGObjectInstance> readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
+	std::shared_ptr<CGObjectInstance> readGarrison(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven);
+	std::shared_ptr<CGObjectInstance> readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl, const ObjectInstanceID & idToBeGiven);
+	std::shared_ptr<CGObjectInstance> readScroll(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl, const ObjectInstanceID & idToBeGiven);
+	std::shared_ptr<CGObjectInstance> readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl, const ObjectInstanceID & idToBeGiven);
 	std::shared_ptr<CGObjectInstance> readMine(const int3 & position);
 	std::shared_ptr<CGObjectInstance> readAbandonedMine(const int3 & position);
 	std::shared_ptr<CGObjectInstance> readPandora(const int3 & position, const ObjectInstanceID & idToBeGiven);
@@ -225,7 +226,7 @@ private:
 	 * @param out the loaded creature set
 	 * @param number the count of creatures to read
 	 */
-	void readCreatureSet(CCreatureSet * out, int number);
+	void readCreatureSet(CArmedInstance * out, const ObjectInstanceID & idToBeGiven);
 
 	void readBoxContent(CGPandoraBox * object, const int3 & position, const ObjectInstanceID & idToBeGiven);
 	void readBoxHotaContent(CGPandoraBox * object, const int3 & position, const ObjectInstanceID & idToBeGiven);
@@ -249,7 +250,7 @@ private:
 	/**
 	* read optional message and optional guards
 	*/
-	void readMessageAndGuards(MetaString & message, CCreatureSet * guards, const int3 & position);
+	void readMessageAndGuards(MetaString & message, CArmedInstance * guards, const int3 & position, const ObjectInstanceID & idToBeGiven);
 
 	/// reads string from input stream and converts it to unicode
 	std::string readBasicString();

+ 1 - 5
lib/networkPacks/NetPacksLib.cpp

@@ -1246,7 +1246,7 @@ void RemoveObject::applyGs(CGameState *gs)
 		}
 	}
 
-	gs->getMap().instanceNames.erase(obj->instanceName);
+
 	gs->getMap().eraseObject(objectID);
 	gs->getMap().calculateGuardingGreaturePositions();//FIXME: excessive, update only affected tiles
 }
@@ -1322,17 +1322,13 @@ void TryMoveHero::applyGs(CGameState *gs)
 
 		gs->getMap().removeBlockVisTiles(boat); //hero blockvis mask will be used, we don't need to duplicate it with boat
 		h->setBoat(boat);
-		h->attachTo(*boat);
-		boat->setBoardedHero(h);
 	}
 	else if(result == DISEMBARK) //hero leaves boat to destination tile
 	{
 		auto * b = h->getBoat();
 		b->direction = h->moveDir;
 		b->pos = start;
-		b->setBoardedHero(nullptr);
 		gs->getMap().addBlockVisTiles(b);
-		h->detachFrom(*b);
 		h->setBoat(nullptr);
 	}
 

+ 1 - 0
server/CGameHandler.cpp

@@ -4263,6 +4263,7 @@ std::shared_ptr<CGObjectInstance> CGameHandler::createNewObject(const int3 & vis
 	auto o = handler->create(gameState()->cb, nullptr);
 	handler->configureObject(o.get(), getRandomGenerator());
 	assert(o->ID == objectID);
+	gameState()->getMap().generateUniqueInstanceName(o.get());
 
 	assert(!handler->getTemplates(terrainType).empty());
 	if (handler->getTemplates().empty())