Răsfoiți Sursa

Handle water Prisons and Taverns.

Tomasz Zieliński 2 ani în urmă
părinte
comite
351d596bdc

+ 11 - 0
lib/CHeroHandler.cpp

@@ -102,6 +102,17 @@ std::string CHero::getSpecialtyTooltipTextID() const
 	return TextIdentifier("hero", modScope, identifier, "specialty", "tooltip").get();
 }
 
+BoatId CHero::getBoatType() const
+{
+	switch(heroClass->getAlignment())
+	{
+		case EAlignment::EVIL : return EBoatId::BOAT_EVIL;
+		case EAlignment::GOOD : return EBoatId::BOAT_GOOD;
+		case EAlignment::NEUTRAL : return EBoatId::BOAT_NEUTRAL;
+		default: return EBoatId::NONE;
+	}
+}
+
 void CHero::registerIcons(const IconRegistar & cb) const
 {
 	cb(getIconIndex(), 0, "UN32", iconSpecSmall);

+ 2 - 0
lib/CHeroHandler.h

@@ -99,6 +99,8 @@ public:
 	std::string getSpecialtyDescriptionTextID() const override;
 	std::string getSpecialtyTooltipTextID() const override;
 
+	BoatId getBoatType() const;
+
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
 

+ 1 - 1
lib/IGameCallback.h

@@ -130,7 +130,7 @@ public:
 	virtual void giveHeroBonus(GiveBonus * bonus)=0;
 	virtual void setMovePoints(SetMovePoints * smp)=0;
 	virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
-	virtual void giveHero(ObjectInstanceID id, PlayerColor player)=0;
+	virtual void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) = 0;
 	virtual void changeObjPos(ObjectInstanceID objid, int3 newPos)=0;
 	virtual void sendAndApply(CPackForClient * pack) = 0;
 	virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map

+ 4 - 0
lib/NetPacks.h

@@ -690,6 +690,7 @@ struct DLL_LINKAGE HeroRecruited : public CPackForClient
 
 	si32 hid = -1; //subID of hero
 	ObjectInstanceID tid;
+	ObjectInstanceID boatId;
 	int3 tile;
 	PlayerColor player;
 
@@ -699,6 +700,7 @@ struct DLL_LINKAGE HeroRecruited : public CPackForClient
 	{
 		h & hid;
 		h & tid;
+		h & boatId;
 		h & tile;
 		h & player;
 	}
@@ -709,6 +711,7 @@ struct DLL_LINKAGE GiveHero : public CPackForClient
 	void applyGs(CGameState * gs) const;
 
 	ObjectInstanceID id; //object id
+	ObjectInstanceID boatId;
 	PlayerColor player;
 
 	virtual void visitTyped(ICPackVisitor & visitor) override;
@@ -716,6 +719,7 @@ struct DLL_LINKAGE GiveHero : public CPackForClient
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & id;
+		h & boatId;
 		h & player;
 	}
 };

+ 31 - 2
lib/NetPacksLib.cpp

@@ -1402,14 +1402,31 @@ void HeroRecruited::applyGs(CGameState * gs) const
 	CGTownInstance *t = gs->getTown(tid);
 	PlayerState *p = gs->getPlayerState(player);
 
-	assert(!h->boat);
+	if (boatId >= 0)
+	{
+		CGObjectInstance *obj = gs->getObjInstance(boatId);
+		auto * boat = dynamic_cast<CGBoat *>(obj);
+		if (boat)
+		{
+			h->boat = boat;
+			h->attachTo(*boat);
+			boat->hero = h;
+		}
+	}
 
 	h->setOwner(player);
 	h->pos = tile;
 	bool fresh = !h->isInitialized();
 	if(fresh)
 	{ // this is a fresh hero who hasn't appeared yet
-		h->movement = h->maxMovePoints(true);
+		if (boatId >= 0) //Hero spawns on water
+		{
+			h->movement = h->maxMovePoints(false);
+		}
+		else
+		{
+			h->movement = h->maxMovePoints(true);
+		}
 	}
 
 	gs->hpool.heroesPool.erase(hid);
