Bläddra i källkod

* refactoring, a few intriguing problems remain

mateuszb 12 år sedan
förälder
incheckning
9e00090c42

+ 26 - 26
AI/VCAI/VCAI.cpp

@@ -656,7 +656,7 @@ void VCAI::tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos)
 			addVisitableObj(obj);
 }
 
-void VCAI::heroExchangeStarted(si32 hero1, si32 hero2)
+void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2)
 {
 	NET_EVENT_HANDLER;
 	LOG_ENTRY;
@@ -1541,7 +1541,7 @@ void VCAI::wander(HeroPtr h)
 		{
 			if(!dest)
 			{
-				BNLOG("Visit attempt made the object (id=%d) gone...", dest.id);
+				BNLOG("Visit attempt made the object (id=%d) gone...", dest.id.getNum());
 			}
 			else
 			{
@@ -1968,7 +1968,7 @@ void VCAI::tryRealize(CGoal g)
 		if(cb->getResourceAmount(static_cast<Res::ERes>(g.resID)) >= g.value)
 			throw cannotFulfillGoalException("Goal is already fulfilled!");
 
-		if(const CGObjectInstance *obj = cb->getObj(g.objid, false))
+		if(const CGObjectInstance *obj = cb->getObj(ObjectInstanceID(g.objid), false))
 		{
 			if(const IMarket *m = IMarket::castFrom(obj, false))
 			{
@@ -2069,7 +2069,7 @@ bool VCAI::fulfillsGoal (CGoal &goal, CGoal &mainGoal)
 {
 	if (mainGoal.goalType == GET_OBJ && goal.goalType == VISIT_TILE) //deduce that GET_OBJ was completed by visiting object's tile
 	{ //TODO: more universal mechanism
-		if (cb->getObj(mainGoal.objid)->visitablePos() == goal.tile)
+		if (cb->getObj(ObjectInstanceID(mainGoal.objid))->visitablePos() == goal.tile)
 			return true;
 	}
 	return false;
@@ -2078,7 +2078,7 @@ bool VCAI::fulfillsGoal (CGoal &goal, const CGoal &mainGoal)
 {
 	if (mainGoal.goalType == GET_OBJ && goal.goalType == VISIT_TILE) //deduce that GET_OBJ was completed by visiting object's tile
 	{ //TODO: more universal mechanism
-		if (cb->getObj(mainGoal.objid)->visitablePos() == goal.tile)
+		if (cb->getObj(ObjectInstanceID(mainGoal.objid))->visitablePos() == goal.tile)
 			return true;
 	}
 	return false;
@@ -2226,7 +2226,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 				{
 					if (q.quest->checkQuest(hero))
 					{
-						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
+						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id.getNum()).sethero(hero));
 						return;
 					}
 				}
@@ -2243,7 +2243,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 				{
 					if (q.quest->checkQuest(hero))
 					{
-						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
+						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id.getNum()).sethero(hero));
 						return;
 					}
 				}
@@ -2257,7 +2257,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 				{
 					if (q.quest->checkQuest(hero)) //veyr bad info - stacks can be split between multiple heroes :(
 					{
-						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
+						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id.getNum()).sethero(hero));
 						return;
 					}
 				}
@@ -2295,7 +2295,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 			{
 				auto obj = cb->getObjByQuestIdentifier(q.quest->m13489val);
 				if (obj)
-					striveToGoal (CGoal(GET_OBJ).setobjid(obj->id));
+					striveToGoal (CGoal(GET_OBJ).setobjid(obj->id.getNum()));
 				else
 					striveToGoal (CGoal(VISIT_TILE).settile(q.tile)); //visit seer hut
 				break;
@@ -2307,7 +2307,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 				{
 					if (q.quest->checkQuest(hero))
 					{
-						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
+						striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id.getNum()).sethero(hero));
 						return;
 					}
 				}
@@ -2772,9 +2772,9 @@ TSubgoal CGoal::whatToDoToAchieve()
 			case EVictoryConditionType::ARTIFACT:
                 return CGoal(GET_ART_TYPE).setaid(vc.objectId);
 			case EVictoryConditionType::BEATHERO:
-				return CGoal(GET_OBJ).setobjid(vc.obj->id);
+				return CGoal(GET_OBJ).setobjid(vc.obj->id.getNum());
 			case EVictoryConditionType::BEATMONSTER:
-				return CGoal(GET_OBJ).setobjid(vc.obj->id);
+				return CGoal(GET_OBJ).setobjid(vc.obj->id.getNum());
 			case EVictoryConditionType::BUILDCITY:
 				//TODO build castle/capitol
 				break;
@@ -2812,14 +2812,14 @@ TSubgoal CGoal::whatToDoToAchieve()
 					} //TODO: use FIND_OBJ
 					else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID<Obj::OBELISK>)) //there are unvisited Obelisks
 					{
-						return CGoal(GET_OBJ).setobjid(obj->id);
+						return CGoal(GET_OBJ).setobjid(obj->id.getNum());
 					}
 					else
 						return CGoal(EXPLORE);
 				}
 				break;
 			case EVictoryConditionType::CAPTURECITY:
-				return CGoal(GET_OBJ).setobjid(vc.obj->id);
+				return CGoal(GET_OBJ).setobjid(vc.obj->id.getNum());
 			case EVictoryConditionType::GATHERRESOURCE:
                 return CGoal(COLLECT_RES).setresID(static_cast<Res::ERes>(vc.objectId)).setvalue(vc.count);
 				//TODO mines? piles? marketplace?
@@ -2867,14 +2867,14 @@ TSubgoal CGoal::whatToDoToAchieve()
 				}
 			}
 			if (o && isReachable(o))
-				return CGoal(GET_OBJ).setobjid(o->id);
+				return CGoal(GET_OBJ).setobjid(o->id.getNum());
 			else
 				return CGoal(EXPLORE);
 		}
 		break;
 	case GET_OBJ:
 		{
-			const CGObjectInstance * obj = cb->getObj(objid);
+			const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(objid));
 			if(!obj)
 				return CGoal(EXPLORE);
 			int3 pos = obj->visitablePos();
@@ -2883,7 +2883,7 @@ TSubgoal CGoal::whatToDoToAchieve()
 		break;
 	case VISIT_HERO:
 		{
-			const CGObjectInstance * obj = cb->getObj(objid);
+			const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(objid));
 			if(!obj)
 				return CGoal(EXPLORE);
 			int3 pos = obj->visitablePos();
@@ -3189,8 +3189,8 @@ TSubgoal CGoal::whatToDoToAchieve()
 					auto backObj = backOrNull(cb->getVisitableObjs(m->o->visitablePos())); //it'll be a hero if we have one there; otherwise marketplace
 					assert(backObj);
 					if(backObj->tempOwner != ai->playerID)
-						return CGoal(GET_OBJ).setobjid(m->o->id);
-					return setobjid(m->o->id).setisElementar(true);
+						return CGoal(GET_OBJ).setobjid(m->o->id.getNum());
+					return setobjid(m->o->id.getNum()).setisElementar(true);
 				}
 			}
 		}
@@ -3238,7 +3238,7 @@ TSubgoal CGoal::whatToDoToAchieve()
 			if (dwellings.size())
 			{
 				boost::sort(dwellings, isCloser);
-				return CGoal(GET_OBJ).setobjid (dwellings.front()->id); //TODO: consider needed resources
+				return CGoal(GET_OBJ).setobjid (dwellings.front()->id.getNum()); //TODO: consider needed resources
 			}
 			else
 				return CGoal(EXPLORE);
@@ -3315,7 +3315,7 @@ TSubgoal CGoal::whatToDoToAchieve()
 					ai->reserveObject(h, obj); //no one else will capture same object until we fail
 
 					if (obj->ID == Obj::HERO)
-						return CGoal(VISIT_HERO).sethero(h).setobjid(obj->id).setisAbstract(true); //track enemy hero
+						return CGoal(VISIT_HERO).sethero(h).setobjid(obj->id.getNum()).setisAbstract(true); //track enemy hero
 					else
 						return CGoal(VISIT_TILE).sethero(h).settile(obj->visitablePos());
 				}
@@ -3375,9 +3375,9 @@ TSubgoal CGoal::whatToDoToAchieve()
 						secondaryPath = cb->getPathInfo(hero->visitablePos())->turns;
 
 						if (primaryPath < secondaryPath)
-							return CGoal(VISIT_HERO).setisAbstract(true).setobjid(h->id).sethero(hero); //go to the other hero if we are faster
+							return CGoal(VISIT_HERO).setisAbstract(true).setobjid(h->id.getNum()).sethero(hero); //go to the other hero if we are faster
 						else
-							return CGoal(VISIT_HERO).setisAbstract(true).setobjid(hero->id).sethero(h); //let the other hero come to us
+							return CGoal(VISIT_HERO).setisAbstract(true).setobjid(hero->id.getNum()).sethero(h); //let the other hero come to us
 					}
 				}
 
@@ -3426,7 +3426,7 @@ TSubgoal CGoal::whatToDoToAchieve()
 TSubgoal CGoal::goVisitOrLookFor(const CGObjectInstance *obj)
 {
 	if(obj)
-		return CGoal(GET_OBJ).setobjid(obj->id);
+		return CGoal(GET_OBJ).setobjid(obj->id.getNum());
 	else
 		return CGoal(EXPLORE);
 }
@@ -3901,7 +3901,7 @@ ObjectIdRef::operator const CGObjectInstance*() const
 	return cb->getObj(id, false);
 }
 
-ObjectIdRef::ObjectIdRef(int _id) : id(_id)
+ObjectIdRef::ObjectIdRef(ObjectInstanceID _id) : id(_id)
 {
 
 }
@@ -3935,7 +3935,7 @@ HeroPtr::HeroPtr(const CGHeroInstance *H)
 HeroPtr::HeroPtr()
 {
 	h = nullptr;
-	hid = -1;
+	hid = ObjectInstanceID();
 }
 
 HeroPtr::~HeroPtr()

+ 4 - 5
AI/VCAI/VCAI.h

@@ -29,7 +29,7 @@ typedef const std::string& crstring;
 struct HeroPtr
 {
 	const CGHeroInstance *h;
-	int hid; //hero id (object subID or type ID)
+	ObjectInstanceID hid;
 
 public:
 	std::string name;
@@ -138,7 +138,6 @@ struct CGoal
 		isElementar = false;
 		isAbstract = false;
 		value = 0;
-		objid = -1;
 		aid = -1;
 		resID = -1;
 		tile = int3(-1, -1, -1);
@@ -220,12 +219,12 @@ struct CIssueCommand : CGoal
 // This class stores object id, so we can detect when we lose access to the underlying object.
 struct ObjectIdRef
 {
-	int id;
+	ObjectInstanceID id;
 
 	const CGObjectInstance *operator->() const;
 	operator const CGObjectInstance *() const;
 
-	ObjectIdRef(int _id);
+	ObjectIdRef(ObjectInstanceID _id);
 	ObjectIdRef(const CGObjectInstance *obj);
 
 	bool operator<(const ObjectIdRef &rhs) const;
@@ -315,7 +314,7 @@ public:
 	virtual void availableArtifactsChanged(const CGBlackMarket *bm = NULL) OVERRIDE;
 	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) OVERRIDE;
 	virtual void tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos) OVERRIDE;
-	virtual void heroExchangeStarted(si32 hero1, si32 hero2) OVERRIDE;
+	virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2) OVERRIDE;
 	virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) OVERRIDE;
 	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) OVERRIDE;
 	virtual void heroMovePointsChanged(const CGHeroInstance * hero) OVERRIDE;

+ 1 - 1
CCallback.cpp

@@ -259,7 +259,7 @@ void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroIn
 	{
 		if(gs->players[*player].availableHeroes[i] == hero)
 		{
-			HireHero pack(i,townOrTavern->id);
+			HireHero pack(i, townOrTavern->id);
 			pack.player = *player;
 			sendRequest(&pack);
 			return;

+ 3 - 3
client/CCastleInterface.cpp

@@ -746,7 +746,7 @@ void CCastleBuildings::enterCastleGate()
 		if (t->id != this->town->id && t->visitingHero == NULL && //another town, empty and this is
 			t->hasBuilt(BuildingID::CASTLE_GATE, ETownType::INFERNO))
 		{
-			availableTowns.push_back(t->id);//add to the list
+			availableTowns.push_back(t->id.getNum());//add to the list
 		}
 	}
 	CPicture *titlePic = new CPicture (LOCPLINT->castleInt->bicons->ourImages[BuildingID::CASTLE_GATE].bitmap, 0,0, false);//will be deleted by selection window
@@ -909,7 +909,7 @@ void CCastleInterface::close()
 
 void CCastleInterface::castleTeleport(int where)
 {
-	const CGTownInstance * dest = LOCPLINT->cb->getTown(where);
+	const CGTownInstance * dest = LOCPLINT->cb->getTown(ObjectInstanceID(where));
 	LOCPLINT->cb->teleportHero(town->visitingHero, dest);
 }
 
@@ -1653,7 +1653,7 @@ void CMageGuildScreen::Scroll::hover(bool on)
 
 }
 
-CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, ArtifactID aid, int hid):
+CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, ArtifactID aid, ObjectInstanceID hid):
     CWindowObject(PLAYER_COLORED, "TPSMITH")
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;

+ 1 - 1
client/CCastleInterface.h

@@ -369,5 +369,5 @@ class CBlacksmithDialog : public CWindowObject
 	CGStatusBar *statusBar;
 
 public:
-	CBlacksmithDialog(bool possible, int creMachineID, ArtifactID aid, int hid);
+	CBlacksmithDialog(bool possible, CreatureID creMachineID, ArtifactID aid, ObjectInstanceID hid);
 };

+ 7 - 7
client/CPlayerInterface.cpp

@@ -200,22 +200,22 @@ void CPlayerInterface::yourTurn()
 	acceptTurn();
 }
 
-STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const SDL_Rect & r, const int & hid)
+STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const SDL_Rect & r, const ObjectInstanceID & hid)
 {
 	TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
 	for(int h=0; h<hlp.objects.size(); ++h)
-		if(hlp.objects[h].first->id==hid)
+		if(hlp.objects[h].first->id == hid)
 		{
 			hlp.objects[h].second = r;
 			return;
 		}
 }
 
-STRONG_INLINE void delObjRect(const int & x, const int & y, const int & z, const int & hid)
+STRONG_INLINE void delObjRect(const int & x, const int & y, const int & z, const ObjectInstanceID & hid)
 {
 	TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
 	for(int h=0; h<hlp.objects.size(); ++h)
-		if(hlp.objects[h].first->id==hid)
+		if(hlp.objects[h].first->id == hid)
 		{
 			hlp.objects.erase(hlp.objects.begin()+h);
 			return;
@@ -1156,7 +1156,7 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
 	h & sleepingSize;
 	for (int i = 0; i < sleepingSize; i++)
 	{
-		si32 hid;
+		ObjectInstanceID hid;
 		if (h.saving)
 			hid = sleepingHeroes[i]->id;
 		h &	hid;
@@ -1176,7 +1176,7 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
 	h & heroListSize;
 	for (int i = 0; i < heroListSize; i++)
 	{
-		si32 hid;
+		ObjectInstanceID hid;
 		if (h.saving)
 			hid = wanderingHeroes[i]->id;
 		h & hid;
@@ -1381,7 +1381,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
 		stillMoveHero.setn(CONTINUE_MOVE);
 }
 
-void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2)
+void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	GH.pushInt(new CExchangeWindow(hero1, hero2));

+ 1 - 1
client/CPlayerInterface.h

@@ -175,7 +175,7 @@ public:
 	void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) OVERRIDE;//if gain hero received bonus, else he lost it
 	void playerBonusChanged(const Bonus &bonus, bool gain) OVERRIDE;
 	void requestRealized(PackageApplied *pa) OVERRIDE;
-	void heroExchangeStarted(si32 hero1, si32 hero2) OVERRIDE;
+	void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2) OVERRIDE;
 	void centerView (int3 pos, int focusTime) OVERRIDE;
 	void objectPropertyChanged(const SetObjectProperty * sop) OVERRIDE;
 	void objectRemoved(const CGObjectInstance *obj) OVERRIDE;

+ 2 - 2
client/CSpellWindow.cpp

@@ -586,7 +586,7 @@ Uint8 CSpellWindow::pagesWithinCurrentTab()
 
 void CSpellWindow::teleportTo( int town, const CGHeroInstance * hero )
 {
-	const CGTownInstance * dest = LOCPLINT->cb->getTown(town);
+	const CGTownInstance * dest = LOCPLINT->cb->getTown(ObjectInstanceID(town));
 	LOCPLINT->cb->castSpell(hero, SpellID::TOWN_PORTAL, dest->visitablePos());
 }
 
@@ -761,7 +761,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 							const CGTownInstance *t = Towns[i];
 							if (t->visitingHero == NULL) //empty town and this is
 							{
-								availableTowns.push_back(t->id);//add to the list
+								availableTowns.push_back(t->id.getNum());//add to the list
 							}
 						}
 						if (availableTowns.empty())

+ 10 - 10
client/Client.h

@@ -164,19 +164,19 @@ public:
 	//not working yet, will be implement somewhen later with support for local-sim-based gameplay
 	void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells) OVERRIDE {};
 	bool removeObject(const CGObjectInstance * obj) OVERRIDE {return false;};
-	void setBlockVis(int objid, bool bv) OVERRIDE {};
+	void setBlockVis(ObjectInstanceID objid, bool bv) OVERRIDE {};
 	void setOwner(const CGObjectInstance * obj, TPlayerColor owner) OVERRIDE {};
 	void setHoverName(const CGObjectInstance * obj, MetaString * name) OVERRIDE {};
 	void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) OVERRIDE {};
 	void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) OVERRIDE {}; 
 	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE {};
 	ui32 showBlockingDialog(BlockingDialog *iw) OVERRIDE {return 0;}; //synchronous version of above
