Browse Source

Support for Cartographers of all types.
But damn, it's slow.

DjWarmonger 16 years ago
parent
commit
dd2509f4e8
6 changed files with 175 additions and 50 deletions
  1. 115 47
      hch/CObjectHandler.cpp
  2. 16 2
      hch/CObjectHandler.h
  3. 35 0
      lib/IGameCallback.cpp
  4. 3 1
      lib/IGameCallback.h
  5. 1 0
      lib/RegisterTypes.cpp
  6. 5 0
      lib/map.cpp

+ 115 - 47
hch/CObjectHandler.cpp

@@ -2770,46 +2770,6 @@ const std::string & CGMagicWell::getHoverText() const
 	return hoverName;
 }
 
-void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
-{
-	if(!(availableFor & (1 << h->tempOwner))) 
-		return;
-	if(cb->getPlayerSettings(h->tempOwner)->human)
-	{
-		if(humanActivate)
-			activated(h);
-	}
-	else if(computerActivate)
-		activated(h);
-}
-
-void CGPandoraBox::endBattle( const CGHeroInstance *h, BattleResult *result ) const
-{
-	if(result->winner)
-		return;
-
-	giveContents(h,true);
-}
-
-void CGEvent::activated( const CGHeroInstance * h ) const
-{
-	if(army)
-	{
-		InfoWindow iw;
-		iw.player = h->tempOwner;
-		if(message.size())
-			iw.text << message;
-		else
-			iw.text.addTxt(MetaString::ADVOB_TXT, 16);
-		cb->showInfoDialog(&iw);
-		cb->startBattleI(h, this, false, boost::bind(&CGEvent::endBattle,this,h,_1));
-	}
-	else
-	{
-		giveContents(h,false);
-	}
-}
-
 void CGPandoraBox::initObj()
 {
 	blockVisit = true;
@@ -2855,6 +2815,14 @@ void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const
 	}
 }
 
+void CGPandoraBox::endBattle( const CGHeroInstance *h, BattleResult *result ) const
+{
+	if(result->winner)
+		return;
+
+	giveContents(h,true);
+}
+
 void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) const
 {
 	InfoWindow iw;
@@ -3099,6 +3067,38 @@ void CGPandoraBox::getText( InfoWindow &iw, bool &afterBattle, int val, int nega
 	}
 }
 
+void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
+{
+	if(!(availableFor & (1 << h->tempOwner))) 
+		return;
+	if(cb->getPlayerSettings(h->tempOwner)->human)
+	{
+		if(humanActivate)
+			activated(h);
+	}
+	else if(computerActivate)
+		activated(h);
+}
+
+void CGEvent::activated( const CGHeroInstance * h ) const
+{
+	if(army)
+	{
+		InfoWindow iw;
+		iw.player = h->tempOwner;
+		if(message.size())
+			iw.text << message;
+		else
+			iw.text.addTxt(MetaString::ADVOB_TXT, 16);
+		cb->showInfoDialog(&iw);
+		cb->startBattleI(h, this, false, boost::bind(&CGEvent::endBattle,this,h,_1));
+	}
+	else
+	{
+		giveContents(h,false);
+	}
+}
+
 void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
 {
 	InfoWindow iw;
@@ -3539,11 +3539,17 @@ void CBank::setPropertyDer (ui8 what, ui32 val)
 			daycounter++;
 			break;
 		case 12: //multiplier
-			multiplier *= ((float)val)/100;
+			multiplier = ((float)val)/100;
 			break;
 		case 13: //bank preset
 			bc = &VLC->objh->banksInfo[index][val];
 			break;
+		case 14:
+			reset();
+			break;
+		case 15:
+			bc = NULL;
+			break;
 		case 18: //Artifacts
 		{
 			std::vector<CArtifact*> arts; 
@@ -3651,10 +3657,10 @@ void CBank::fightGuards (const CGHeroInstance * h, ui32 accept) const
 				tlog1 << "Error: Unexpected army data: " << bc->guards.size() <<" items found";
 				return;
 		}
-	//TODO: start combat 
+	cb->startBattleI (h, this, true, boost::bind (&CBank::endBattle, this, h, _1));
 	}
 }