@@ -1440,6 +1457,18 @@ void GiveHero::applyGs(CGameState * gs) const
 {
 	CGHeroInstance *h = gs->getHero(id);
 
+	if (boatId >= 0)
+	{
+		CGObjectInstance *obj = gs->getObjInstance(boatId);
+		auto * boat = dynamic_cast<CGBoat *>(obj);
+		if (boat)
+		{
+			h->boat = boat;
+			h->attachTo(*boat);
+			boat->hero = h;
+		}
+	}
+
 	//bonus system
 	h->detachFrom(gs->globalEffects);
 	h->attachTo(*gs->getPlayerState(player));

+ 27 - 16
lib/mapObjects/CGHeroInstance.cpp

@@ -444,21 +444,38 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 			//update hero parameters
 			SetMovePoints smp;
 			smp.hid = id;
-			smp.val = maxMovePoints (true); //TODO: hota prison on water?
+			
+			cb->setManaPoints (id, manaLimit());		
+			
+			ObjectInstanceID boatId;
+			if (cb->gameState()->map->getTile(pos).isWater())
+			{
+				smp.val = maxMovePoints(false);
+				//Create a new boat for hero
+				NewObject no;
+				no.ID = Obj::BOAT;
+				no.subID = getBoatType().getNum();
+				no.pos = pos + int3(1,0,0); //FIXME: handle this magic offset somehow
+				
+				cb->sendAndApply(&no);
+
+				cb->getVisitableObjs(pos);
+				boatId = cb->getTopObj(pos)->id;
+			}
+			else
+			{
+				smp.val = maxMovePoints(true);
+			}
+			cb->giveHero(id, h->tempOwner, boatId); //recreates def and adds hero to player
+			cb->setObjProperty(id, ObjProperty::ID, Obj::HERO); //set ID to 34 AFTER hero gets correct flag color
 			cb->setMovePoints (&smp);
-			cb->setManaPoints (id, manaLimit());
 
-			cb->setObjProperty(id, ObjProperty::ID, Obj::HERO); //set ID to 34
-			cb->giveHero(id,h->tempOwner); //recreates def and adds hero to player
-
-			txt_id = 102;
+			h->showInfoDialog(102);
 		}
 		else //already 8 wandering heroes
 		{
-			txt_id = 103;
+			h->showInfoDialog(103);
 		}
-
-		h->showInfoDialog(txt_id);
 	}
 }
 
@@ -939,13 +956,7 @@ si32 CGHeroInstance::getManaNewTurn() const
 
 BoatId CGHeroInstance::getBoatType() const
 {
-	switch(type->heroClass->getAlignment())
-	{
-		case EAlignment::EVIL : return EBoatId::BOAT_EVIL;
-		case EAlignment::GOOD : return EBoatId::BOAT_GOOD;
-		case EAlignment::NEUTRAL : return EBoatId::BOAT_NEUTRAL;
-		default: return EBoatId::NONE;
-	}
+	return type->getBoatType();
 }
 
 void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const

+ 13 - 1
server/CGameHandler.cpp

@@ -2732,11 +2732,12 @@ void CGameHandler::setManaPoints(ObjectInstanceID hid, int val)
 	sendAndApply(&sm);
 }
 
-void CGameHandler::giveHero(ObjectInstanceID id, PlayerColor player)
+void CGameHandler::giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId)
 {
 	GiveHero gh;
 	gh.id = id;
 	gh.player = player;
+	gh.boatId = boatId;
 	sendAndApply(&gh);
 
 	//Reveal fow around new hero, especially released from Prison
@@ -4415,6 +4416,17 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
 	hr.hid = nh->subID;
 	hr.player = player;
 	hr.tile = nh->convertFromVisitablePos(obj->visitablePos());
+	if (getTile(hr.tile)->isWater())
+	{
+		//Create a new boat for hero
+		NewObject no;
+		no.ID = Obj::BOAT;
+		no.subID = VLC->heroh->objects[nh->subID]->getBoatType().getNum();
+		no.pos = hr.tile + int3(1,0,0);
+		sendAndApply(&no);
+
+		hr.boatId = getTopObj(hr.tile)->id;
+	}
 	sendAndApply(&hr);
 
 	std::map<ui32, ConstTransitivePtr<CGHeroInstance> > pool = gs->unusedHeroesFromPool();

+ 1 - 1
server/CGameHandler.h

@@ -195,7 +195,7 @@ public:
 	void giveHeroBonus(GiveBonus * bonus) override;
 	void setMovePoints(SetMovePoints * smp) override;
 	void setManaPoints(ObjectInstanceID hid, int val) override;
-	void giveHero(ObjectInstanceID id, PlayerColor player) override;
+	void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) override;
 	void changeObjPos(ObjectInstanceID objid, int3 newPos) override;
 	void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override;