-	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE {};
-	void showThievesGuildWindow(TPlayerColor player, int requestingObjId) OVERRIDE {};
+	void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE {};
+	void showThievesGuildWindow(TPlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE {};
 	void giveResource(TPlayerColor player, Res::ERes which, int val) OVERRIDE {};
 
 	void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE {};
-	void takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE {};
+	void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE {};
 	bool changeStackType(const StackLocation &sl, CCreature *c) OVERRIDE {return false;};
 	bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) OVERRIDE {return false;};
 	bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE {return false;};
@@ -200,15 +200,15 @@ public:
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL) OVERRIDE {}; //use hero=NULL for no hero
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
-	void setAmount(int objid, ui32 val) OVERRIDE {};
-	bool moveHero(si32 hid, int3 dst, ui8 instant, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER) OVERRIDE {return false;};
+	void setAmount(ObjectInstanceID objid, ui32 val) OVERRIDE {};
+	bool moveHero(ObjectInstanceID hid, int3 dst, ui8 instant, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER) OVERRIDE {return false;};
 	void giveHeroBonus(GiveBonus * bonus) OVERRIDE {};
 	void setMovePoints(SetMovePoints * smp) OVERRIDE {};
-	void setManaPoints(int hid, int val) OVERRIDE {};
-	void giveHero(int id, TPlayerColor player) OVERRIDE {};
-	void changeObjPos(int objid, int3 newPos, ui8 flags) OVERRIDE {};
+	void setManaPoints(ObjectInstanceID hid, int val) OVERRIDE {};
+	void giveHero(ObjectInstanceID id, TPlayerColor player) OVERRIDE {};
+	void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags) OVERRIDE {};
 	void sendAndApply(CPackForClient * info) OVERRIDE {};
-	void heroExchange(si32 hero1, si32 hero2) OVERRIDE {};
+	void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) OVERRIDE {};
 
 	//////////////////////////////////////////////////////////////////////////
 	friend class CCallback; //handling players actions

+ 2 - 2
client/GUIClasses.cpp

@@ -2710,7 +2710,7 @@ void CMarketplaceWindow::makeDeal()
 			leftIdToSend = hLeft->serial;
 			break;
 		case EMarketMode::ARTIFACT_RESOURCE:
-			leftIdToSend = hLeft->getArtInstance()->id;
+			leftIdToSend = hLeft->getArtInstance()->id.getNum();
 			break;
 		default:
 			leftIdToSend = hLeft->id;
@@ -5071,7 +5071,7 @@ void CExchangeWindow::prepareBackground()
 	new CAnimImage("PortraitsLarge", heroInst[1]->portrait, 0, 485, 13);
 }
 
-CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2):
+CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2):
     CWindowObject(PLAYER_COLORED | BORDERED, "TRADE2")
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;

+ 1 - 1
client/GUIClasses.h

@@ -1034,7 +1034,7 @@ public:
 
 	void prepareBackground(); //prepares or redraws bg
 
-	CExchangeWindow(si32 hero1, si32 hero2); //c-tor
+	CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2); //c-tor
 	~CExchangeWindow(); //d-tor
 };
 

+ 23 - 23
client/NetPacksClient.cpp

@@ -111,7 +111,7 @@ void SetPrimSkill::applyCl( CClient *cl )
 	const CGHeroInstance *h = cl->getHero(id);
 	if(!h)
 	{
-		tlog1 << "Cannot find hero with ID " << id << std::endl;
+		tlog1 << "Cannot find hero with ID " << id.getNum() << std::endl;
 		return;
 	}
 	INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroPrimarySkillChanged,h,which,val);
@@ -255,7 +255,7 @@ void GiveBonus::applyCl( CClient *cl )
 	{
 	case HERO:
 		{
-			const CGHeroInstance *h = GS(cl)->getHero(id);
+			const CGHeroInstance *h = GS(cl)->getHero(ObjectInstanceID(id));
 			INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, *h->getBonusList().back(),true);
 		}
 		break;
@@ -270,13 +270,13 @@ void GiveBonus::applyCl( CClient *cl )
 
 void ChangeObjPos::applyFirstCl( CClient *cl )
 {
-	CGObjectInstance *obj = GS(cl)->map->objects[objid];
+	CGObjectInstance *obj = GS(cl)->getObjInstance(objid);
 	if(flags & 1)
 		CGI->mh->hideObject(obj);
 }
 void ChangeObjPos::applyCl( CClient *cl )
 {
-	CGObjectInstance *obj = GS(cl)->map->objects[objid];
+	CGObjectInstance *obj = GS(cl)->getObjInstance(objid);
 	if(flags & 1)
 		CGI->mh->printObject(obj);
 
@@ -295,7 +295,7 @@ void RemoveBonus::applyCl( CClient *cl )
 	{
 	case HERO:
 		{
-			const CGHeroInstance *h = GS(cl)->getHero(id);
+			const CGHeroInstance *h = GS(cl)->getHero(ObjectInstanceID(id));
 			INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, bonus,false);
 		}
 		break;
@@ -527,9 +527,9 @@ void InfoWindow::applyCl( CClient *cl )
 void SetObjectProperty::applyCl( CClient *cl )
 {
 	//inform all players that see this object
-	for(std::map<ui8,CGameInterface *>::const_iterator it = cl->playerint.begin(); it != cl->playerint.end(); ++it)
+	for(auto it = cl->playerint.cbegin(); it != cl->playerint.cend(); ++it)
 	{
-		if(GS(cl)->isVisible(GS(cl)->map->objects[id], it->first))
+		if(GS(cl)->isVisible(GS(cl)->getObjInstance(id), it->first))
 			INTERFACE_CALL_IF_PRESENT(it->first, objectPropertyChanged, this);
 	}
 }
@@ -826,46 +826,46 @@ void OpenWindow::applyCl(CClient *cl)
 	{
 	case EXCHANGE_WINDOW:
 		{
-			const CGHeroInstance *h = cl->getHero(id1);
-			const CGObjectInstance *h2 = cl->getHero(id2);
+			const CGHeroInstance *h = cl->getHero(ObjectInstanceID(id1));
+			const CGObjectInstance *h2 = cl->getHero(ObjectInstanceID(id2));
 			assert(h && h2);
-			INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroExchangeStarted, id1, id2);
+			INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroExchangeStarted, ObjectInstanceID(id1), ObjectInstanceID(id2));
 		}
 		break;
 	case RECRUITMENT_FIRST:
 	case RECRUITMENT_ALL:
 		{
-			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl->getObj(id1));
-			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl->getObj(id2));
+			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl->getObj(ObjectInstanceID(id1)));
+			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl->getObj(ObjectInstanceID(id2)));
 			INTERFACE_CALL_IF_PRESENT(dst->tempOwner,showRecruitmentDialog, dw, dst, window == RECRUITMENT_FIRST ? 0 : -1);
 		}
 		break;
 	case SHIPYARD_WINDOW:
 		{
-			const IShipyard *sy = IShipyard::castFrom(cl->getObj(id1));
+			const IShipyard *sy = IShipyard::castFrom(cl->getObj(ObjectInstanceID(id1)));
 			INTERFACE_CALL_IF_PRESENT(sy->o->tempOwner, showShipyardDialog, sy);
 		}
 		break;
 	case THIEVES_GUILD:
 		{
 			//displays Thieves' Guild window (when hero enters Den of Thieves)
-			const CGObjectInstance *obj = cl->getObj(id2);
+			const CGObjectInstance *obj = cl->getObj(ObjectInstanceID(id2));
 			INTERFACE_CALL_IF_PRESENT(id1, showThievesGuildWindow, obj);
 		}
 		break;
 	case UNIVERSITY_WINDOW:
 		{
 			//displays University window (when hero enters University on adventure map)
-			const IMarket *market = IMarket::castFrom(cl->getObj(id1));
-			const CGHeroInstance *hero = cl->getHero(id2);
+			const IMarket *market = IMarket::castFrom(cl->getObj(ObjectInstanceID(id1)));
+			const CGHeroInstance *hero = cl->getHero(ObjectInstanceID(id2));
 			INTERFACE_CALL_IF_PRESENT(hero->tempOwner,showUniversityWindow, market, hero);
 		}
 		break;
 	case MARKET_WINDOW:
 		{
 			//displays Thieves' Guild window (when hero enters Den of Thieves)
-			const CGObjectInstance *obj = cl->getObj(id1);
-			const CGHeroInstance *hero = cl->getHero(id2);
+			const CGObjectInstance *obj = cl->getObj(ObjectInstanceID(id1));
+			const CGHeroInstance *hero = cl->getHero(ObjectInstanceID(id2));
 			const IMarket *market = IMarket::castFrom(obj);
 			INTERFACE_CALL_IF_PRESENT(cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, showMarketWindow, market, hero);
 		}
@@ -873,8 +873,8 @@ void OpenWindow::applyCl(CClient *cl)
 	case HILL_FORT_WINDOW:
 		{
 			//displays Hill fort window
-			const CGObjectInstance *obj = cl->getObj(id1);
-			const CGHeroInstance *hero = cl->getHero(id2);
+			const CGObjectInstance *obj = cl->getObj(ObjectInstanceID(id1));
+			const CGHeroInstance *hero = cl->getHero(ObjectInstanceID(id2));
 			INTERFACE_CALL_IF_PRESENT(cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, showHillFortWindow, obj, hero);
 		}
 		break;
@@ -884,8 +884,8 @@ void OpenWindow::applyCl(CClient *cl)
 		}
 		break;
 	case TAVERN_WINDOW:
-		const CGObjectInstance *obj1 = cl->getObj(id1),
-								*obj2 = cl->getObj(id2);
+		const CGObjectInstance *obj1 = cl->getObj(ObjectInstanceID(id1)),
+								*obj2 = cl->getObj(ObjectInstanceID(id2));
 		INTERFACE_CALL_IF_PRESENT(obj1->tempOwner, showTavernWindow, obj2);
 		break;
 	}
@@ -920,7 +920,7 @@ void SetAvailableArtifacts::applyCl(CClient *cl)
 	}
 	else
 	{
-		const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(cl->getObj(id));
+		const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(cl->getObj(ObjectInstanceID(id)));
 		assert(bm);
 		INTERFACE_CALL_IF_PRESENT(cl->getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, availableArtifactsChanged, bm);
 	}

+ 1 - 1
lib/BattleState.cpp

@@ -1119,7 +1119,7 @@ std::string CStack::nodeName() const
 
 	oss << " from slot " << (int)slot;
 	if(base && base->armyObj)
-		oss << " of armyobj=" << base->armyObj->id;
+		oss << " of armyobj=" << base->armyObj->id.getNum();
 	return oss.str();
 }
 

+ 3 - 3
lib/CArtHandler.cpp

@@ -561,7 +561,7 @@ ArtifactID CArtHandler::getRandomArt(int flags)
 }
 ArtifactID CArtHandler::getArtSync (ui32 rand, int flags, bool erasePicked)
 {
-	auto erasePickedArt = [&]( TArtifactInstanceID id )
+	auto erasePickedArt = [&]( ArtifactID id )
 	{
 		std::vector<CArtifact*>* ptr;
 		CArtifact *art = artifacts[id];
@@ -867,7 +867,7 @@ CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s)
 
 void CArtifactInstance::init()
 {
-	id = -1;
+	id = ArtifactInstanceID();
 	setNodeType(ARTIFACT_INSTANCE);
 }
 
@@ -1260,7 +1260,7 @@ ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const
 	return ArtifactPosition::PRE_FIRST;
 }
 
-const CArtifactInstance * CArtifactSet::getArtByInstanceId( TArtifactInstanceID artInstId ) const
+const CArtifactInstance * CArtifactSet::getArtByInstanceId( ArtifactInstanceID artInstId ) const
 {
 	BOOST_FOREACH(auto i, artifactsWorn)
 		if(i.second.artifact->id == artInstId)

+ 2 - 3
lib/CArtHandler.h

@@ -110,7 +110,7 @@ public:
 	CArtifactInstance();
 
 	ConstTransitivePtr<CArtifact> artType;
-	TArtifactInstanceID id;
+	ArtifactInstanceID id;
 
 	//CArtifactInstance(int aid);
 
@@ -217,7 +217,6 @@ public:
 	bool legalArtifact(ArtifactID id);
 	void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
 	void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
-	void erasePickedArt (TArtifactInstanceID id);
 	bool isBigArtifact (ArtifactID artID) const {return bigArtifacts.find(artID) != bigArtifacts.end();}
 	void initAllowedArtifactsList(const std::vector<bool> &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed
 	static ArtifactID creatureToMachineID(CreatureID id);
@@ -274,7 +273,7 @@ public:
 	CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true); //NULL - no artifact
 	ArtifactPosition getArtPos(int aid, bool onlyWorn = true) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
 	ArtifactPosition getArtPos(const CArtifactInstance *art) const;
-	const CArtifactInstance *getArtByInstanceId(TArtifactInstanceID artInstId) const;
+	const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
 	bool hasArt(ui32 aid, bool onlyWorn = false) const; //checks if hero possess artifact of given id (either in backack or worn)
 	bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;
 	si32 getArtTypeId(ArtifactPosition pos) const;

+ 2 - 2
lib/CBattleCallback.cpp

@@ -467,7 +467,7 @@ std::set<BattleHex> CBattleInfoCallback::battleGetAttackedHexes(const CStack* at
 	return attackedHexes;
 }
 
-si32 CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const
+SpellID CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const
 {
 	switch (mode)
 	{
@@ -479,7 +479,7 @@ si32 CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERando
 		break;
 	default:
 		tlog1 << "Incorrect mode of battleGetRandomSpell (" << mode <<")\n";
-		return -1;
+		return SpellID::NONE;
 	}
 }
 

+ 1 - 1
lib/CBattleCallback.h

@@ -259,7 +259,7 @@ public:
 	ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
 	std::set<const CStack*> getAffectedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, BattleHex destinationTile); //calculates stack affected by given spell
 
-	si32 battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
+	SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
 	SpellID getRandomBeneficialSpell(const CStack * subject) const;
 	SpellID getRandomCastedSpell(const CStack * caster) const; //called at the beginning of turn for Faerie Dragon
 

+ 12 - 10
lib/CGameState.cpp

@@ -1083,7 +1083,7 @@ void CGameState::init(StartInfo * si)
 					it->second.hero = h;
 
 				CGHeroInstance * nnn =  static_cast<CGHeroInstance*>(createObject(Obj::HERO,h,hpos,it->first));
-				nnn->id = map->objects.size();
+				nnn->id = ObjectInstanceID(map->objects.size());
 				nnn->initHero();
 				map->heroes.push_back(nnn);
 				map->objects.push_back(nnn);
@@ -1094,10 +1094,10 @@ void CGameState::init(StartInfo * si)
 
 	/*************************replace hero placeholders*****************************/
 	tlog4 << "\tReplacing hero placeholders";