-void CBank::endBattle (const BattleResult *result)
+void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) const
 {
 	if (result->winner == 0)
 	{
@@ -3697,23 +3703,23 @@ void CBank::endBattle (const BattleResult *result)
 			iw.components.push_back (Component (Component::RESOURCE, it->first, it->second, 0));
 			cb->giveResource (cb->getCurrentPlayer(), it->first, it->second);
 		}
-		for (std::vector<si32>::iterator it = artifacts.begin(); it != artifacts.end(); it++)
+		for (std::vector<si32>::const_iterator it = artifacts.begin(); it != artifacts.end(); it++)
 		{
 			iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 			iw.text.addReplacement (MetaString::ART_NAMES, *it);
 			cb->giveHeroArtifact (*it, cb->getSelectedHero() ,-2);
 		}
 		CCreatureSet ourArmy;
-		for (std::vector< std::pair <ui16, ui32> >::iterator it = bc->creatures.begin(); it != bc->creatures.end(); it++)
+		for (std::vector< std::pair <ui16, ui32> >::const_iterator it = bc->creatures.begin(); it != bc->creatures.end(); it++)
 		{
 			int slot = ourArmy.getSlotFor (it->second);
 			ourArmy.slots[slot] = *it; //assuming we're not going to add multiple stacks of same creature
 		}
 		cb->giveCreatures (id, cb->getHero (cb->getSelectedHero()), &ourArmy);
-			bc = NULL;
+			cb->setObjProperty (id, 15, 0); //bc = NULL
 	}
 	else
-		reset();
+		cb->setObjProperty (id, 14, 0); //reset
 }
 
 void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8
@@ -4026,3 +4032,65 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
 		cb->sendAndApply(&ow);
 	}
 }
+
+void CCartographer::onHeroVisit( const CGHeroInstance * h ) const 
+{
+	if (!hasVisited (h->getOwner()) )
+	{
+		if (cb->getResource(h->tempOwner, 6) >= 1000)
+		{
+			int text;
+			if (cb->getTile(pos)->tertype == 8) //water
+					text = 25;
+			else
+			{
+				if (pos.z == 0)
+					text = 26;
+				else
+					text = 27;
+			}
+			BlockingDialog bd (true, false);
+			bd.player = h->getOwner();
+			bd.soundID = soundBase::LIGHTHOUSE;
+			bd.text.addTxt (MetaString::ADVOB_TXT, text);
+			cb->showBlockingDialog (&bd, boost::bind (&CCartographer::buyMap, this, h, _1));
+		}
+		else
+		{
+			InfoWindow iw;
+			iw.player = h->getOwner();
+			iw.soundID = soundBase::CAVEHEAD;
+			iw.text << std::pair<ui8,ui32>(11,28);
+			cb->showInfoDialog (&iw);
+		}
+	}	
+	else
+	{
+		InfoWindow iw;
+		iw.player = h->getOwner();
+		iw.soundID = soundBase::CAVEHEAD;
+		iw.text << std::pair<ui8,ui32>(11,24);
+		cb->showInfoDialog (&iw);
+	}
+}
+void CCartographer::buyMap (const CGHeroInstance *h, ui32 accept) const
+{
+	if (accept)
+	{
+		FoWChange fw;
+		fw.player = h->tempOwner;
+		int floor, surface = 0;
+		if (cb->getTile(pos)->tertype == 8) //water
+			surface = 2;
+		else
+			surface = 1;
+		if (pos.z == 0) //ground
+			floor = 1;
+		else
+			floor = 2;
+
+		cb->getAllTiles (fw.tiles, h->tempOwner, floor, surface);
+		cb->sendAndApply (&fw);
+		cb->setObjProperty (id, 10, h->tempOwner);
+	}
+}

+ 16 - 2
hch/CObjectHandler.h

@@ -176,7 +176,7 @@ public:
 	std::set<ui8> players; //players that visited this object
 
 	bool hasVisited(ui8 player) const;
-	void setPropertyDer(ui8 what, ui32 val);//synchr
+	virtual void setPropertyDer( ui8 what, ui32 val );
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -855,7 +855,7 @@ class DLL_EXPORT CBank : public CArmedInstance
 	void newTurn();
 	void onHeroVisit (const CGHeroInstance * h) const;
 	void fightGuards (const CGHeroInstance *h, ui32 accept) const;