-	std::vector<std::pair<CGHeroInstance*, int> > campHeroReplacements; //instance, id in vector
+	std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > campHeroReplacements; //instance, id in vector
 	if (scenarioOps->campState)
 	{
-		auto replaceHero = [&](int objId, CGHeroInstance * ghi)
+		auto replaceHero = [&](ObjectInstanceID objId, CGHeroInstance * ghi)
 		{
 			campHeroReplacements.push_back(std::make_pair(ghi, objId));
 // 			ghi->tempOwner = getHumanPlayerInfo()[0]->color;
@@ -1120,6 +1120,7 @@ void CGameState::init(StartInfo * si)
 			//selecting heroes by type
 			for(int g=0; g<map->objects.size(); ++g)
 			{
+				const ObjectInstanceID gid = ObjectInstanceID(g);
 				CGObjectInstance * obj = map->objects[g];
 				if (obj->ID != Obj::HERO_PLACEHOLDER)
 				{
@@ -1135,7 +1136,7 @@ void CGameState::init(StartInfo * si)
 						if (ghi->subID == hp->subID)
 						{
 							found = true;
-							replaceHero(g, ghi);
+							replaceHero(gid, ghi);
 							Xheroes -= ghi;
 							break;
 						}
@@ -1144,7 +1145,7 @@ void CGameState::init(StartInfo * si)
 					{
 						CGHeroInstance * nh = new CGHeroInstance();
 						nh->initHero(hp->subID);
-						replaceHero(g, nh);
+						replaceHero(gid, nh);
 					}
 				}
 			}
@@ -1158,6 +1159,7 @@ void CGameState::init(StartInfo * si)
 
 			for(int g=0; g<map->objects.size(); ++g)
 			{
+				const ObjectInstanceID gid = ObjectInstanceID(g);
 				CGObjectInstance * obj = map->objects[g];
 				if (obj->ID != Obj::HERO_PLACEHOLDER)
 				{
@@ -1168,7 +1170,7 @@ void CGameState::init(StartInfo * si)
 				if (hp->subID == 0xFF) //select by power
 				{
 					if(Xheroes.size() > hp->power - 1)
-						replaceHero(g, Xheroes[hp->power - 1]);
+						replaceHero(gid, Xheroes[hp->power - 1]);
 					else
 					{
 						tlog3 << "Warning, no hero to replace!\n";
@@ -1242,7 +1244,7 @@ void CGameState::init(StartInfo * si)
 	//Replace placeholders with heroes from previous missions
 	BOOST_FOREACH(auto obj, campHeroReplacements)
 	{
-		CGHeroPlaceholder *placeholder = dynamic_cast<CGHeroPlaceholder*>(&*map->objects[obj.second]);
+		CGHeroPlaceholder *placeholder = dynamic_cast<CGHeroPlaceholder*>(getObjInstance(obj.second));
 
 		CGHeroInstance *heroToPlace = obj.first;
 		heroToPlace->id = obj.second;
@@ -1257,7 +1259,7 @@ void CGameState::init(StartInfo * si)
 		{
 			art->artType = VLC->arth->artifacts[art->artType->id];
 			gs->map->artInstances.push_back(art);
-			art->id = gs->map->artInstances.size() - 1;
+			art->id = ArtifactInstanceID(gs->map->artInstances.size() - 1);
 		};
 
 		BOOST_FOREACH(auto &&i, heroToPlace->artifactsWorn)
@@ -1266,7 +1268,7 @@ void CGameState::init(StartInfo * si)
 			fixArtifact(i.artifact);
 
 		map->heroes.push_back(heroToPlace);
-		map->objects[heroToPlace->id] = heroToPlace;
+		map->objects[heroToPlace->id.getNum()] = heroToPlace;
 		map->addBlockVisTiles(heroToPlace);
 
 		//const auto & travelOptions = scenarioOps->campState->getCurrentScenario().travelOptions;
@@ -2270,7 +2272,7 @@ int CGameState::victoryCheck( ui8 player ) const
 			}
 			break;
 		case EVictoryConditionType::BEATMONSTER:
-			if(!map->objects[map->victoryCondition.obj->id]) //target monster not present on map
+			if(!getObj(map->victoryCondition.obj->id)) //target monster not present on map
 				return 1;
 			break;
 		case EVictoryConditionType::TAKEDWELLINGS:

+ 1 - 1
lib/CGameState.h

@@ -165,7 +165,7 @@ struct DLL_LINKAGE PlayerState : public CBonusSystemNode
 public:
 	TPlayerColor color;
 	bool human; //true if human controlled player, false for AI
-	ui32 currentSelection; //id of hero/town, 0xffffffff if none
+	ObjectInstanceID currentSelection; //id of hero/town, 0xffffffff if none
 	ui8 team;
 	TResources resources;
 	std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;

+ 74 - 73
lib/CObjectHandler.cpp

@@ -39,12 +39,12 @@ using namespace boost::assign;
 #define USE_COVERAGE_MAP 0
 
 
-std::map<int,std::map<int, std::vector<int> > > CGTeleport::objs;
-std::vector<std::pair<int, int> > CGTeleport::gates;
+std::map<int,std::map<int, std::vector<ObjectInstanceID> > > CGTeleport::objs;
+std::vector<std::pair<ObjectInstanceID, ObjectInstanceID> > CGTeleport::gates;
 IGameCallback * IObjectInterface::cb = NULL;
 extern boost::rand48 ran;
-std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
-std::map <si32, std::vector<si32> > CGMagi::eyelist;
+std::map <TPlayerColor, std::set <ui8> > CGKeys::playerKeyMap;
+std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist;
 ui8 CGObelisk::obeliskCount; //how many obelisks are on map
 std::map<ui8, ui8> CGObelisk::visited; //map: team_id => how many obelisks has been visited
 
@@ -52,7 +52,7 @@ std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
 std::vector<int> CGTownInstance::universitySkills;
 
 ///helpers
-static void openWindow(const OpenWindow::EWindow type, const ui32 id1, const ui32 id2 = 0)
+static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
 {
 	OpenWindow ow;
 	ow.window = type;
@@ -70,7 +70,7 @@ static void showInfoDialog(const TPlayerColor playerID, const ui32 txtID, const
 	IObjectInterface::cb->sendAndApply(&iw);
 }
 
-static void showInfoDialog(const int heroID, const ui32 txtID, const ui16 soundID)
+static void showInfoDialog(const ObjectInstanceID heroID, const ui32 txtID, const ui16 soundID)
 {
 	const TPlayerColor playerID = IObjectInterface::cb->getOwner(heroID);
 	showInfoDialog(playerID,txtID,soundID);
@@ -263,7 +263,7 @@ CGObjectInstance::CGObjectInstance(): animPhaseShift(rand()%0xff)
 	//std::cout << "Tworze obiekt "<<this<<std::endl;
 	//state = new CLuaObjectScript();
 	ID = Obj::NO_OBJ;
-	subID = id = -1;
+	subID = -1;
 	defInfo = NULL;
 	tempOwner = 254;
 	blockVisit = false;
@@ -299,7 +299,7 @@ bool CGObjectInstance::visitableAt(int x, int y) const //returns true if object
 {
 	if(defInfo==NULL)
 	{
-		tlog2 << "Warning: VisitableAt for obj "<<id<<": NULL defInfo!\n";
+		tlog2 << "Warning: VisitableAt for obj "<< id.getNum() <<": NULL defInfo!\n";
 		return false;
 	}
 
@@ -435,7 +435,7 @@ void CGObjectInstance::getSightTiles(boost::unordered_set<int3, ShashInt3> &tile
 {
 	cb->getTilesInRange(tiles, getSightCenter(), getSightRadious(), tempOwner, 1);
 }
-void CGObjectInstance::hideTiles(int ourplayer, int radius) const
+void CGObjectInstance::hideTiles(TPlayerColor ourplayer, int radius) const
 {
 	for (auto i = cb->gameState()->teams.begin(); i != cb->gameState()->teams.end(); i++)
 	{
@@ -476,11 +476,11 @@ void CGObjectInstance::getNameVis( std::string &hname ) const
 	}
 }
 
-void CGObjectInstance::giveDummyBonus(int heroID, ui8 duration) const
+void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) const
 {
 	GiveBonus gbonus;
 	gbonus.bonus.type = Bonus::NONE;
-	gbonus.id = heroID;
+	gbonus.id = heroID.getNum();
 	gbonus.bonus.duration = duration;
 	gbonus.bonus.source = Bonus::OBJECT;
 	gbonus.bonus.sid = ID;
@@ -493,7 +493,7 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
 	{
 	case Obj::HILL_FORT:
 		{
-			openWindow(OpenWindow::HILL_FORT_WINDOW,id,h->id);
+			openWindow(OpenWindow::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
 		}
 		break;
 	case Obj::SANCTUARY:
@@ -504,7 +504,7 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
 		break;
 	case Obj::TAVERN:
 		{
-			openWindow(OpenWindow::TAVERN_WINDOW,h->id,id);
+			openWindow(OpenWindow::TAVERN_WINDOW,h->id.getNum(),id.getNum());
 		}
 		break;
 	}
@@ -536,7 +536,7 @@ static int lowestSpeed(const CGHeroInstance * chi)
 {
 	if(!chi->Slots().size())
 	{
-		tlog1 << "Error! Hero " << chi->id << " ("<<chi->name<<") has no army!\n";
+		tlog1 << "Error! Hero " << chi->id.getNum() << " ("<<chi->name<<") has no army!\n";
 		return 20;
 	}
 	TSlots::const_iterator i = chi->Slots().begin();
@@ -949,7 +949,7 @@ void CGHeroInstance::initObj() //TODO: use bonus system
 	{
 		Bonus *bonus = new Bonus();
 		bonus->val = spec.val;
-		bonus->sid = id; //from the hero, specialty has no unique id
+		bonus->sid = id.getNum(); //from the hero, specialty has no unique id
 		bonus->duration = Bonus::PERMANENT;
 		bonus->source = Bonus::HERO_SPECIAL;
 		switch (spec.type)
@@ -1274,7 +1274,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
 	}
 	else
 	{
-		Bonus *bonus = new Bonus(Bonus::PERMANENT, Bonus::SECONDARY_SKILL_PREMY, Bonus::SECONDARY_SKILL, skillVal, id, which, skillValType);
+		Bonus *bonus = new Bonus(Bonus::PERMANENT, Bonus::SECONDARY_SKILL_PREMY, Bonus::SECONDARY_SKILL, skillVal, id.getNum(), which, skillValType);
 		bonus->source = Bonus::SECONDARY_SKILL;
 		addNewBonus(bonus);
 	}
@@ -1493,7 +1493,7 @@ int CGHeroInstance::getSpellCost(const CSpell *sp) const
 
 void CGHeroInstance::pushPrimSkill( PrimarySkill::PrimarySkill which, int val )
 {
-	addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id, which));
+	addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id.getNum(), which));
 }
 
 EAlignment::EAlignment CGHeroInstance::getAlignment() const
@@ -1837,8 +1837,8 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
 		}
 
 		OpenWindow ow;
-		ow.id1 = id;
-		ow.id2 = h->id;
+		ow.id1 = id.getNum();
+		ow.id2 = h->id.getNum();
 		ow.window = (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::REFUGEE_CAMP)
 			? OpenWindow::RECRUITMENT_FIRST
 			: OpenWindow::RECRUITMENT_ALL;
@@ -1878,13 +1878,13 @@ void CGTownInstance::setPropertyDer(ui8 what, ui32 val)
 	switch (what)
 	{
 		case 11: //add visitor of town building
-			bonusingBuildings[val]->setProperty (ObjProperty::VISITORS, visitingHero->id);
+			bonusingBuildings[val]->setProperty (ObjProperty::VISITORS, visitingHero->id.getNum());
 			break;
 		case 12:
 			bonusingBuildings[val]->setProperty (12, 0);
 			break;
 		case 13: //add garrisoned hero to visitors
-			bonusingBuildings[val]->setProperty (ObjProperty::VISITORS, garrisonHero->id);
+			bonusingBuildings[val]->setProperty (ObjProperty::VISITORS, garrisonHero->id.getNum());
 			break;
 		case 14:
 			bonusValue.first = val;
@@ -2537,7 +2537,7 @@ bool CGVisitableOPH::wasVisited (const CGHeroInstance * h) const
 
 void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
 {
-	if(visitors.find(h->id)==visitors.end())
+	if(!vstd::contains(visitors, h->id))
 	{
 		onNAHeroVisit(h->id, false);
 		switch(ID)
@@ -2549,7 +2549,7 @@ void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
 		case Obj::SCHOOL_OF_WAR:
 			break;
 		default:
-			cb->setObjProperty(id, ObjProperty::VISITORS, h->id); //add to the visitors
+			cb->setObjProperty(id, ObjProperty::VISITORS, h->id.getNum()); //add to the visitors
 			break;
 		}
 	}
@@ -2567,16 +2567,16 @@ void CGVisitableOPH::initObj()
 		ttype = -1;
 }
 
-void CGVisitableOPH::treeSelected( int heroID, int resType, int resVal, TExpType expVal, ui32 result ) const
+void CGVisitableOPH::treeSelected( ObjectInstanceID heroID, int resType, int resVal, TExpType expVal, ui32 result ) const
 {
 	if(result) //player agreed to give res for exp
 	{
 		cb->giveResource(cb->getOwner(heroID), static_cast<Res::ERes>(resType), -resVal); //take resource
 		cb->changePrimSkill(cb->getHero(heroID), PrimarySkill::EXPERIENCE, expVal);
-		cb->setObjProperty(id, ObjProperty::VISITORS, heroID); //add to the visitors
+		cb->setObjProperty(id, ObjProperty::VISITORS, heroID.getNum()); //add to the visitors
 	}
 }
-void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
+void CGVisitableOPH::onNAHeroVisit(ObjectInstanceID heroID, bool alreadyVisited) const
 {
 	Component::EComponentType c_id = Component::PRIM_SKILL; //most used here
 	int subid=0, ot=0, sound = 0;
@@ -2682,7 +2682,7 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
 				val = VLC->heroh->reqExp(h->level+val) - VLC->heroh->reqExp(h->level);
 				if(!ttype)
 				{
-					cb->setObjProperty(id, ObjProperty::VISITORS, heroID); //add to the visitors
+					cb->setObjProperty(id, ObjProperty::VISITORS, heroID.getNum()); //add to the visitors
 					InfoWindow iw;
 					iw.soundID = sound;
 					iw.components.push_back(Component(c_id,subid,1,0));
@@ -2735,7 +2735,7 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
 				}
 				else
 				{
-					cb->setObjProperty(id, ObjProperty::VISITORS, heroID); //add to the visitors
+					cb->setObjProperty(id, ObjProperty::VISITORS, heroID.getNum()); //add to the visitors
 					cb->changePrimSkill(h,PrimarySkill::ATTACK,2);
 					cb->changePrimSkill(h,PrimarySkill::DEFENSE,2);
 					cb->changePrimSkill(h,PrimarySkill::KNOWLEDGE,2);
@@ -2823,25 +2823,25 @@ const std::string & CGVisitableOPH::getHoverText() const
 	return hoverName;
 }
 
-void CGVisitableOPH::arenaSelected( int heroID, int primSkill ) const
+void CGVisitableOPH::arenaSelected( ObjectInstanceID heroID, int primSkill ) const
 {
-	cb->setObjProperty(id, ObjProperty::VISITORS, heroID); //add to the visitors
+	cb->setObjProperty(id, ObjProperty::VISITORS, heroID.getNum()); //add to the visitors
 	cb->changePrimSkill(cb->getHero(heroID), static_cast<PrimarySkill::PrimarySkill>(primSkill-1), 2);
 }
 
 void CGVisitableOPH::setPropertyDer( ui8 what, ui32 val )
 {
 	if(what == ObjProperty::VISITORS)
-		visitors.insert(val);
+		visitors.insert(ObjectInstanceID(val));
 }
 
-void CGVisitableOPH::schoolSelected(int heroID, ui32 which) const
+void CGVisitableOPH::schoolSelected(ObjectInstanceID heroID, ui32 which) const
 {
 	if(!which) //player refused to pay
 		return;
 
 	int base = (ID == Obj::SCHOOL_OF_MAGIC  ?  2  :  0);
-	cb->setObjProperty(id, ObjProperty::VISITORS, heroID); //add to the visitors
+	cb->setObjProperty(id, ObjProperty::VISITORS, heroID.getNum()); //add to the visitors
 	cb->giveResource(cb->getOwner(heroID),Res::GOLD,-1000); //take 1000 gold
 	cb->changePrimSkill(cb->getHero(heroID), static_cast<PrimarySkill::PrimarySkill>(base + which-1), +1); //give appropriate skill
 }
@@ -2866,7 +2866,7 @@ void COPWBonus::setProperty(ui8 what, ui32 val)
 }
 void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
 {
-	int heroID = h->id;
+	ObjectInstanceID heroID = h->id;
 	if (town->hasBuilt(ID))
 	{
 		InfoWindow iw;
@@ -2878,7 +2878,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
 				{
 					GiveBonus gb;
 					gb.bonus = Bonus(Bonus::ONE_WEEK, Bonus::LAND_MOVEMENT, Bonus::OBJECT, 600, 94, VLC->generaltexth->arraytxt[100]);
-					gb.id = heroID;
+					gb.id = heroID.getNum();
 					cb->giveHeroBonus(&gb);
 					iw.text << VLC->generaltexth->allTexts[580];
 					cb->showInfoDialog(&iw);
@@ -2888,7 +2888,8 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
 				if (visitors.empty() && h->mana <= h->manaLimit() * 2)
 				{
 					cb->setManaPoints (heroID, 2 * h->manaLimit());
-					cb->setObjProperty (id, ObjProperty::VISITED, true);
+					//TODO: investigate line below
+					//cb->setObjProperty (town->id, ObjProperty::VISITED, true);
 					iw.text << VLC->generaltexth->allTexts[579];
 					cb->showInfoDialog(&iw);
 					cb->setObjProperty (town->id, 11, id); //add to visitors
@@ -2906,11 +2907,11 @@ CTownBonus::CTownBonus (BuildingID index, CGTownInstance *TOWN)
 void CTownBonus::setProperty (ui8 what, ui32 val)
 {
 	if(what == 4)
-		visitors.insert(val);
+		visitors.insert(ObjectInstanceID(val));
 }
 void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
 {
-	int heroID = h->id;
+	ObjectInstanceID heroID = h->id;
 	if (town->hasBuilt(ID) && visitors.find(heroID) == visitors.end())
 	{
 		InfoWindow iw;
@@ -3183,13 +3184,14 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
 	else
 		powerFactor = -3;
 
-	std::set<ui32> myKindCres; //what creatures are the same kind as we
-	myKindCres.insert(subID); //we
-	myKindCres.insert(VLC->creh->creatures[subID]->upgrades.begin(),VLC->creh->creatures[subID]->upgrades.end()); //our upgrades
+	std::set<CreatureID> myKindCres; //what creatures are the same kind as we
+	const CCreature * myCreature = VLC->creh->creatures[subID];
+	myKindCres.insert(myCreature->idNumber); //we
+	myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades
 
 	BOOST_FOREACH(ConstTransitivePtr<CCreature> &crea, VLC->creh->creatures)
 	{
-		if(vstd::contains(crea->upgrades, (ui32) id)) //it's our base creatures
+		if(vstd::contains(crea->upgrades, myCreature->idNumber)) //it's our base creatures
 			myKindCres.insert(crea->idNumber);
 	}
 
@@ -3656,7 +3658,7 @@ void CGVisitableOPW::setPropertyDer( ui8 what, ui32 val )
 
 void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
 {
-	int destinationid=-1;
+	ObjectInstanceID destinationid;
 	switch(ID)
 	{
 	case Obj::MONOLITH1: //one way - find corresponding exit monolith
@@ -3705,14 +3707,14 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
 	case Obj::SUBTERRANEAN_GATE: //find nearest subterranean gate on the other level
 		{
 			destinationid = getMatchingGate(id);
-			if(destinationid < 0) //no exit
+			if(destinationid == ObjectInstanceID()) //no exit
 			{
 				showInfoDialog(h,153,0);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged.
 			}
 			break;
 		}
 	}
-	if(destinationid < 0)
+	if(destinationid == ObjectInstanceID())
 	{
 		tlog2 << "Cannot find exit... (obj at " << pos << ") :( \n";
 		return;
@@ -3779,18 +3781,18 @@ void CGTeleport::postInit() //matches subterranean gates into pairs
 
 		if(best.first >= 0) //found pair
 		{
-			gates.push_back(std::pair<int, int>(cur->id, gatesSplit[1][best.first]->id));
+			gates.push_back(std::make_pair(cur->id, gatesSplit[1][best.first]->id));
 			gatesSplit[1][best.first] = NULL;
 		}
 		else
 		{
-			gates.push_back(std::pair<int, int>(cur->id, -1));
+			gates.push_back(std::make_pair(cur->id, ObjectInstanceID()));
 		}
 	}
 	objs.erase(103);
 }
 
-int CGTeleport::getMatchingGate(int id)
+ObjectInstanceID CGTeleport::getMatchingGate(ObjectInstanceID id)
 {
 	for(int i=0; i < gates.size(); i++)
 	{
@@ -3800,7 +3802,7 @@ int CGTeleport::getMatchingGate(int id)
 			return gates[i].first;
 	}
 
-	return -1;
+	return ObjectInstanceID();
 }
 
 void CGArtifact::initObj()
@@ -4089,7 +4091,7 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
 	cb->removeObject(this);
 }
 
-void CGPickable::chosen( int which, int heroID ) const
+void CGPickable::chosen( int which, ObjectInstanceID heroID ) const
 {
 	const CGHeroInstance *h = cb->getHero(heroID);
 	switch(which)
@@ -4715,9 +4717,9 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
 		case MORALE_BONUS: case LUCK_BONUS:
 		{
 			Bonus hb(Bonus::ONE_WEEK, (rewardType == 3 ? Bonus::MORALE : Bonus::LUCK),
-				Bonus::OBJECT, rVal, h->id, "", -1);
+				Bonus::OBJECT, rVal, h->id.getNum(), "", -1);
 			GiveBonus gb;
-			gb.id = h->id;
+			gb.id = h->id.getNum();
 			gb.bonus = hb;
 			cb->giveHeroBonus(&gb);
 		}
@@ -4853,7 +4855,7 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
 	InfoWindow iw;
 	iw.player = h->tempOwner;
 	GiveBonus gbonus;
-	gbonus.id = h->id;
+	gbonus.id = h->id.getNum();
 	gbonus.bonus.duration = Bonus::ONE_BATTLE;
 	gbonus.bonus.source = Bonus::OBJECT;
 	gbonus.bonus.sid = ID;
@@ -5250,8 +5252,8 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 		iw.components.push_back(Component(Component::MORALE,0,moraleDiff,0));
 		cb->showInfoDialog(&iw);
 		GiveBonus gb;
-		gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::MORALE,Bonus::OBJECT,moraleDiff,id,"");
-		gb.id = h->id;
+		gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::MORALE,Bonus::OBJECT,moraleDiff,id.getNum(),"");
+		gb.id = h->id.getNum();
 		cb->giveHeroBonus(&gb);
 	}
 
@@ -5261,8 +5263,8 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 		iw.components.push_back(Component(Component::LUCK,0,luckDiff,0));
 		cb->showInfoDialog(&iw);
 		GiveBonus gb;
-		gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,luckDiff,id,"");
-		gb.id = h->id;
+		gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,luckDiff,id.getNum(),"");
+		gb.id = h->id.getNum();
 		cb->giveHeroBonus(&gb);
 	}
 
@@ -5842,8 +5844,8 @@ void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
 		{
 			//ruin morale
 			GiveBonus gb;
-			gb.id = h->id;
-			gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::MORALE,Bonus::OBJECT,-3,id,"");
+			gb.id = h->id.getNum();
+			gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::MORALE,Bonus::OBJECT,-3,id.getNum(),"");
 			gb.bdescr.addTxt(MetaString::ARRAY_TXT,104); //Warrior Tomb Visited -3
 			cb->giveHeroBonus(&gb);
 		}
@@ -6053,7 +6055,7 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
 		if (ID == Obj::CRYPT) //morale penalty for empty Crypt
 		{
 			GiveBonus gbonus;
-			gbonus.id = h->id;
+			gbonus.id = h->id.getNum();
 			gbonus.bonus.duration = Bonus::ONE_BATTLE;
 			gbonus.bonus.source = Bonus::OBJECT;
 			gbonus.bonus.sid = ID;
@@ -6099,7 +6101,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 			else
 			{
 				GiveBonus gbonus;
-				gbonus.id = h->id;
+				gbonus.id = h->id.getNum();
 				gbonus.bonus.duration = Bonus::ONE_BATTLE;
 				gbonus.bonus.source = Bonus::OBJECT;
 				gbonus.bonus.sid = ID;
@@ -6118,7 +6120,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 			{
 				iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
 				GiveBonus gbonus;
-				gbonus.id = h->id;
+				gbonus.id = h->id.getNum();
 				gbonus.bonus.duration = Bonus::ONE_BATTLE;
 				gbonus.bonus.source = Bonus::OBJECT;
 				gbonus.bonus.sid = ID;
@@ -6244,8 +6246,8 @@ void CGPyramid::onHeroVisit (const CGHeroInstance * h) const
 		iw.text << VLC->generaltexth->advobtxt[107];
 		iw.components.push_back (Component (Component::LUCK, 0 , -2, 0));
 		GiveBonus gb;
-		gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,-2,id,VLC->generaltexth->arraytxt[70]);
-		gb.id = h->id;
+		gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,-2,id.getNum(),VLC->generaltexth->arraytxt[70]);
+		gb.id = h->id.getNum();
 		cb->giveHeroBonus(&gb);
 		cb->showInfoDialog(&iw);
 	}
@@ -6411,10 +6413,9 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
 		showInfoDialog(h,61,soundBase::LIGHTHOUSE);
 
 		fw.mode = 1;
-		std::vector<si32>::iterator it;
-		for (it = eyelist[subID].begin(); it < eyelist[subID].end(); it++)
+		BOOST_FOREACH(auto it, eyelist[subID])
 		{
-			const CGObjectInstance *eye = cb->getObj(*it);
+			const CGObjectInstance *eye = cb->getObj(it);
 
 			cb->getTilesInRange (fw.tiles, eye->pos, 10, h->tempOwner, 1);
 			cb->sendAndApply(&fw);
@@ -6630,7 +6631,7 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
 	}
 	else
 	{
-		openWindow(OpenWindow::SHIPYARD_WINDOW,id,h->id);
+		openWindow(OpenWindow::SHIPYARD_WINDOW,id.getNum(),h->id.getNum());
 	}
 }
 
@@ -6768,7 +6769,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
 			RemoveBonus rb(RemoveBonus::PLAYER);
 			rb.whoID = oldOwner;
 			rb.source = Bonus::OBJECT;
-			rb.id = id;
+			rb.id = id.getNum();
 			cb->sendAndApply(&rb);
 		}
 	}
@@ -6797,7 +6798,7 @@ void CGLighthouse::giveBonusTo( ui8 player ) const
 	gb.id = player;
 	gb.bonus.duration = Bonus::PERMANENT;
 	gb.bonus.source = Bonus::OBJECT;
-	gb.bonus.sid = id;
+	gb.bonus.sid = id.getNum();
 	cb->sendAndApply(&gb);
 }
 
@@ -7091,7 +7092,7 @@ std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
 
 void CGMarket::onHeroVisit(const CGHeroInstance * h) const
 {
-	openWindow(OpenWindow::MARKET_WINDOW,id,h->id);
+	openWindow(OpenWindow::MARKET_WINDOW,id.getNum(),h->id.getNum());
 }
 
 int CGMarket::getMarketEfficiency() const
@@ -7177,7 +7178,7 @@ void CGBlackMarket::newTurn() const
 		return;
 
 	SetAvailableArtifacts saa;
-	saa.id = id;
+	saa.id = id.getNum();
 	cb->pickAllowedArtsSet(saa.arts);
 	cb->sendAndApply(&saa);
 }
@@ -7216,7 +7217,7 @@ std::vector<int> CGUniversity::availableItemsIds(EMarketMode::EMarketMode mode)
 
 void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
 {
-	openWindow(OpenWindow::UNIVERSITY_WINDOW,id,h->id);
+	openWindow(OpenWindow::UNIVERSITY_WINDOW,id.getNum(),h->id.getNum());
 }
 
 GrowthInfo::Entry::Entry(const std::string &format, int _count)

+ 14 - 14
lib/CObjectHandler.h

@@ -170,7 +170,7 @@ public:
 	int3 pos; //h3m pos
 	Obj ID;
 	si32 subID; //normal subID (this one from OH3 maps ;])
-	si32 id;//number of object in map's vector
+	ObjectInstanceID id;//number of object in map's vector
 	CGDefInfo * defInfo;
 	ui8 animPhaseShift;
 
@@ -194,7 +194,7 @@ public:
 	std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
 	bool isVisitable() const; //returns true if object is visitable
 	bool operator<(const CGObjectInstance & cmp) const;  //screen printing priority comparing
-	void hideTiles(int ourplayer, int radius) const;
+	void hideTiles(TPlayerColor ourplayer, int radius) const;
 	CGObjectInstance();
 	virtual ~CGObjectInstance();
 	//CGObjectInstance(const CGObjectInstance & right);
@@ -218,7 +218,7 @@ protected:
 	virtual void setPropertyDer(ui8 what, ui32 val);//synchr
 
 	void getNameVis(std::string &hname) const;
-	void giveDummyBonus(int heroID, ui8 duration = Bonus::ONE_DAY) const;
+	void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const;
 };
 class CGHeroPlaceholder : public CGObjectInstance
 {
@@ -484,7 +484,7 @@ private:
 class DLL_LINKAGE CGVisitableOPH : public CGObjectInstance //objects visitable only once per hero
 {
 public:
-	std::set<si32> visitors; //ids of heroes who have visited this obj
+	std::set<ObjectInstanceID> visitors; //ids of heroes who have visited this obj
 	si8 ttype; //tree type - used only by trees of knowledge: 0 - give level for free; 1 - take 2000 gold; 2 - take 10 gems
 
 	const std::string & getHoverText() const override;
@@ -501,11 +501,11 @@ public:
 protected:
 	void setPropertyDer(ui8 what, ui32 val) override;//synchr
 private:
-	void onNAHeroVisit(int heroID, bool alreadyVisited) const;
+	void onNAHeroVisit(ObjectInstanceID heroID, bool alreadyVisited) const;
 	///dialog callbacks
-	void treeSelected(int heroID, int resType, int resVal, TExpType expVal, ui32 result) const;
-	void schoolSelected(int heroID, ui32 which) const;
-	void arenaSelected(int heroID, int primSkill) const;
+	void treeSelected(ObjectInstanceID heroID, int resType, int resVal, TExpType expVal, ui32 result) const;
+	void schoolSelected(ObjectInstanceID heroID, ui32 which) const;
+	void arenaSelected(ObjectInstanceID heroID, int primSkill) const;
 };
 class DLL_LINKAGE CGTownBuilding : public IObjectInterface
 {
@@ -541,7 +541,7 @@ class DLL_LINKAGE CTownBonus : public CGTownBuilding
 ///used for one-time bonusing structures
 ///feel free to merge inheritance tree
 public:
-	std::set<si32> visitors;
+	std::set<ObjectInstanceID> visitors;
 	void setProperty(ui8 what, ui32 val) override;
 	void onHeroVisit (const CGHeroInstance * h) const override;
 
@@ -945,7 +945,7 @@ public:
 
 	void onHeroVisit(const CGHeroInstance * h) const override;
 	void initObj() override;
-	void chosen(int which, int heroID) const;
+	void chosen(int which, ObjectInstanceID heroID) const;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1013,12 +1013,12 @@ protected:
 class DLL_LINKAGE CGTeleport : public CGObjectInstance //teleports and subterranean gates
 {
 public:
-	static std::map<int,std::map<int, std::vector<int> > > objs; //teleports: map[ID][subID] => vector of ids
-	static std::vector<std::pair<int, int> > gates; //subterranean gates: pairs of ids
+	static std::map<int,std::map<int, std::vector<ObjectInstanceID> > > objs; //teleports: map[ID][subID] => vector of ids
+	static std::vector<std::pair<ObjectInstanceID, ObjectInstanceID> > gates; //subterranean gates: pairs of ids
 	void onHeroVisit(const CGHeroInstance * h) const override;
 	void initObj() override;
 	static void postInit();
-	static int getMatchingGate(int id); //receives id of one subterranean gate and returns id of the paired one, -1 if none
+	static ObjectInstanceID getMatchingGate(ObjectInstanceID id); //receives id of one subterranean gate and returns id of the paired one, -1 if none
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1254,7 +1254,7 @@ public:
 class DLL_LINKAGE CGMagi : public CGObjectInstance
 {
 public:
-	static std::map <si32, std::vector<si32> > eyelist; //[subID][id], supports multiple sets as in H5
+	static std::map <si32, std::vector<ObjectInstanceID> > eyelist; //[subID][id], supports multiple sets as in H5
 
 	void initObj() override;
 	void onHeroVisit(const CGHeroInstance * h) const override;

+ 5 - 0
lib/GameConstants.cpp

@@ -8,6 +8,8 @@
  *
  */
 
+#define INSTANTIATE_BASE_FOR_ID_HERE
+
 #include "StdInc.h"
 
 #include "VCMI_Lib.h"
@@ -86,3 +88,6 @@ CSpell * SpellID::toSpell() const
 {
 	return VLC->spellh->spells[*this];
 }
+
+template std::ostream & operator << <ArtifactInstanceID>(std::ostream & os, BaseForID<ArtifactInstanceID> id);
+template std::ostream & operator << <ObjectInstanceID>(std::ostream & os, BaseForID<ObjectInstanceID> id);

+ 89 - 1
lib/GameConstants.h

@@ -94,9 +94,12 @@ namespace GameConstants
 }
 
 class CArtifact;
+class CArtifactInstance;
 class CGDefInfo;
 class CCreature;
 class CSpell;
+class CGameInfoCallback;
+class CNonConstInfoCallback;
 
 #define ID_LIKE_CLASS_COMMON(CLASS_NAME, ENUM_NAME)	\
 CLASS_NAME(const CLASS_NAME & other)				\
@@ -144,6 +147,86 @@ bool DLL_LINKAGE operator>=(const A & a, const B & b);
 	ID_LIKE_OPERATORS_INTERNAL_DECLS(ENUM_NAME, CLASS_NAME)
 
 
+#define OP_DECL_INT(CLASS_NAME, OP)					\
+bool operator OP (const CLASS_NAME & b) const		\
+{													\
+	return num OP b.num;							\
+}
+
+#define INSTID_LIKE_CLASS_COMMON(CLASS_NAME)		\
+public:												\
+CLASS_NAME() : BaseForID<CLASS_NAME>(-1) {}			\
+CLASS_NAME(const CLASS_NAME & other)				\
+{													\
+	num = other.num;								\
+}													\
+CLASS_NAME & operator=(const CLASS_NAME & other)	\
+{													\
+	num = other.num;								\
+	return *this;									\
+}													\
+explicit CLASS_NAME(si32 id)						\
+	: BaseForID<CLASS_NAME>(id)						\
+{}
+
+template < typename Derived>
+class BaseForID
+{
+protected:
+	si32 num;
+public:
+	si32 getNum() const
+	{
+		return num;
+	}
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & num;
+	}
+
+	explicit BaseForID(si32 _num = -1)
+	{
+		num = _num;
+	}
+
+	OP_DECL_INT(BaseForID<Derived>, ==)
+	OP_DECL_INT(BaseForID<Derived>, !=)
+	OP_DECL_INT(BaseForID<Derived>, <)
+	OP_DECL_INT(BaseForID<Derived>, >)
+	OP_DECL_INT(BaseForID<Derived>, <=)
+	OP_DECL_INT(BaseForID<Derived>, >=)
+};
+
+template<typename Der>
+DLL_LINKAGE std::ostream & operator << (std::ostream & os, BaseForID<Der> id);
+
+template<typename Der>
+std::ostream & operator << (std::ostream & os, BaseForID<Der> id)
+{
+	return os << id;
+}
+
+class ArtifactInstanceID : public BaseForID<ArtifactInstanceID>
+{
+	INSTID_LIKE_CLASS_COMMON(ArtifactInstanceID)
+
+	friend class CGameInfoCallback;
+	friend class CNonConstInfoCallback;
+};
+
+
+class ObjectInstanceID : public BaseForID<ObjectInstanceID>
+{
+	INSTID_LIKE_CLASS_COMMON(ObjectInstanceID)
+
+	friend class CGameInfoCallback;
+	friend class CNonConstInfoCallback;
+};
+
+#ifndef INSTANTIATE_BASE_FOR_ID_HERE
+extern template std::ostream & operator << <ArtifactInstanceID>(std::ostream & os, BaseForID<ArtifactInstanceID> id);
+extern template std::ostream & operator << <ObjectInstanceID>(std::ostream & os, BaseForID<ObjectInstanceID> id);
+#endif
 
 // Enum declarations
 namespace PrimarySkill
@@ -762,10 +845,15 @@ typedef ui8 TBonusType;
 typedef si32 TBonusSubtype;
 typedef si32 TSlot;
 typedef si32 TQuantity;
-typedef si32 TArtifactInstanceID;
 typedef ui8 TPlayerColor;
 
 
 #undef ID_LIKE_CLASS_COMMON
 #undef ID_LIKE_OPERATORS_DECLS
 #undef ID_LIKE_OPERATORS_INTERNAL_DECLS
+#undef INSTID_LIKE_CLASS_COMMON
+#undef OP_DECL_INT
+
+
+
+

+ 37 - 16
lib/IGameCallback.cpp

@@ -41,11 +41,11 @@ CGameState * CPrivilagedInfoCallback::gameState ()
 	return gs;
 }
 
-int CGameInfoCallback::getOwner(int heroID) const
+TPlayerColor CGameInfoCallback::getOwner(ObjectInstanceID heroID) const
 {
 	const CGObjectInstance *obj = getObj(heroID);
 	ERROR_RET_VAL_IF(!obj, "No such object!", -1);
-	return gs->map->objects[heroID]->tempOwner;
+	return obj->tempOwner;
 }
 
 int CGameInfoCallback::getResource(TPlayerColor Player, Res::ERes which) const
@@ -241,34 +241,35 @@ const CGObjectInstance * CGameInfoCallback::getObjByQuestIdentifier(int identifi
 /*                                                                      */
 /************************************************************************/
 
-const CGObjectInstance* CGameInfoCallback::getObj(int objid, bool verbose) const
+const CGObjectInstance* CGameInfoCallback::getObj(ObjectInstanceID objid, bool verbose) const
 {
-	if(objid < 0  ||  objid >= gs->map->objects.size())
+	si32 oid = objid.num;
+	if(oid < 0  ||  oid >= gs->map->objects.size())
 	{
 		if(verbose)
-			tlog1 << "Cannot get object with id " << objid << std::endl;
+			tlog1 << "Cannot get object with id " << oid << std::endl;
 		return NULL;
 	}
 
-	const CGObjectInstance *ret = gs->map->objects[objid];
+	const CGObjectInstance *ret = gs->map->objects[oid];
 	if(!ret)
 	{
 		if(verbose)
-			tlog1 << "Cannot get object with id " << objid << ". Object was removed.\n";
+			tlog1 << "Cannot get object with id " << oid << ". Object was removed.\n";
 		return NULL;
 	}
 
 	if(!isVisible(ret, player))
 	{
 		if(verbose)
-			tlog1 << "Cannot get object with id " << objid << ". Object is not visible.\n";
+			tlog1 << "Cannot get object with id " << oid << ". Object is not visible.\n";
 		return NULL;
 	}
 
 	return ret;
 }
 
-const CGHeroInstance* CGameInfoCallback::getHero(int objid) const
+const CGHeroInstance* CGameInfoCallback::getHero(ObjectInstanceID objid) const
 {
 	const CGObjectInstance *obj = getObj(objid, false);
 	if(obj)
@@ -276,11 +277,11 @@ const CGHeroInstance* CGameInfoCallback::getHero(int objid) const
 	else
 		return NULL;
 }
-const CGTownInstance* CGameInfoCallback::getTown(int objid) const
+const CGTownInstance* CGameInfoCallback::getTown(ObjectInstanceID objid) const
 {
 	const CGObjectInstance *obj = getObj(objid, false);
 	if(obj)
-		return dynamic_cast<const CGTownInstance*>(gs->map->objects[objid].get());
+		return dynamic_cast<const CGTownInstance*>(obj);
 	else
 		return NULL;
 }
@@ -352,7 +353,7 @@ void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObj
 	}
 }
 