-	void endBattle (const BattleResult *result);
+	void endBattle (const CGHeroInstance *h, const BattleResult *result) const;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -888,6 +888,20 @@ public:
 
 
 
+class DLL_EXPORT CCartographer : public CPlayersVisited
+{
+///behaviour varies depending on surface and  floor 
+public:
+	void onHeroVisit( const CGHeroInstance * h ) const;
+	void buyMap (const CGHeroInstance *h, ui32 accept) const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & players;
+	}
+
+
+};
 struct BankConfig
 {
 	BankConfig() {chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };

+ 35 - 0
lib/IGameCallback.cpp

@@ -17,6 +17,10 @@
  *
  */
 
+CGameState *const IGameCallback::gameState ()
+{ 
+	return gs;
+}
 const CGObjectInstance* IGameCallback::getObj(int objid)
 {
 	if(objid < 0  ||  objid >= gs->map->objects.size())
@@ -110,6 +114,37 @@ void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radiou
 	}
 }
 
+void IGameCallback::getAllTiles (std::set<int3> &tiles, int player/*=-1*/, int floor, int surface )
+{
+	if(player >= PLAYER_LIMIT)
+	{
+		tlog1 << "Illegal call to getTilesInRange!\n";
+		return;
+	}
+	bool water = false, land = false;
+	if (surface == 0 || surface == 2)
+		water = true;
+	if (surface == 0 || surface == 1)
+		land  = true;
+	std::set<int> floors;
+	if (floor==1 || floor == 0) // ground
+		floors.insert(0);
+	if (floor==2 || floor == 0) // undergroundground
+		floors.insert(1);
+	for (std::set<int>::iterator i = floors.begin(); i!= floors.end(); i++)
+	{
+		for (int xd = 0; xd <= gs->map->width - 1; xd++)
+		{
+			for (int yd = 0; yd <= gs->map->height - 1; yd++)
+			{
+				if ((getTile (int3 (xd,yd,*i))->tertype == 8 && water == true)
+					|| (getTile (int3 (xd,yd,*i))->tertype != 8 && land == true))
+					tiles.insert(int3(xd,yd,*i));
+			}
+		}
+	}
+}
+
 bool IGameCallback::isAllowed( int type, int id )
 {
 	switch(type)

+ 3 - 1
lib/IGameCallback.h

@@ -41,6 +41,7 @@ protected:
 public:
 	virtual ~IGameCallback(){};
 
+	CGameState *const gameState ();
 	virtual int getOwner(int heroID);
 	virtual int getResource(int player, int which);
 	virtual int getDate(int mode=0); ////mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
@@ -52,7 +53,8 @@ public:
 	virtual int getSelectedHero()=0;
 	virtual const PlayerSettings * getPlayerSettings(int color);
 	virtual int getHeroCount(int player, bool includeGarrisoned);
-	virtual void getTilesInRange(std::set<int3> &tiles, int3 pos, int radious, int player=-1, int mode=0); //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only unrevealed
+	virtual void getTilesInRange(std::set<int3> &tiles, int3 pos, int radious, int player=-1, int mode=0);  //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only unrevealed
+	virtual void getAllTiles (std::set<int3> &tiles, int player=-1, int floor=0, int surface=0);
 	virtual bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact
 	virtual void getAllowedArts(std::vector<CArtifact*> &out, std::vector<CArtifact*> CArtHandler::*arts);
 	virtual void getAllowed(std::vector<CArtifact*> &out, int flags); //flags: bitfield uses EartClass

+ 1 - 0
lib/RegisterTypes.cpp

@@ -51,6 +51,7 @@ void registerTypes1(Serializer &s)
 	s.template registerType<CGOnceVisitable>();
 	s.template registerType<CBank>();
 	s.template registerType<CGShipyard>();
+	s.template registerType<CCartographer>();
 	s.template registerType<CGObjectInstance>();
 }
 

+ 5 - 0
lib/map.cpp

@@ -1924,6 +1924,11 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
 				nobj = new CBank();
 				break;
 			}
+		case 13: //Cartographer
+			{
+				nobj = new CCartographer();
+				break;
+			}
 		default:
 			nobj = new CGObjectInstance();
 		} //end of main switch