-int CGameInfoCallback::howManyTowns(int Player) const
+int CGameInfoCallback::howManyTowns(TPlayerColor Player) const
 {
 	ERROR_RET_VAL_IF(!hasAccess(Player), "Access forbidden!", -1);
 	return gs->players[Player].towns.size();
@@ -846,12 +847,12 @@ TResources CPlayerSpecificInfoCallback::getResourceAmount() const
 	return gs->players[*player].resources;
 }
 
-CGHeroInstance *CNonConstInfoCallback::getHero(int objid)
+CGHeroInstance *CNonConstInfoCallback::getHero(ObjectInstanceID objid)
 {
 	return const_cast<CGHeroInstance*>(CGameInfoCallback::getHero(objid));
 }
 
-CGTownInstance *CNonConstInfoCallback::getTown(int objid)
+CGTownInstance *CNonConstInfoCallback::getTown(ObjectInstanceID objid)
 {
 
 	return const_cast<CGTownInstance*>(CGameInfoCallback::getTown(objid));
@@ -872,6 +873,16 @@ PlayerState * CNonConstInfoCallback::getPlayer( TPlayerColor color, bool verbose
 	return const_cast<PlayerState*>(CGameInfoCallback::getPlayer(color, verbose));
 }
 
+CArtifactInstance * CNonConstInfoCallback::getArtInstance( ArtifactInstanceID aid )
+{
+	return gs->map->artInstances[aid.num];
+}
+
+CGObjectInstance * CNonConstInfoCallback::getObjInstance( ObjectInstanceID oid )
+{
+	return gs->map->objects[oid.num];
+}
+
 const TeamState * CGameInfoCallback::getTeam( ui8 teamID ) const
 {
 	ERROR_RET_VAL_IF(!vstd::contains(gs->teams, teamID), "Cannot find info for team " << int(teamID), NULL);
@@ -907,12 +918,22 @@ bool CGameInfoCallback::isInTheMap(const int3 &pos) const
 	return gs->map->isInTheMap(pos);
 }
 
+const CArtifactInstance * CGameInfoCallback::getArtInstance( ArtifactInstanceID aid ) const
+{
+	return gs->map->artInstances[aid.num];
+}
+
+const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid ) const
+{
+	return gs->map->objects[oid.num];
+}
+
 void IGameEventRealizer::showInfoDialog( InfoWindow *iw )
 {
 	commitPackage(iw);
 }
 
-void IGameEventRealizer::showInfoDialog(const std::string &msg, int player)
+void IGameEventRealizer::showInfoDialog(const std::string &msg, TPlayerColor player)
 {
 	InfoWindow iw;
 	iw.player = player;
@@ -920,7 +941,7 @@ void IGameEventRealizer::showInfoDialog(const std::string &msg, int player)
 	showInfoDialog(&iw);
 }
 
-void IGameEventRealizer::setObjProperty(int objid, int prop, si64 val)
+void IGameEventRealizer::setObjProperty(ObjectInstanceID objid, int prop, si64 val)
 {
 	SetObjectProperty sob;
 	sob.id = objid;

+ 24 - 20
lib/IGameCallback.h

@@ -95,7 +95,7 @@ public:
 	void getUpgradeInfo(const CArmedInstance *obj, int stackPos, UpgradeInfo &out)const;
 
 	//hero
-	const CGHeroInstance* getHero(int objid) const;
+	const CGHeroInstance* getHero(ObjectInstanceID objid) const;
 	const CGHeroInstance* getHeroWithSubid(int subid) const;
 	int getHeroCount(TPlayerColor player, bool includeGarrisoned) const;
 	bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
@@ -103,14 +103,16 @@ public:
 	int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
 	const CGHeroInstance* getSelectedHero(TPlayerColor player) const; //NULL if no hero is selected
 	const CGHeroInstance* getSelectedHero() const; //of current (active) player
+	const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
+	const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;
 
 	//objects
-	const CGObjectInstance* getObj(int objid, bool verbose = true) const;
+	const CGObjectInstance* getObj(ObjectInstanceID objid, bool verbose = true) const;
 	std::vector <const CGObjectInstance * > getBlockingObjs(int3 pos)const;
 	std::vector <const CGObjectInstance * > getVisitableObjs(int3 pos, bool verbose = true)const;
 	std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
 	std::vector <std::string > getObjDescriptions(int3 pos)const; //returns descriptions of objects at pos in order from the lowest to the highest
-	int getOwner(int heroID) const;
+	TPlayerColor getOwner(ObjectInstanceID heroID) const;
 	const CGObjectInstance *getObjByQuestIdentifier(int identifier) const; //NULL if object has been removed (eg. killed)
 
 	//map
@@ -122,8 +124,8 @@ public:
 	bool isInTheMap(const int3 &pos) const;
 
 	//town
-	const CGTownInstance* getTown(int objid) const;
-	int howManyTowns(int Player) const;
+	const CGTownInstance* getTown(ObjectInstanceID objid) const;
+	int howManyTowns(TPlayerColor Player) const;
 	const CGTownInstance * getTownInfo(int val, bool mode)const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
 	std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
 	std::string getTavernGossip(const CGObjectInstance * townOrTavern) const; 
@@ -135,7 +137,7 @@ public:
 	//from gs
 	const TeamState *getTeam(ui8 teamID) const;
 	const TeamState *getPlayerTeam(TPlayerColor color) const;
-	std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID) const;
+	std::set<BuildingID> getBuildingRequiments(const CGTownInstance *t, BuildingID ID) const;
 	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID) const;// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
 };
 
@@ -182,9 +184,11 @@ public:
 	PlayerState *getPlayer(TPlayerColor color, bool verbose = true);
 	TeamState *getTeam(ui8 teamID);//get team by team ID
 	TeamState *getPlayerTeam(TPlayerColor color);// get team by player color
-	CGHeroInstance *getHero(int objid);
-	CGTownInstance *getTown(int objid);
+	CGHeroInstance *getHero(ObjectInstanceID objid);
+	CGTownInstance *getTown(ObjectInstanceID objid);
 	TerrainTile * getTile(int3 pos);
+	CArtifactInstance * getArtInstance(ArtifactInstanceID aid);
+	CGObjectInstance * getObjInstance(ObjectInstanceID oid);
 };
 
 class DLL_LINKAGE IGameEventRealizer
@@ -193,10 +197,10 @@ public:
 	virtual void commitPackage(CPackForClient *pack) = 0;
 
 	virtual void showInfoDialog(InfoWindow *iw);
-	virtual void setObjProperty(int objid, int prop, si64 val);
+	virtual void setObjProperty(ObjectInstanceID objid, int prop, si64 val);
 
 
-	virtual void showInfoDialog(const std::string &msg, int player);
+	virtual void showInfoDialog(const std::string &msg, TPlayerColor player);
 };
 
 class DLL_LINKAGE IGameEventCallback : public IGameEventRealizer
@@ -204,19 +208,19 @@ class DLL_LINKAGE IGameEventCallback : public IGameEventRealizer
 public:
 	virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells)=0;
 	virtual bool removeObject(const CGObjectInstance * obj)=0;
-	virtual void setBlockVis(int objid, bool bv)=0;
+	virtual void setBlockVis(ObjectInstanceID objid, bool bv)=0;
 	virtual void setOwner(const CGObjectInstance * objid, TPlayerColor owner)=0;
 	virtual void setHoverName(const CGObjectInstance * obj, MetaString * name)=0;
 	virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false)=0;
 	virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0; 
 	virtual void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback)=0;
 	virtual ui32 showBlockingDialog(BlockingDialog *iw) =0; //synchronous version of above //TODO:
-	virtual void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
-	virtual void showThievesGuildWindow(TPlayerColor player, int requestingObjId) =0;
+	virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
+	virtual void showThievesGuildWindow(TPlayerColor player, ObjectInstanceID requestingObjId) =0;
 	virtual void giveResource(TPlayerColor player, Res::ERes which, int val)=0;
 
 	virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
-	virtual void takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
+	virtual void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
 	virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
 	virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
 	virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack
@@ -238,15 +242,15 @@ public:
 	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
 	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
 	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
-	virtual void setAmount(int objid, ui32 val)=0;
-	virtual bool moveHero(si32 hid, int3 dst, ui8 instant, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER)=0;
+	virtual void setAmount(ObjectInstanceID objid, ui32 val)=0;
+	virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 instant, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER)=0;
 	virtual void giveHeroBonus(GiveBonus * bonus)=0;
 	virtual void setMovePoints(SetMovePoints * smp)=0;
-	virtual void setManaPoints(int hid, int val)=0;
-	virtual void giveHero(int id, TPlayerColor player)=0;
-	virtual void changeObjPos(int objid, int3 newPos, ui8 flags)=0;
+	virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
+	virtual void giveHero(ObjectInstanceID id, TPlayerColor player)=0;
+	virtual void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags)=0;
 	virtual void sendAndApply(CPackForClient * info)=0;
-	virtual void heroExchange(si32 hero1, si32 hero2)=0; //when two heroes meet on adventure map
+	virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
 	virtual void addQuest(int player, QuestInfo & quest){};
 };
 

+ 3 - 3
lib/IGameEventsReceiver.h

@@ -124,11 +124,11 @@ public:
 	virtual void playerBonusChanged(const Bonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
 	virtual void requestSent(const CPackForServer *pack, int requestID){};
 	virtual void requestRealized(PackageApplied *pa){};
-	virtual void heroExchangeStarted(si32 hero1, si32 hero2){};
+	virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2){};
 	virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
 	virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
 	virtual void playerBlocked(int reason){}; //reason: 0 - upcoming battle
-	virtual void gameOver(ui8 player, bool victory){}; //player lost or won the game
-	virtual void playerStartsTurn(ui8 player){};
+	virtual void gameOver(TPlayerColor player, bool victory){}; //player lost or won the game
+	virtual void playerStartsTurn(TPlayerColor player){};
 	virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox
 };

+ 3 - 3
lib/Mapping/CMap.cpp

@@ -283,14 +283,14 @@ void CMap::checkForObjectives()
 
 void CMap::addNewArtifactInstance(CArtifactInstance * art)
 {
-	art->id = artInstances.size();
+	art->id = ArtifactInstanceID(artInstances.size());
 	artInstances.push_back(art);
 }
 
 void CMap::eraseArtifactInstance(CArtifactInstance * art)
 {
-	assert(artInstances[art->id] == art);
-	artInstances[art->id].dellNull();
+	assert(artInstances[art->id.getNum()] == art);
+	artInstances[art->id.getNum()].dellNull();
 }
 
 void CMap::addQuest(CGObjectInstance * quest)

+ 1 - 1
lib/Mapping/CMap.h

@@ -767,7 +767,7 @@ public:
 	std::vector< ConstTransitivePtr<CQuest> > quests;
 
 	/** associative list to identify which hero/creature id belongs to which object id(index for objects) */
-	bmap<si32, si32> questIdentifierToId;
+	bmap<si32, ObjectInstanceID> questIdentifierToId;
 
 	/**
 	 * Serialize method.

+ 1 - 1
lib/Mapping/CMapEditManager.cpp

@@ -414,7 +414,7 @@ TerrainViewPattern CMapEditManager::getFlippedPattern(const TerrainViewPattern &
 void CMapEditManager::insertObject(CGObjectInstance * obj, int posx, int posy, bool underground)
 {
 	obj->pos = int3(posx, posy, underground ? 1 : 0);
-	obj->id = map->objects.size();
+	obj->id = ObjectInstanceID(map->objects.size());
 	map->objects.push_back(obj);
 	if(obj->ID == Obj::TOWN)
 	{

+ 3 - 3
lib/Mapping/MapFormatH3M.cpp

@@ -815,7 +815,7 @@ void CMapLoaderH3M::readObjects()
 		int3 objPos = readInt3();
 
 		int defnum = reader.readUInt32();
-		int idToBeGiven = map->objects.size();
+		ObjectInstanceID idToBeGiven = ObjectInstanceID(map->objects.size());
 
 		CGDefInfo * defInfo = map->customDefs.at(defnum);
 		reader.skip(5);
@@ -1460,7 +1460,7 @@ void CMapLoaderH3M::readObjects()
 			nobj->subID = defInfo->subid;
 		}
 		nobj->defInfo = defInfo;
-		assert(idToBeGiven == map->objects.size());
+		assert(idToBeGiven == ObjectInstanceID(map->objects.size()));
 		map->objects.push_back(nobj);
 		if(nobj->ID == Obj::TOWN)
 		{
@@ -1521,7 +1521,7 @@ void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number)
 	out->validTypes(true);
 }
 
-CGObjectInstance * CMapLoaderH3M::readHero(int idToBeGiven)
+CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven)
 {
 	CGHeroInstance * nhi = new CGHeroInstance();
 

+ 1 - 1
lib/Mapping/MapFormatH3M.h

@@ -171,7 +171,7 @@ private:
 	 * @param idToBeGiven the object id which should be set for the hero
 	 * @return a object instance
 	 */
-	CGObjectInstance * readHero(int idToBeGiven);
+	CGObjectInstance * readHero(ObjectInstanceID idToBeGiven);
 
 	/**
 	 * Reads a seer hut.

+ 70 - 65
lib/NetPacks.h

@@ -240,7 +240,7 @@ struct PlayerBlocked : public CPackForClient //96
 
 	enum EReason { UPCOMING_BATTLE };
 
-	ui8 reason;
+	EReason reason;
 	TPlayerColor player;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -255,7 +255,7 @@ struct YourTurn : public CPackForClient //100
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui8 player;
+	TPlayerColor player;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -300,7 +300,7 @@ struct SetPrimSkill : public CPackForClient //105
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui8 abs; //0 - changes by value; 1 - sets to value
-	si32 id;
+	ObjectInstanceID id;
 	PrimarySkill::PrimarySkill which;
 	si64 val;
 
@@ -316,7 +316,7 @@ struct SetSecSkill : public CPackForClient //106
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui8 abs; //0 - changes by value; 1 - sets to value
-	si32 id;
+	ObjectInstanceID id;
 	SecondarySkill which;
 	ui16 val;
 
@@ -332,7 +332,7 @@ struct HeroVisitCastle : public CPackForClient //108
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui8 flags; //1 - start
-	ui32 tid, hid;
+	ObjectInstanceID tid, hid;
 
 	bool start() //if hero is entering castle (if false - leaving)
 	{
@@ -354,7 +354,7 @@ struct ChangeSpells : public CPackForClient //109
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui8 learn; //1 - gives spell, 0 - takes
-	ui32 hid;
+	ObjectInstanceID hid;
 	std::set<SpellID> spells;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -370,7 +370,8 @@ struct SetMana : public CPackForClient //110
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 
-	si32 hid, val;
+	ObjectInstanceID hid;
+	si32 val;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -384,7 +385,8 @@ struct SetMovePoints : public CPackForClient //111
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui32 hid, val;
+	ObjectInstanceID hid;
+	si32 val;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -420,7 +422,7 @@ struct SetAvailableHeroes : public CPackForClient //113
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui8 player;
+	TPlayerColor player;
 	si32 hid[GameConstants::AVAILABLE_HEROES_PER_PLAYER]; //-1 if no hero
 	CSimpleArmy army[GameConstants::AVAILABLE_HEROES_PER_PLAYER];
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -442,7 +444,7 @@ struct GiveBonus :  public CPackForClient //115
 
 	enum {HERO, PLAYER, TOWN};
 	ui8 who; //who receives bonus, uses enum above
-	ui32 id; //hero. town or player id - whoever receives it
+	si32 id; //hero. town or player id - whoever receives it
 	Bonus bonus;
 	MetaString bdescr;
 
@@ -463,7 +465,7 @@ struct ChangeObjPos : public CPackForClient //116
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui32 objid;
+	ObjectInstanceID objid;
 	int3 nPos;
 	ui8 flags; //bit flags: 1 - redraw
 
@@ -483,7 +485,7 @@ struct PlayerEndsGame : public CPackForClient //117
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui8 player;
+	TPlayerColor player;
 	ui8 victory;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -544,7 +546,7 @@ struct SetCommanderProperty : public CPackForClient //120
 	void applyCl(CClient *cl){};
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 heroid; //for commander attached to hero
+	ObjectInstanceID heroid; //for commander attached to hero
 	StackLocation sl; //for commander not on the hero?
 
 	ECommanderProperty which;
@@ -585,12 +587,12 @@ struct PrepareForAdvancingCampaign : public CPackForClient //122
 struct RemoveObject : public CPackForClient //500
 {
 	RemoveObject(){type = 500;};
-	RemoveObject(si32 ID){id = ID;type = 500;};
+	RemoveObject(ObjectInstanceID ID){id = ID;type = 500;};
 	void applyFirstCl(CClient *cl);
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 id;
+	ObjectInstanceID id;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -609,7 +611,8 @@ struct TryMoveHero : public CPackForClient //501
 		FAILED, SUCCESS, TELEPORTATION, RESERVED___, BLOCKING_VISIT, EMBARK, DISEMBARK
 	};
 
-	ui32 id, movePoints;
+	ObjectInstanceID id;
+	ui32 movePoints;
 	EResult result; //uses EResult
 	int3 start, end; //h3m format
 	boost::unordered_set<int3, ShashInt3> fowRevealed; //revealed tiles
@@ -643,7 +646,7 @@ struct NewStructures : public CPackForClient //504
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 tid;
+	ObjectInstanceID tid;
 	std::set<BuildingID> bid;
 	si16 builded;
 
@@ -658,7 +661,7 @@ struct RazeStructures : public CPackForClient //505
 	void applyCl (CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 tid;
+	ObjectInstanceID tid;
 	std::set<BuildingID> bid;
 	si16 destroyed;
 
@@ -673,7 +676,7 @@ struct SetAvailableCreatures : public CPackForClient //506
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 tid;
+	ObjectInstanceID tid;
 	std::vector<std::pair<ui32, std::vector<CreatureID> > > creatures;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -687,7 +690,7 @@ struct SetHeroesInTown : public CPackForClient //508
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 tid, visiting, garrison; //id of town, visiting hero, hero in garrison
+	ObjectInstanceID tid, visiting, garrison; //id of town, visiting hero, hero in garrison
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -721,7 +724,8 @@ struct HeroRecruited : public CPackForClient //515
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 hid, tid; //subID of hero
+	si32 hid;//subID of hero
+	ObjectInstanceID tid;
 	int3 tile;
 	TPlayerColor player;
 
@@ -738,7 +742,7 @@ struct GiveHero : public CPackForClient //516
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui32 id; //object id
+	ObjectInstanceID id; //object id
 	TPlayerColor player;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -755,7 +759,7 @@ struct OpenWindow : public CPackForClient //517
 	enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD,
 	              UNIVERSITY_WINDOW, HILL_FORT_WINDOW, MARKET_WINDOW, PUZZLE_MAP, TAVERN_WINDOW};
 	ui8 window;
-	ui32 id1, id2;
+	si32 id1, id2;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -768,7 +772,6 @@ struct NewObject  : public CPackForClient //518
 	NewObject()
 	{
 		type = 518;
-		id = -1;
 	}
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
@@ -777,7 +780,7 @@ struct NewObject  : public CPackForClient //518
 	ui32 subID;
 	int3 pos;
 
-	int id; //used locally, filled during applyGs
+	ObjectInstanceID id; //used locally, filled during applyGs
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1061,7 +1064,8 @@ struct NewTurn : public CPackForClient //101
 
 	struct Hero
 	{
-		ui32 id, move, mana; //id is a general serial id
+		ObjectInstanceID id;
+		ui32 move, mana; //id is a general serial id
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
 			h & id & move & mana;
@@ -1141,11 +1145,11 @@ struct SetObjectProperty : public CPackForClient//1001
 	DLL_LINKAGE void applyGs(CGameState *gs);
 	void applyCl(CClient *cl);
 
-	ui32 id;
+	ObjectInstanceID id;
 	ui8 what; //1 - owner; 2 - blockvis; 3 - first stack count; 4 - visitors; 5 - visited; 6 - ID (if 34 then also def is replaced)
 	ui32 val;
 	SetObjectProperty(){type = 1001;};
-	SetObjectProperty(ui32 ID, ui8 What, ui32 Val):id(ID),what(What),val(Val){type = 1001;};
+	SetObjectProperty(ObjectInstanceID ID, ui8 What, ui32 Val):id(ID),what(What),val(Val){type = 1001;};
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1157,10 +1161,10 @@ struct SetHoverName : public CPackForClient//1002
 {
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	ui32 id;
+	ObjectInstanceID id;
 	MetaString name;
 	SetHoverName(){type = 1002;};
-	SetHoverName(ui32 ID, MetaString& Name):id(ID),name(Name){type = 1002;};
+	SetHoverName(ObjectInstanceID ID, MetaString& Name):id(ID),name(Name){type = 1002;};
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1172,7 +1176,7 @@ struct HeroLevelUp : public Query//2000
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 heroid;
+	ObjectInstanceID heroid;
 	PrimarySkill::PrimarySkill primskill;
 	ui8 level;
 	std::vector<SecondarySkill> skills;
@@ -1190,7 +1194,7 @@ struct CommanderLevelUp : public Query
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	si32 heroid; //for commander attached to hero
+	ObjectInstanceID heroid; //for commander attached to hero
 	StackLocation sl; //for commander not on the hero?
 
 	std::vector<ui32> skills; //0-5 - secondary skills, val-100 - special skill
@@ -1268,7 +1272,7 @@ struct GarrisonDialog : public Query//2004
 {
 	GarrisonDialog(){type = 2004;}
 	void applyCl(CClient *cl);
-	si32 objid, hid;
+	ObjectInstanceID objid, hid;
 	bool removableUnits;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1336,7 +1340,7 @@ struct BattleResult : public CPackForClient//3003
 	ui8 winner; //0 - attacker, 1 - defender, [2 - draw (should be possible?)]
 	std::map<ui32,si32> casualties[2]; //first => casualties of attackers - map crid => number
 	TExpType exp[2]; //exp for attacker and defender
-	std::set<TArtifactInstanceID> artifacts; //artifacts taken from loser to winner - currently unused
+	std::set<ArtifactInstanceID> artifacts; //artifacts taken from loser to winner - currently unused
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1765,8 +1769,8 @@ struct EndTurn : public CPackForServer
 struct DismissHero : public CPackForServer
 {
 	DismissHero(){};
-	DismissHero(si32 HID) : hid(HID) {};
-	si32 hid;
+	DismissHero(ObjectInstanceID HID) : hid(HID) {};
+	ObjectInstanceID hid;
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1778,9 +1782,9 @@ struct DismissHero : public CPackForServer
 struct MoveHero : public CPackForServer
 {
 	MoveHero(){};
-	MoveHero(const int3 &Dest, si32 HID) : dest(Dest), hid(HID){};
+	MoveHero(const int3 &Dest, ObjectInstanceID HID) : dest(Dest), hid(HID){};
 	int3 dest;
-	si32 hid;
+	ObjectInstanceID hid;
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1792,9 +1796,9 @@ struct MoveHero : public CPackForServer
 struct CastleTeleportHero : public CPackForServer
 {
 	CastleTeleportHero(){};
-	CastleTeleportHero(const si32 HID, si32 Dest, ui8 Source ) : dest(Dest), hid(HID), source(Source){};
-	si32 dest;
-	si32 hid;
+	CastleTeleportHero(const ObjectInstanceID HID, ObjectInstanceID Dest, ui8 Source ) : dest(Dest), hid(HID), source(Source){};
+	ObjectInstanceID dest;
+	ObjectInstanceID hid;
 	si8 source;//who give teleporting, 1=castle gate
 
 	bool applyGh(CGameHandler *gh);
@@ -1807,12 +1811,12 @@ struct CastleTeleportHero : public CPackForServer
 struct ArrangeStacks : public CPackForServer
 {
 	ArrangeStacks(){};
-	ArrangeStacks(ui8 W, ui8 P1, ui8 P2, si32 ID1, si32 ID2, si32 VAL)
+	ArrangeStacks(ui8 W, ui8 P1, ui8 P2, ObjectInstanceID ID1, ObjectInstanceID ID2, si32 VAL)
 		:what(W),p1(P1),p2(P2),id1(ID1),id2(ID2),val(VAL) {};
 
 	ui8 what; //1 - swap; 2 - merge; 3 - split
 	ui8 p1, p2; //positions of first and second stack
-	si32 id1, id2; //ids of objects with garrison
+	ObjectInstanceID id1, id2; //ids of objects with garrison
 	si32 val;
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1824,9 +1828,9 @@ struct ArrangeStacks : public CPackForServer
 struct DisbandCreature : public CPackForServer
 {
 	DisbandCreature(){};
-	DisbandCreature(ui8 Pos, si32 ID):pos(Pos),id(ID){};
+	DisbandCreature(ui8 Pos, ObjectInstanceID ID):pos(Pos),id(ID){};
 	ui8 pos; //stack pos
-	si32 id; //object id
+	ObjectInstanceID id; //object id
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1838,8 +1842,8 @@ struct DisbandCreature : public CPackForServer
 struct BuildStructure : public CPackForServer
 {
 	BuildStructure(){};
-	BuildStructure(si32 TID, BuildingID BID):tid(TID), bid(BID){};
-	si32 tid; //town id
+	BuildStructure(ObjectInstanceID TID, BuildingID BID):tid(TID), bid(BID){};
+	ObjectInstanceID tid; //town id
 	BuildingID bid; //structure id
 
 	bool applyGh(CGameHandler *gh);
@@ -1858,8 +1862,8 @@ struct RazeStructure : public BuildStructure
 struct RecruitCreatures : public CPackForServer
 {
 	RecruitCreatures(){};
-	RecruitCreatures(si32 TID, CreatureID CRID, si32 Amount, si32 Level):tid(TID),crid(CRID),amount(Amount),level(Level){};
-	si32 tid; //town id
+	RecruitCreatures(ObjectInstanceID TID, CreatureID CRID, si32 Amount, si32 Level):tid(TID),crid(CRID),amount(Amount),level(Level){};
+	ObjectInstanceID tid; //town id
 	CreatureID crid;
 	ui32 amount;//creature amount
 	si32 level;//dwelling level to buy from, -1 if any
@@ -1873,9 +1877,9 @@ struct RecruitCreatures : public CPackForServer
 struct UpgradeCreature : public CPackForServer
 {
 	UpgradeCreature(){};
-	UpgradeCreature(ui8 Pos, si32 ID, CreatureID CRID):pos(Pos),id(ID), cid(CRID){};
+	UpgradeCreature(ui8 Pos, ObjectInstanceID ID, CreatureID CRID):pos(Pos),id(ID), cid(CRID){};
 	ui8 pos; //stack pos
-	si32 id; //object id
+	ObjectInstanceID id; //object id
 	CreatureID cid; //id of type to which we want make upgrade
 
 	bool applyGh(CGameHandler *gh);
@@ -1888,8 +1892,8 @@ struct UpgradeCreature : public CPackForServer
 struct GarrisonHeroSwap : public CPackForServer
 {
 	GarrisonHeroSwap(){};
-	GarrisonHeroSwap(si32 TID):tid(TID){};
-	si32 tid;
+	GarrisonHeroSwap(ObjectInstanceID TID):tid(TID){};
+	ObjectInstanceID tid;
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1914,9 +1918,9 @@ struct ExchangeArtifacts : public CPackForServer
 struct AssembleArtifacts : public CPackForServer
 {
 	AssembleArtifacts(){};
-	AssembleArtifacts(si32 _heroID, ArtifactPosition _artifactSlot, bool _assemble, ui32 _assembleTo)
+	AssembleArtifacts(ObjectInstanceID _heroID, ArtifactPosition _artifactSlot, bool _assemble, ui32 _assembleTo)
 		: heroID(_heroID), artifactSlot(_artifactSlot), assemble(_assemble), assembleTo(_assembleTo){};
-	si32 heroID;
+	ObjectInstanceID heroID;
 	ArtifactPosition artifactSlot;
 	bool assemble; // True to assemble artifact, false to disassemble.
 	ui32 assembleTo; // Artifact to assemble into.
@@ -1931,8 +1935,8 @@ struct AssembleArtifacts : public CPackForServer
 struct BuyArtifact : public CPackForServer
 {
 	BuyArtifact(){};
-	BuyArtifact(si32 HID, ArtifactID AID):hid(HID),aid(AID){};
-	si32 hid;
+	BuyArtifact(ObjectInstanceID HID, ArtifactID AID):hid(HID),aid(AID){};
+	ObjectInstanceID hid;
 	ArtifactID aid;
 
 	bool applyGh(CGameHandler *gh);
@@ -1962,8 +1966,8 @@ struct TradeOnMarketplace : public CPackForServer
 struct SetFormation : public CPackForServer
 {
 	SetFormation(){};
-	SetFormation(si32 HID, ui8 Formation):hid(HID),formation(Formation){};
-	si32 hid;
+	SetFormation(ObjectInstanceID HID, ui8 Formation):hid(HID),formation(Formation){};
+	ObjectInstanceID hid;
 	ui8 formation;
 
 	bool applyGh(CGameHandler *gh);
@@ -1976,8 +1980,9 @@ struct SetFormation : public CPackForServer
 struct HireHero : public CPackForServer
 {
 	HireHero(){};
-	HireHero(si32 HID, si32 TID):hid(HID),tid(TID){};
-	si32 hid, tid; //available hero serial and town (tavern) id
+	HireHero(si32 HID, ObjectInstanceID TID):hid(HID),tid(TID){};
+	si32 hid; //available hero serial
+	ObjectInstanceID tid; //town (tavern) id
 	TPlayerColor player;
 
 	bool applyGh(CGameHandler *gh);
@@ -1990,7 +1995,7 @@ struct HireHero : public CPackForServer
 struct BuildBoat : public CPackForServer
 {
 	BuildBoat(){};
-	si32 objid; //where player wants to buy a boat
+	ObjectInstanceID objid; //where player wants to buy a boat
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -2043,7 +2048,7 @@ struct MakeCustomAction : public CPackForServer
 struct DigWithHero : public CPackForServer
 {
 	DigWithHero(){}
-	si32 id; //digging hero id
+	ObjectInstanceID id; //digging hero id
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -2055,7 +2060,7 @@ struct DigWithHero : public CPackForServer
 struct CastAdvSpell : public CPackForServer
 {
 	CastAdvSpell(){}
-	si32 hid; //hero id
+	ObjectInstanceID hid; //hero id
 	SpellID sid; //spell id
 	int3 pos; //selected tile (not always used)
 
@@ -2111,7 +2116,7 @@ struct SetSelection : public CPackForClient, public CPackForServer //514
 	void applyCl(CClient *cl);
 
 	TPlayerColor player;
-	ui32 id;
+	ObjectInstanceID id;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 16 - 16
lib/NetPacksLib.cpp

@@ -201,13 +201,13 @@ DLL_LINKAGE void GiveBonus::applyGs( CGameState *gs )
 	switch(who)
 	{
 	case HERO:
-		cbsn = gs->getHero(id);
+		cbsn = gs->getHero(ObjectInstanceID(id));
 		break;
 	case PLAYER:
 		cbsn = gs->getPlayer(id);
 		break;
 	case TOWN:
-		cbsn = gs->getTown(id);
+		cbsn = gs->getTown(ObjectInstanceID(id));
 		break;
 	}
 
@@ -234,10 +234,10 @@ DLL_LINKAGE void GiveBonus::applyGs( CGameState *gs )
 
 DLL_LINKAGE void ChangeObjPos::applyGs( CGameState *gs )
 {
-	CGObjectInstance *obj = gs->map->objects[objid];
+	CGObjectInstance *obj = gs->getObjInstance(objid);
 	if(!obj)
 	{
-		tlog1 << "Wrong ChangeObjPos: object " << objid << " doesn't exist!\n";
+		tlog1 << "Wrong ChangeObjPos: object " << objid.getNum() << " doesn't exist!\n";
 		return;
 	}
 	gs->map->removeBlockVisTiles(obj);
@@ -255,7 +255,7 @@ DLL_LINKAGE void RemoveBonus::applyGs( CGameState *gs )
 {
 	CBonusSystemNode *node;
 	if (who == HERO)
-		node = gs->getHero(whoID);
+		node = gs->getHero(ObjectInstanceID(whoID));
 	else
 		node = gs->getPlayer(whoID);
 
@@ -275,7 +275,7 @@ DLL_LINKAGE void RemoveBonus::applyGs( CGameState *gs )
 
 DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
 {
-	CGObjectInstance *obj = gs->map->objects[id];
+	CGObjectInstance *obj = gs->getObjInstance(id);
 	//unblock tiles
 	if(obj->defInfo)
 	{
@@ -305,7 +305,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
 		if(!vstd::contains(gs->hpool.pavailable, h->subID))
 			gs->hpool.pavailable[h->subID] = 0xff;
 
-		gs->map->objects[id] = NULL;
+		gs->map->objects[id.getNum()] = NULL;
 
 
 		return;
@@ -328,7 +328,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
 		//gs->map->quests[quest->qid].dellNull();
 	}
 
-	gs->map->objects[id].dellNull();
+	gs->map->objects[id.getNum()].dellNull();
 }
 
 static int getDir(int3 src, int3 dst)
@@ -434,7 +434,7 @@ DLL_LINKAGE void RazeStructures::applyGs( CGameState *gs )
 
 DLL_LINKAGE void SetAvailableCreatures::applyGs( CGameState *gs )
 {
-	CGDwelling *dw = dynamic_cast<CGDwelling*>(gs->map->objects[tid].get());
+	CGDwelling *dw = dynamic_cast<CGDwelling*>(gs->getObjInstance(tid));
 	assert(dw);
 	dw->creatures = creatures;
 }
@@ -479,13 +479,13 @@ DLL_LINKAGE void HeroRecruited::applyGs( CGameState *gs )
 	h->movement =  h->maxMovePoints(true);
 
 	gs->hpool.heroesPool.erase(hid);
-	if(h->id < 0)
+	if(h->id == ObjectInstanceID())
 	{
-		h->id = gs->map->objects.size();
+		h->id = ObjectInstanceID(gs->map->objects.size());
 		gs->map->objects.push_back(h);
 	}
 	else
-		gs->map->objects[h->id] = h;
+		gs->map->objects[h->id.getNum()] = h;
 
 	h->initHeroDefInfo();
 	gs->map->heroes.push_back(h);
@@ -548,7 +548,7 @@ DLL_LINKAGE void NewObject::applyGs( CGameState *gs )
 	o->subID = subID;
 	o->pos = pos;
 	o->defInfo = VLC->dobjinfo->gobjs[ID][subID];
-	id = o->id = gs->map->objects.size();
+	id = o->id = ObjectInstanceID(gs->map->objects.size());
 	o->hoverName = VLC->generaltexth->names[ID];
 
 	switch(ID)
@@ -911,7 +911,7 @@ DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
 
 DLL_LINKAGE void SetObjectProperty::applyGs( CGameState *gs )
 {
-	CGObjectInstance *obj = gs->map->objects[id];
+	CGObjectInstance *obj = gs->getObjInstance(id);
 	if(!obj)
 	{
 		tlog1 << "Wrong object ID - property cannot be set!\n";
@@ -943,7 +943,7 @@ DLL_LINKAGE void SetObjectProperty::applyGs( CGameState *gs )
 
 DLL_LINKAGE void SetHoverName::applyGs( CGameState *gs )
 {
-	name.toString(gs->map->objects[id]->hoverName);
+	name.toString(gs->getObj(id)->hoverName);
 }
 
 DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs )
@@ -1017,7 +1017,7 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs( CGameState *gs )
 			break;
 		case Bonus::MANA_DRAIN:
 		{
-			CGHeroInstance * h = gs->getHero(additionalInfo);
+			CGHeroInstance * h = gs->getHero(ObjectInstanceID(additionalInfo));
 			st->state.insert (EBattleStackState::DRAINED_MANA);
 			h->mana -= val;
 			vstd::amax(h->mana, 0);

+ 69 - 69
server/CGameHandler.cpp

@@ -1296,7 +1296,7 @@ void CGameHandler::newTurn()
 		}
 	}
 	//      townID,    creatureID, amount
-	std::map<si32, std::map<si32, si32> > newCreas;//creatures that needs to be added by town events
+	std::map<ObjectInstanceID, std::map<si32, si32> > newCreas;//creatures that needs to be added by town events
 
 	BOOST_FOREACH(CGTownInstance *t, gs->map->towns)
 	{
@@ -1346,7 +1346,7 @@ void CGameHandler::newTurn()
 			}
 			//add creatures from town events
 			if (vstd::contains(newCreas, t->id))
-				for(std::map<si32, si32>::iterator i=newCreas[t->id].begin() ; i!=newCreas[t->id].end(); i++)
+				for(auto i=newCreas[t->id].begin() ; i!=newCreas[t->id].end(); i++)
 					sac.creatures[i->first].first += i->second;
 
 			n.cres.push_back(sac);
@@ -1648,7 +1648,7 @@ void CGameHandler::giveSpells( const CGTownInstance *t, const CGHeroInstance *h
 		sendAndApply(&cs);
 }
 
-void CGameHandler::setBlockVis(int objid, bool bv)
+void CGameHandler::setBlockVis(ObjectInstanceID objid, bool bv)
 {
 	SetObjectProperty sop(objid,2,bv);
 	sendAndApply(&sop);
@@ -1670,13 +1670,13 @@ bool CGameHandler::removeObject( const CGObjectInstance * obj )
 	return true;
 }
 
-void CGameHandler::setAmount(int objid, ui32 val)
+void CGameHandler::setAmount(ObjectInstanceID objid, ui32 val)
 {
 	SetObjectProperty sop(objid,3,val);
 	sendAndApply(&sop);
 }
 
-bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, TPlayerColor asker /*= 255*/ )
+bool CGameHandler::moveHero( ObjectInstanceID hid, int3 dst, ui8 instant, TPlayerColor asker /*= 255*/ )
 {
 	const CGHeroInstance *h = getHero(hid);
 
@@ -1687,7 +1687,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, TPlayerColor asker
 		return false;
 	}
 
-	tlog5 << "Player " <<int(asker) << " wants to move hero "<< hid << " from "<< h->pos << " to " << dst << std::endl;
+	tlog5 << "Player " <<int(asker) << " wants to move hero "<< hid.getNum() << " from "<< h->pos << " to " << dst << std::endl;
 	int3 hmpos = dst + int3(-1,0,0);
 
 	if(!gs->map->isInTheMap(hmpos))
@@ -1835,7 +1835,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, TPlayerColor asker
 	}
 }
 
-bool CGameHandler::teleportHero(si32 hid, si32 dstid, ui8 source, TPlayerColor asker/* = 255*/)
+bool CGameHandler::teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui8 source, TPlayerColor asker/* = 255*/)
 {
 	const CGHeroInstance *h = getHero(hid);
 	const CGTownInstance *t = getTown(dstid);
@@ -1947,7 +1947,7 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance
 	tryJoiningArmy(obj, h, remove, true);
 }
 
-void CGameHandler::takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures)
+void CGameHandler::takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures)
 {
 	std::vector<CStackBasicDescriptor> cres = creatures;
 	if (cres.size() <= 0)
@@ -2079,7 +2079,7 @@ void CGameHandler::setMovePoints( SetMovePoints * smp )
 	sendAndApply(smp);
 }
 
-void CGameHandler::setManaPoints( int hid, int val )
+void CGameHandler::setManaPoints( ObjectInstanceID hid, int val )
 {
 	SetMana sm;
 	sm.hid = hid;
@@ -2087,7 +2087,7 @@ void CGameHandler::setManaPoints( int hid, int val )
 	sendAndApply(&sm);
 }
 
-void CGameHandler::giveHero( int id, TPlayerColor player )
+void CGameHandler::giveHero( ObjectInstanceID id, TPlayerColor player )
 {
 	GiveHero gh;
 	gh.id = id;
@@ -2095,7 +2095,7 @@ void CGameHandler::giveHero( int id, TPlayerColor player )
 	sendAndApply(&gh);
 }
 
-void CGameHandler::changeObjPos( int objid, int3 newPos, ui8 flags )
+void CGameHandler::changeObjPos( ObjectInstanceID objid, int3 newPos, ui8 flags )
 {
 	ChangeObjPos cop;
 	cop.objid = objid;
@@ -2104,7 +2104,7 @@ void CGameHandler::changeObjPos( int objid, int3 newPos, ui8 flags )
 	sendAndApply(&cop);
 }
 
-void CGameHandler::useScholarSkill(si32 fromHero, si32 toHero)
+void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID toHero)
 {
 	const CGHeroInstance * h1 = getHero(fromHero);
 	const CGHeroInstance * h2 = getHero(toHero);
@@ -2193,17 +2193,17 @@ void CGameHandler::useScholarSkill(si32 fromHero, si32 toHero)
 	}
 }
 
-void CGameHandler::heroExchange(si32 hero1, si32 hero2)
+void CGameHandler::heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)
 {
-	ui8 player1 = getHero(hero1)->tempOwner;
-	ui8 player2 = getHero(hero2)->tempOwner;
+	TPlayerColor player1 = getHero(hero1)->tempOwner;
+	TPlayerColor player2 = getHero(hero2)->tempOwner;
 
 	if( gameState()->getPlayerRelations( player1, player2))
 	{
 		OpenWindow hex;
 		hex.window = OpenWindow::EXCHANGE_WINDOW;
-		hex.id1 = hero1;
-		hex.id2 = hero2;
+		hex.id1 = hero1.getNum();
+		hex.id2 = hero2.getNum();
 		sendAndApply(&hex);
 		useScholarSkill(hero1,hero2);
 	}
@@ -2341,10 +2341,10 @@ void CGameHandler::close()
 	//exit(0);
 }
 
-bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, TPlayerColor player )
+bool CGameHandler::arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, ui8 p1, ui8 p2, si32 val, TPlayerColor player )
 {
-	const CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1].get()),
-		*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2].get());
+	const CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->getObjInstance(id1)),
+		*s2 = static_cast<CArmedInstance*>(gs->getObjInstance(id2));
 	const CCreatureSet &S1 = *s1, &S2 = *s2;
 	StackLocation sl1(s1, p1), sl2(s2, p2);
 	if(!sl1.validSlot()  ||  !sl2.validSlot())
@@ -2449,9 +2449,9 @@ TPlayerColor CGameHandler::getPlayerAt( CConnection *c ) const
 	}
 }
 
-bool CGameHandler::disbandCreature( si32 id, ui8 pos )
+bool CGameHandler::disbandCreature( ObjectInstanceID id, ui8 pos )
 {
-	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id].get());
+	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->getObjInstance(id));
 	if(!vstd::contains(s1->stacks,pos))
 	{
 		complain("Illegal call to disbandCreature - no such stack in army!");
@@ -2462,9 +2462,9 @@ bool CGameHandler::disbandCreature( si32 id, ui8 pos )
 	return true;
 }
 
-bool CGameHandler::buildStructure( si32 tid, BuildingID bid, bool force /*=false*/ )
+bool CGameHandler::buildStructure( ObjectInstanceID tid, BuildingID bid, bool force /*=false*/ )
 {
-	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid].get());
+	CGTownInstance * t = gs->getTown(tid);
 	CBuilding * b = t->town->buildings[bid];
 
 	if(!force)
@@ -2574,11 +2574,11 @@ bool CGameHandler::buildStructure( si32 tid, BuildingID bid, bool force /*=false
 	checkLossVictory(t->tempOwner);
 	return true;
 }
-bool CGameHandler::razeStructure (si32 tid, BuildingID bid)
+bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
 {
 ///incomplete, simply erases target building
-	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid].get());
-	if (t->builtBuildings.find(bid) == t->builtBuildings.end())
+	const CGTownInstance * t = getTown(tid);
+	if (!vstd::contains(t->builtBuildings, bid))
 		return false;
 	RazeStructures rs;
 	rs.tid = tid;
@@ -2604,9 +2604,9 @@ void CGameHandler::sendMessageToAll( const std::string &message )
 	sendToAllClients(&sm);
 }
 
-bool CGameHandler::recruitCreatures( si32 objid, CreatureID crid, ui32 cram, si32 fromLvl )
+bool CGameHandler::recruitCreatures( ObjectInstanceID objid, CreatureID crid, ui32 cram, si32 fromLvl )
 {
-	const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid].get());
+	const CGDwelling *dw = static_cast<const CGDwelling*>(gs->getObj(objid));
 	const CArmedInstance *dst = NULL;
 	const CCreature *c = VLC->creh->creatures[crid];
 	bool warMachine = c->hasBonusOfType(Bonus::SIEGE_WEAPON);
@@ -2697,9 +2697,9 @@ bool CGameHandler::recruitCreatures( si32 objid, CreatureID crid, ui32 cram, si3
 	return true;
 }
 
-bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, CreatureID upgID )
+bool CGameHandler::upgradeCreature( ObjectInstanceID objid, ui8 pos, CreatureID upgID )
 {
-	CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid].get());
+	CArmedInstance *obj = static_cast<CArmedInstance*>(gs->getObjInstance(objid));
 	assert(obj->hasStackAtSlot(pos));
 	UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
 	int player = obj->tempOwner;
@@ -2773,7 +2773,7 @@ void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst
 	}
 }
 
-bool CGameHandler::garrisonSwap( si32 tid )
+bool CGameHandler::garrisonSwap( ObjectInstanceID tid )
 {
 	CGTownInstance *town = gs->getTown(tid);
 	if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army
@@ -2789,7 +2789,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
 
 		SetHeroesInTown intown;
 		intown.tid = tid;
-		intown.visiting = -1;
+		intown.visiting = ObjectInstanceID();
 		intown.garrison = town->visitingHero->id;
 		sendAndApply(&intown);
 		return true;
@@ -2805,7 +2805,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
 
 		SetHeroesInTown intown;
 		intown.tid = tid;
-		intown.garrison = -1;
+		intown.garrison = ObjectInstanceID();
 		intown.visiting =  town->garrisonHero->id;
 		sendAndApply(&intown);
 		return true;
@@ -2888,7 +2888,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
  * @param assembleTo If assemble is true, this represents the artifact ID of the combination
  * artifact to assemble to. Otherwise it's not used.
  */
-bool CGameHandler::assembleArtifacts (si32 heroID, ArtifactPosition artifactSlot, bool assemble, ui32 assembleTo)
+bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition artifactSlot, bool assemble, ui32 assembleTo)
 {
 
 	CGHeroInstance *hero = gs->getHero(heroID);
@@ -2923,7 +2923,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ArtifactPosition artifactSlot
 	return false;
 }
 
-bool CGameHandler::buyArtifact( ui32 hid, ArtifactID aid )
+bool CGameHandler::buyArtifact( ObjectInstanceID hid, ArtifactID aid )
 {
 	CGHeroInstance *hero = gs->getHero(hid);
 	CGTownInstance *town = hero->visitedTown;
@@ -2989,7 +2989,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, Res::E
 	}
 	else if(const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(m->o)) //black market
 	{
-		saa.id = bm->id;
+		saa.id = bm->id.getNum();
 		saa.arts = bm->artifacts;
 	}
 	else
@@ -3015,7 +3015,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, Res::E
 	return true;
 }
 
-bool CGameHandler::sellArtifact( const IMarket *m, const CGHeroInstance *h, TArtifactInstanceID aid, Res::ERes rid )
+bool CGameHandler::sellArtifact( const IMarket *m, const CGHeroInstance *h, ArtifactInstanceID aid, Res::ERes rid )
 {
 	const CArtifactInstance *art = h->getArtByInstanceId(aid);
 	if(!art)
@@ -3184,7 +3184,7 @@ bool CGameHandler::sendResources(ui32 val, TPlayerColor player, Res::ERes r1, TP
 	return true;
 }
 
-bool CGameHandler::setFormation( si32 hid, ui8 formation )
+bool CGameHandler::setFormation( ObjectInstanceID hid, ui8 formation )
 {
 	gs->getHero(hid)-> formation = formation;
 	return true;
@@ -3730,7 +3730,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 			sendAndApply(&start_action);
 
 			const CStack * stack = gs->curB->battleGetStackByID(ba.stackNumber);
-			int spellID = ba.additionalInfo;
+			SpellID spellID = SpellID(ba.additionalInfo);
 			BattleHex destination(ba.destinationTile);
 
 			const Bonus *randSpellcaster = stack->getBonusLocalFirst(Selector::type(Bonus::RANDOM_SPELLCASTER));
@@ -3910,7 +3910,7 @@ void CGameHandler::playerMessage( TPlayerColor player, const std::string &messag
 	}
 }
 
-void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex destination, ui8 casterSide, TPlayerColor casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero,
+void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex destination, ui8 casterSide, TPlayerColor casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero,
 	int usedSpellPower, ECastingMode::ECastingMode mode, const CStack * stack, si32 selectedStack)
 {
 	const CSpell *spell = SpellID(spellID).toSpell();
@@ -3925,7 +3925,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 									: 0;
 
 		auto obstacle = make_shared<SpellCreatedObstacle>();
-		switch(spellID) // :/
+		switch(spellID.toEnum()) // :/
 		{
 		case SpellID::QUICKSAND:
 			obstacle->obstacleType = CObstacleInstance::QUICKSAND;
@@ -4044,7 +4044,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 			int spellDamage = 0;
 			if (stack && mode != ECastingMode::MAGIC_MIRROR)
 			{
-				int unitSpellPower = stack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, spellID);
+				int unitSpellPower = stack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, spellID.toEnum());
 				if (unitSpellPower)
 					sc.dmgToDisplay = spellDamage = stack->count * unitSpellPower; //TODO: handle immunities
 				else //Faerie Dragon
@@ -4155,7 +4155,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
  				}
 				if (caster && caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
  	 			{
- 	 				int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, spellID) / tier;
+ 	 				int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, spellID.toEnum()) / tier;
 					Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
 					specialBonus.valType = Bonus::PERCENT_TO_ALL;
 					specialBonus.sid = spellID;
@@ -4172,7 +4172,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 			int hpGained = 0;
 			if (stack)
 			{
-				int unitSpellPower = stack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, spellID);
+				int unitSpellPower = stack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, spellID.toEnum());
 				if (unitSpellPower)
 					hpGained = stack->count * unitSpellPower; //Archangel
 				else //Faerie Dragon-like effect - unused fo far
@@ -4288,7 +4288,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 			bsa.pos = gs->curB->getAvaliableHex(creID, !(bool)casterSide); //TODO: unify it
 
 			//TODO stack casting -> probably power will be zero; set the proper number of creatures manually
-			int percentBonus = caster ? caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, spellID) : 0;
+			int percentBonus = caster ? caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, spellID.toEnum()) : 0;
 
 			bsa.amount = usedSpellPower
 				* SpellID(spellID).toSpell()->powers[spellLvl]
@@ -4458,7 +4458,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 				StartAction start_action(ba);
 				sendAndApply(&start_action); //start spell casting
 
-				handleSpellCasting (ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner,
+				handleSpellCasting (SpellID(ba.additionalInfo), skill, ba.destinationTile, ba.side, h->tempOwner,
 									h, secondHero, h->getPrimSkillLevel(PrimarySkill::SPELL_POWER),
 									ECastingMode::HERO_CASTING, NULL, ba.selectedStack);
 
@@ -4560,7 +4560,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
 				{
 					bte.effect = Bonus::MANA_DRAIN;
 					bte.val = manaDrained;
-					bte.additionalInfo = enemy->id; //for sanity
+					bte.additionalInfo = enemy->id.getNum(); //for sanity
 					sendAndApply(&bte);
 				}
 			}
@@ -4590,7 +4590,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
 		if (bl.size() && st->casts && !gs->curB->enchanterCounter[side])
 		{
 			int index = rand() % bl.size();
-			int spellID = bl[index]->subtype; //spell ID
+			SpellID spellID = SpellID(bl[index]->subtype);
 			if (gs->curB->battleCanCastThisSpell(st->owner, SpellID(spellID).toSpell(), ECastingMode::ENCHANTER_CASTING)) //TODO: select another?
 			{
 				int spellLeveL = bl[index]->val; //spell level
@@ -4751,7 +4751,7 @@ void CGameHandler::handleTimeEvents()
 	}
 }
 
-void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<si32, std::map<si32, si32> > &newCreas)
+void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<ObjectInstanceID, std::map<si32, si32> > &newCreas)
 {
 	//TODO event removing desync!!!
 	town->events.sort(evntCmp);
@@ -4837,7 +4837,7 @@ ui32 CGameHandler::getQueryResult( TPlayerColor player, int queryID )
 	return 0;
 }
 
-void CGameHandler::showGarrisonDialog( int upobj, int hid, bool removableUnits, const boost::function<void()> &cb )
+void CGameHandler::showGarrisonDialog( ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb )
 {
 	ui8 player = getOwner(hid);
 	GarrisonDialog gd;
@@ -4859,17 +4859,17 @@ void CGameHandler::showGarrisonDialog( int upobj, int hid, bool removableUnits,
 			allowedExchanges.erase(gd.queryID);
 		};
 
-		allowedExchanges[gd.queryID] = std::pair<si32,si32>(upobj,hid);
+		allowedExchanges[gd.queryID] = std::make_pair(upobj,hid);
 		sendAndApply(&gd);
 	}
 }
 
-void CGameHandler::showThievesGuildWindow(TPlayerColor player, int requestingObjId)
+void CGameHandler::showThievesGuildWindow(TPlayerColor player, ObjectInstanceID requestingObjId)
 {
 	OpenWindow ow;
 	ow.window = OpenWindow::THIEVES_GUILD;
 	ow.id1 = player;
-	ow.id2 = requestingObjId;
+	ow.id2 = requestingObjId.getNum();
 	sendAndApply(&ow);
 }
 
@@ -4878,9 +4878,9 @@ bool CGameHandler::isAllowedArrangePack(const ArrangeStacks *pack)
 	return isAllowedExchangeForQuery(pack->id1, pack->id2);
 }
 
-bool CGameHandler::isAllowedExchangeForQuery(int id1, int id2) {
+bool CGameHandler::isAllowedExchangeForQuery(ObjectInstanceID id1, ObjectInstanceID id2) {
 	boost::unique_lock<boost::recursive_mutex> lock(gsm);
-	for(std::map<ui32, std::pair<si32,si32> >::const_iterator i = allowedExchanges.begin(); i!=allowedExchanges.end(); i++)
+	for(auto i = allowedExchanges.cbegin(); i!=allowedExchanges.cend(); i++)
 		if((id1 == i->second.first && id2 == i->second.second) ||
 		   (id2 == i->second.first && id1 == i->second.second))
 			return true;
@@ -4888,7 +4888,7 @@ bool CGameHandler::isAllowedExchangeForQuery(int id1, int id2) {
 	return false;
 }
 
-bool CGameHandler::isAllowedExchange( int id1, int id2 )
+bool CGameHandler::isAllowedExchange( ObjectInstanceID id1, ObjectInstanceID id2 )
 {
 	if(id1 == id2)
 		return true;
@@ -4941,7 +4941,7 @@ void CGameHandler::objectVisited( const CGObjectInstance * obj, const CGHeroInst
 	sendAndApply(&hv);
 }
 
-bool CGameHandler::buildBoat( ui32 objid )
+bool CGameHandler::buildBoat( ObjectInstanceID objid )
 {
 	const IShipyard *obj = IShipyard::castFrom(getObj(objid));
 
@@ -5269,13 +5269,13 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
 {
 	if(attacker->hasBonusOfType(attackMode))
 	{
-		std::set<ui32> spellsToCast;
+		std::set<SpellID> spellsToCast;
 		TBonusListPtr spells = attacker->getBonuses(Selector::type(attackMode));
 		BOOST_FOREACH(const Bonus *sf, *spells)
 		{
-			spellsToCast.insert (sf->subtype);
+			spellsToCast.insert (SpellID(sf->subtype));
 		}
-		BOOST_FOREACH(ui32 spellID, spellsToCast)
+		BOOST_FOREACH(SpellID spellID, spellsToCast)
 		{
 			const CStack * oneOfAttacked = NULL;
 			for (int g=0; g<bat.bsa.size(); ++g)
@@ -5505,7 +5505,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int
 			}
 
 			GiveBonus gb;
-			gb.id = h->id;
+			gb.id = h->id.getNum();
 			gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, SpellID::DIMENSION_DOOR);
 			sendAndApply(&gb);
 
@@ -5532,7 +5532,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int
 			int subtype = schoolLevel >= 2 ? 1 : 2; //adv or expert
 
 			GiveBonus gb;
-			gb.id = h->id;
+			gb.id = h->id.getNum();
 			gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::FLYING_MOVEMENT, Bonus::SPELL_EFFECT, 0, SpellID::FLY, subtype);
 			sendAndApply(&gb);
 		}
@@ -5542,7 +5542,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int
 			int subtype = schoolLevel >= 2 ? 1 : 2; //adv or expert
 
 			GiveBonus gb;
-			gb.id = h->id;
+			gb.id = h->id.getNum();
 			gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::WATER_WALKING, Bonus::SPELL_EFFECT, 0, SpellID::WATER_WALK, subtype);
 			sendAndApply(&gb);
 		}
@@ -5565,11 +5565,11 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int
 			if (h->getSpellSchoolLevel(s) < 2)
 			{
 				double dist = town->pos.dist2d(h->pos);
-				int nearest = town->id; //nearest town's ID
+				ObjectInstanceID nearest = town->id; //nearest town's ID
 				BOOST_FOREACH(const CGTownInstance * currTown, gs->getPlayer(h->tempOwner)->towns)
 				{
 					double curDist = currTown->pos.dist2d(h->pos);
-					if (nearest == -1 || curDist < dist)
+					if (nearest == ObjectInstanceID() || curDist < dist)
 					{
 						nearest = town->id;
 						dist = curDist;
@@ -5848,7 +5848,7 @@ void CGameHandler::runBattle()
 			TBonusListPtr bl = gs->curB->heroes[i]->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
 			BOOST_FOREACH (Bonus *b, *bl)
 			{
-				handleSpellCasting(b->subtype, 3, -1, 0, gs->curB->heroes[i]->tempOwner, NULL, gs->curB->heroes[1-i], b->val, ECastingMode::HERO_CASTING, NULL);
+				handleSpellCasting(SpellID(b->subtype), 3, -1, 0, gs->curB->heroes[i]->tempOwner, NULL, gs->curB->heroes[1-i], b->val, ECastingMode::HERO_CASTING, NULL);
 			}
 		}
 	}
@@ -6189,7 +6189,7 @@ void CGameHandler::removeObstacle(const CObstacleInstance &obstacle)
 
 CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
 {
-	heroWithDeadCommander = -1;
+	heroWithDeadCommander = ObjectInstanceID();
 
 	int color = army->tempOwner;
 	if(color == GameConstants::UNFLAGGABLE_PLAYER)
@@ -6230,7 +6230,7 @@ void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh)
 		else
 			gh->eraseStack(ncount.first, true);
 	}
-	if (heroWithDeadCommander > -1)
+	if (heroWithDeadCommander != ObjectInstanceID())
 	{
 		SetCommanderProperty scp;
 		scp.heroid = heroWithDeadCommander;

+ 30 - 30
server/CGameHandler.h

@@ -75,7 +75,7 @@ struct CasualtiesAfterBattle
 	typedef std::pair<StackLocation, int> TStackAndItsNewCount;
 	enum {ERASE = -1};
 	std::vector<TStackAndItsNewCount> newStackCounts;
-	si32 heroWithDeadCommander; //TODO: unify stack loactions
+	ObjectInstanceID heroWithDeadCommander; //TODO: unify stack loactions
 
 	CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat);
 	void takeFromArmy(CGameHandler *gh);
@@ -85,7 +85,7 @@ class CGameHandler : public IGameCallback, CBattleInfoCallback
 {
 private:
 	void makeStackDoNothing(const CStack * next);
-	bool isAllowedExchangeForQuery(int id1, int id2);
+	bool isAllowedExchangeForQuery(ObjectInstanceID id1, ObjectInstanceID id2);
 public:
 	CVCMIServer *s;
 	std::map<int,CConnection*> connections; //player color -> connection to client with interface of that player
@@ -98,10 +98,10 @@ public:
 
 	//TODO get rid of cfunctionlist (or similar) and use serialziable callback structure
 	std::map<ui32, CFunctionList<void(ui32)> > callbacks; //query id => callback function - for selection and yes/no dialogs
-	std::map<ui32, std::pair<si32,si32> > allowedExchanges;
+	std::map<ui32, std::pair<ObjectInstanceID, ObjectInstanceID> > allowedExchanges;
 
 	bool isBlockedByQueries(const CPack *pack, int packType, TPlayerColor player); 
-	bool isAllowedExchange(int id1, int id2);
+	bool isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2);
 	bool isAllowedArrangePack(const ArrangeStacks *pack);
 	void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
 	int moveStack(int stack, BattleHex dest); //returned value - travelled distance
@@ -131,7 +131,7 @@ public:
 	//do sth
 	void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells) OVERRIDE;
 	bool removeObject(const CGObjectInstance * obj) OVERRIDE;
-	void setBlockVis(int objid, bool bv) OVERRIDE;
+	void setBlockVis(ObjectInstanceID objid, bool bv) OVERRIDE;
 	void setOwner(const CGObjectInstance * obj, TPlayerColor owner) OVERRIDE;
 	void setHoverName(const CGObjectInstance * objid, MetaString * name) OVERRIDE;
 	void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) OVERRIDE;
@@ -139,12 +139,12 @@ public:
 	//void showInfoDialog(InfoWindow *iw) OVERRIDE;
 	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE;
 	ui32 showBlockingDialog(BlockingDialog *iw) OVERRIDE; //synchronous version of above
-	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE;
-	void showThievesGuildWindow(TPlayerColor player, int requestingObjId) OVERRIDE;
+	void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE;
+	void showThievesGuildWindow(TPlayerColor player, ObjectInstanceID requestingObjId) OVERRIDE;
 	void giveResource(TPlayerColor player, Res::ERes which, int val) OVERRIDE;
 
 	void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE;
-	void takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE;
+	void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE;
 	bool changeStackType(const StackLocation &sl, CCreature *c) OVERRIDE;
 	bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) OVERRIDE;
 	bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE;
@@ -167,20 +167,20 @@ public:
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL) OVERRIDE; //use hero=NULL for no hero
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) OVERRIDE; //for hero<=>neutral army
-	void setAmount(int objid, ui32 val) OVERRIDE;
-	bool moveHero(si32 hid, int3 dst, ui8 instant, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER) OVERRIDE;
+	void setAmount(ObjectInstanceID objid, ui32 val) OVERRIDE;
+	bool moveHero(ObjectInstanceID hid, int3 dst, ui8 instant, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER) OVERRIDE;
 	void giveHeroBonus(GiveBonus * bonus) OVERRIDE;
 	void setMovePoints(SetMovePoints * smp) OVERRIDE;
-	void setManaPoints(int hid, int val) OVERRIDE;
-	void giveHero(int id, TPlayerColor player) OVERRIDE;
-	void changeObjPos(int objid, int3 newPos, ui8 flags) OVERRIDE;
-	void heroExchange(si32 hero1, si32 hero2) OVERRIDE;
+	void setManaPoints(ObjectInstanceID hid, int val) OVERRIDE;
+	void giveHero(ObjectInstanceID id, TPlayerColor player) OVERRIDE;
+	void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags) OVERRIDE;
+	void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) OVERRIDE;
 	//////////////////////////////////////////////////////////////////////////
-	void useScholarSkill(si32 hero1, si32 hero2);
+	void useScholarSkill(ObjectInstanceID hero1, ObjectInstanceID hero2);
 	void setPortalDwelling(const CGTownInstance * town, bool forced, bool clear);
 	bool tryAttackingGuard(const int3 &guardPos, const CGHeroInstance * h);
 	void visitObjectOnTile(const TerrainTile &t, const CGHeroInstance * h);
-	bool teleportHero(si32 hid, si32 dstid, ui8 source, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER);
+	bool teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui8 source, TPlayerColor asker = GameConstants::NEUTRAL_PLAYER);
 	void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
 	void levelUpHero(const CGHeroInstance * hero, SecondarySkill skill);//handle client respond and send one more request if needed
 	void levelUpHero(const CGHeroInstance * hero);//initial call - check if hero have remaining levelups & handle them
@@ -198,7 +198,7 @@ public:
 	void playerMessage( TPlayerColor player, const std::string &message);
 	bool makeBattleAction(BattleAction &ba);
 	bool makeAutomaticAction(const CStack *stack, BattleAction &ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack)
-	void handleSpellCasting(int spellID, int spellLvl, BattleHex destination, ui8 casterSide, TPlayerColor casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero,
+	void handleSpellCasting(SpellID spellID, int spellLvl, BattleHex destination, ui8 casterSide, TPlayerColor casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero,
 		int usedSpellPower, ECastingMode::ECastingMode mode, const CStack * stack, si32 selectedStack = -1);
 	bool makeCustomAction(BattleAction &ba);
 	void stackTurnTrigger(const CStack * stack);
@@ -206,30 +206,30 @@ public:
 	void removeObstacle(const CObstacleInstance &obstacle);
 	bool queryReply( ui32 qid, ui32 answer, TPlayerColor player );
 	bool hireHero( const CGObjectInstance *obj, ui8 hid, TPlayerColor player );
-	bool buildBoat( ui32 objid );
-	bool setFormation( si32 hid, ui8 formation );
+	bool buildBoat( ObjectInstanceID objid );
+	bool setFormation( ObjectInstanceID hid, ui8 formation );
 	bool tradeResources(const IMarket *market, ui32 val, TPlayerColor player, ui32 id1, ui32 id2);
 	bool sacrificeCreatures(const IMarket *market, const CGHeroInstance *hero, TSlot slot, ui32 count);
 	bool sendResources(ui32 val, TPlayerColor player, Res::ERes r1, TPlayerColor r2);
 	bool sellCreatures(ui32 count, const IMarket *market, const CGHeroInstance * hero, ui32 slot, Res::ERes resourceID);
 	bool transformInUndead(const IMarket *market, const CGHeroInstance * hero, ui32 slot);
-	bool assembleArtifacts (si32 heroID, ArtifactPosition artifactSlot, bool assemble, ui32 assembleTo);
-	bool buyArtifact( ui32 hid, ArtifactID aid ); //for blacksmith and mage guild only -> buying for gold in common buildings
+	bool assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition artifactSlot, bool assemble, ui32 assembleTo);
+	bool buyArtifact( ObjectInstanceID hid, ArtifactID aid ); //for blacksmith and mage guild only -> buying for gold in common buildings
 	bool buyArtifact( const IMarket *m, const CGHeroInstance *h, Res::ERes rid, ArtifactID aid); //for artifact merchant and black market -> buying for any resource in special building / advobject
-	bool sellArtifact( const IMarket *m, const CGHeroInstance *h, TArtifactInstanceID aid, Res::ERes rid); //for artifact merchant selling
+	bool sellArtifact( const IMarket *m, const CGHeroInstance *h, ArtifactInstanceID aid, Res::ERes rid); //for artifact merchant selling
 	//void lootArtifacts (TArtHolder source, TArtHolder dest, std::vector<ui32> &arts); //after battle - move al arts to winer
 	bool buySecSkill( const IMarket *m, const CGHeroInstance *h, SecondarySkill skill);
-	bool garrisonSwap(si32 tid);
-	bool upgradeCreature( ui32 objid, ui8 pos, CreatureID upgID );
-	bool recruitCreatures(si32 objid, CreatureID crid, ui32 cram, si32 level);
-	bool buildStructure(si32 tid, BuildingID bid, bool force=false);//force - for events: no cost, no checkings
-	bool razeStructure(si32 tid, BuildingID bid);
-	bool disbandCreature( si32 id, ui8 pos );
-	bool arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, TPlayerColor player);
+	bool garrisonSwap(ObjectInstanceID tid);
+	bool upgradeCreature( ObjectInstanceID objid, ui8 pos, CreatureID upgID );
+	bool recruitCreatures(ObjectInstanceID objid, CreatureID crid, ui32 cram, si32 level);
+	bool buildStructure(ObjectInstanceID tid, BuildingID bid, bool force=false);//force - for events: no cost, no checkings
+	bool razeStructure(ObjectInstanceID tid, BuildingID bid);
+	bool disbandCreature( ObjectInstanceID id, ui8 pos );
+	bool arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, ui8 p1, ui8 p2, si32 val, TPlayerColor player);
 	void save(const std::string &fname);
 	void close();
 	void handleTimeEvents();
-	void handleTownEvents(CGTownInstance *town, NewTurn &n, std::map<si32, std::map<si32, si32> > &newCreas);
+	void handleTownEvents(CGTownInstance *town, NewTurn &n, std::map<ObjectInstanceID, std::map<si32, si32> > &newCreas);
 	bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
 	void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
 	void engageIntoBattle( TPlayerColor player );

+ 1 - 1
server/NetPacksServer.cpp

@@ -188,7 +188,7 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh )
 	case EMarketMode::ARTIFACT_RESOURCE:
 		if(!hero)
 			COMPLAIN_AND_RETURN("Only hero can sell artifacts!");
-		return gh->sellArtifact(m, hero, r1, static_cast<Res::ERes>(r2));
+		return gh->sellArtifact(m, hero, ArtifactInstanceID(r1), static_cast<Res::ERes>(r2));
 	case EMarketMode::CREATURE_UNDEAD:
 		return gh->transformInUndead(m, hero, r1);
 	case EMarketMode::RESOURCE_SKILL: