Browse Source

* new spell: remove obstacle
* minor changes

mateuszb 16 years ago
parent
commit
c4b0bd9d7e

+ 1 - 0
CGameInterface.h

@@ -120,6 +120,7 @@ public:
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
 	virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
 	virtual void battleNewStackAppeared(int stackID){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
+	virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles){}; //called when a certain set  of obstacles is removed from batlefield; IDs of them are given
 };
 class CAIHandler
 {

+ 29 - 2
client/CBattleInterface.cpp

@@ -848,7 +848,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 			//get dead stack if we cast resurrection or animate dead
 			const CStack * stackUnder = LOCPLINT->cb->battleGetStackByPos(myNumber, spellToCast->additionalInfo != 38 && spellToCast->additionalInfo != 39);
 
-			if(stackUnder && spellToCast->additionalInfo == 39 && !stackUnder->hasFeatureOfType(StackFeature::UNDEAD)) //animate dead can be cast only on living creatures
+			if(stackUnder && spellToCast->additionalInfo == 39 && !stackUnder->hasFeatureOfType(StackFeature::UNDEAD)) //animate dead can be cast only on undead creatures
 				stackUnder = NULL;
 
 			bool whichCase; //for cases 1, 2 and 3
@@ -896,6 +896,14 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 				}
 				break;
 			case 4: //TODO: implement this case
+				if( blockedByObstacle(myNumber) )
+				{
+					CGI->curh->changeGraphic(3, 0);
+				}
+				else
+				{
+					CGI->curh->changeGraphic(1, 0);
+				}
 				break;
 			}
 		}
@@ -1520,6 +1528,19 @@ bool CBattleInterface::isTileAttackable(const int & number) const
 	return false;
 }
 
+bool CBattleInterface::blockedByObstacle(int hex) const
+{
+	std::vector<CObstacleInstance> obstacles = LOCPLINT->cb->battleGetAllObstacles();
+	std::set<int> coveredHexes;
+	for(int b = 0; b < obstacles.size(); ++b)
+	{
+		std::vector<int> blocked = CGI->heroh->obstacles[obstacles[b].ID].getBlocked(obstacles[b].pos);
+		for(int w = 0; w < blocked.size(); ++w)
+			coveredHexes.insert(blocked[w]);
+	}
+	return vstd::contains(coveredHexes, hex);
+}
+
 void CBattleInterface::handleEndOfMove(int stackNumber, int destinationTile)
 {
 	const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackNumber);
@@ -1575,7 +1596,9 @@ void CBattleInterface::hexLclicked(int whichOne)
 				if(!LOCPLINT->cb->battleGetStackByPos(whichOne, onlyAlive))
 					allowCasting = false;
 				break;
-			case 4: //TODO: implement this case
+			case 4:
+				if(!blockedByObstacle(whichOne))
+					allowCasting = false;
 				break;
 			}
 			//destination checked
@@ -1971,6 +1994,10 @@ void CBattleInterface::castThisSpell(int spellID)
 			spellSelMode = -1;
 		}
 	}
+	if(CGI->spellh->spells[spellID].attributes.find("OBSTACLE_TARGET") != std::string::npos) //spell to be cast on an obstacle
+	{
+		spellSelMode = 4;
+	}
 	if(spellSelMode == -1) //user does not have to select location
 	{
 		spellToCast->destinationTile = -1;

+ 2 - 1
client/CBattleInterface.h

@@ -214,6 +214,7 @@ private:
 	void projectileShowHelper(SDL_Surface * to); //prints projectiles present on the battlefield
 	void giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional=-1);
 	bool isTileAttackable(const int & number) const; //returns true if tile 'number' is neighbouring any tile from active stack's range or is one of these tiles
+	bool blockedByObstacle(int hex) const;
 
 	void handleEndOfMove(int stackNumber, int destinationTile); //helper function
 
@@ -237,7 +238,7 @@ public:
 	int getAnimSpeed() const; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
 
 	CBattleHex bfield[BFIELD_SIZE]; //11 lines, 17 hexes on each
-	std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
+	//std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
 	SDL_Surface * cellBorder, * cellShade;
 	CondSh<BattleAction *> *givenCommand; //data != NULL if we have i.e. moved current unit
 	bool myTurn; //if true, interface is active (commands can be ordered

+ 17 - 0
client/CPlayerInterface.cpp

@@ -981,6 +981,23 @@ void CPlayerInterface::battleNewStackAppeared(int stackID)
 	battleInt->newStack(stackID);
 }
 
+void CPlayerInterface::battleObstaclesRemoved(const std::set<si32> & removedObstacles)
+{
+	for(std::set<si32>::const_iterator it = removedObstacles.begin(); it != removedObstacles.end(); ++it)
+	{
+		for(std::map< int, CDefHandler * >::iterator itBat = battleInt->idToObstacle.begin(); itBat != battleInt->idToObstacle.end(); ++itBat)
+		{
+			if(itBat->first == *it) //remove this obstacle
+			{
+				battleInt->idToObstacle.erase(itBat);
+				break;
+			}
+		}
+	}
+	//update accessible hexes
+	battleInt->redrawBackgroundWithHexes(battleInt->activeStack);
+}
+
 void CPlayerInterface::battleNewRound(int round) //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);

+ 1 - 0
client/CPlayerInterface.h

@@ -179,6 +179,7 @@ public:
 	void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
 	void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks); //called when stacks are healed / resurrected
 	void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
+	void battleObstaclesRemoved(const std::set<si32> & removedObstacles); //called when a certain set  of obstacles is removed from batlefield; IDs of them are given
 
 	//-------------//
 	void heroKilled(const CGHeroInstance* hero);

+ 1 - 1
client/FontBase.h

@@ -2,7 +2,7 @@
 #define __FONTBASE_H__
 
 /*
- * Graphics.h, part of VCMI engine
+ * FontBase.h, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *

+ 7 - 0
client/NetPacksClient.cpp

@@ -462,6 +462,13 @@ void StacksHealedOrResurrected::applyCl( CClient *cl )
 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleStacksHealedRes, shiftedHealed);
 }
 
+void ObstaclesRemoved::applyCl( CClient *cl )
+{
+	//inform interfaces about removed obstacles
+	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleObstaclesRemoved, obstacles);
+	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleObstaclesRemoved, obstacles);
+}
+
 CGameState* CPackForClient::GS( CClient *cl )
 {
 	return cl->gs;

+ 9 - 6
hch/CObjectHandler.cpp

@@ -4035,10 +4035,11 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
 
 void CCartographer::onHeroVisit( const CGHeroInstance * h ) const 
 {
-	if (!hasVisited (h->getOwner()) )
+	if (!hasVisited (h->getOwner()) ) //if hero has not visited yet this cartographer
 	{
-		if (cb->getResource(h->tempOwner, 6) >= 1000)
+		if (cb->getResource(h->tempOwner, 6) >= 1000) //if he can afford a map
 		{
+			//ask if he wants to buy one
 			int text;
 			if (cb->getTile(pos)->tertype == 8) //water
 					text = 25;
@@ -4055,7 +4056,7 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
 			bd.text.addTxt (MetaString::ADVOB_TXT, text);
 			cb->showBlockingDialog (&bd, boost::bind (&CCartographer::buyMap, this, h, _1));
 		}
-		else
+		else //if he cannot afford
 		{
 			InfoWindow iw;
 			iw.player = h->getOwner();
@@ -4064,7 +4065,7 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
 			cb->showInfoDialog (&iw);
 		}
 	}	
-	else
+	else //if he already visited carographer
 	{
 		InfoWindow iw;
 		iw.player = h->getOwner();
@@ -4073,9 +4074,10 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
 		cb->showInfoDialog (&iw);
 	}
 }
+
 void CCartographer::buyMap (const CGHeroInstance *h, ui32 accept) const
 {
-	if (accept)
+	if (accept) //if hero wants to buy map
 	{
 		cb->giveResource (h->tempOwner, 6, -1000);
 		FoWChange fw;
@@ -4090,8 +4092,9 @@ void CCartographer::buyMap (const CGHeroInstance *h, ui32 accept) const
 		else
 			floor = 2;
 
+		//reveal apropriate tiles
 		cb->getAllTiles (fw.tiles, h->tempOwner, floor, surface);
 		cb->sendAndApply (&fw);
 		cb->setObjProperty (id, 10, h->tempOwner);
 	}
-}
+}

+ 3 - 2
lib/CGameState.h

@@ -96,11 +96,12 @@ public:
 
 struct DLL_EXPORT CObstacleInstance
 {
-	int ID; //ID of obstacle
+	int uniqueID;
+	int ID; //ID of obstacle (defines type of it)
 	int pos; //position on battlefield
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & ID & pos;
+		h & ID & pos & uniqueID;
 	}
 };
 

+ 15 - 0
lib/NetPacks.h

@@ -977,6 +977,21 @@ struct StacksHealedOrResurrected : public CPackForClient //3013
 	}
 };
 
+struct ObstaclesRemoved : public CPackForClient //3014
+{
+	ObstaclesRemoved(){type = 3014;}
+
+	DLL_EXPORT void applyGs(CGameState *gs);
+	void applyCl(CClient *cl);
+
+	std::set<si32> obstacles; //uniqueIDs of removed obstacles
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & obstacles;
+	}
+};
+
 struct ShowInInfobox : public CPackForClient //107
 {
 	ShowInInfobox(){type = 107;};

+ 18 - 0
lib/NetPacksLib.cpp

@@ -1013,6 +1013,24 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
 	}
 }
 
+DLL_EXPORT void ObstaclesRemoved::applyGs( CGameState *gs )
+{
+	if(gs->curB) //if there is a battle
+	{
+		for(std::set<si32>::const_iterator it = obstacles.begin(); it != obstacles.end(); ++it)
+		{
+			for(int i=0; i<gs->curB->obstacles.size(); ++i)
+			{
+				if(gs->curB->obstacles[i].uniqueID == *it) //remove this obstacle
+				{
+					gs->curB->obstacles.erase(gs->curB->obstacles.begin() + i);
+					break;
+				}
+			}
+		}
+	}
+}
+
 DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
 {
 	gs->currentPlayer = player;

+ 1 - 0
lib/RegisterTypes.cpp

@@ -104,6 +104,7 @@ void registerTypes2(Serializer &s)
 	s.template registerType<StacksInjured>();
 	s.template registerType<BattleResultsApplied>();
 	s.template registerType<StacksHealedOrResurrected>();
+	s.template registerType<ObstaclesRemoved>();
 	s.template registerType<ShowInInfobox>();
 	s.template registerType<OpenWindow>();
 	s.template registerType<NewObject>();

+ 18 - 0
server/CGameHandler.cpp

@@ -1014,6 +1014,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
 		while(toBlock>0)
 		{
 			CObstacleInstance coi;
+			coi.uniqueID = curB->obstacles.size();
 			coi.ID = possibleObstacles[rand()%possibleObstacles.size()];
 			coi.pos = rand()%BFIELD_SIZE;
 			std::vector<int> block = VLC->heroh->obstacles[coi.ID].getBlocked(coi.pos);
@@ -2869,6 +2870,23 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 						sendAndApply(&shr);
 					break;
 				}
+			case 64: //remove obstacle
+				{
+					ObstaclesRemoved obr;
+					for(int g=0; g<gs->curB->obstacles.size(); ++g)
+					{
+						std::vector<int> blockedHexes = VLC->heroh->obstacles[gs->curB->obstacles[g].ID].getBlocked(gs->curB->obstacles[g].pos);
+
+						if(vstd::contains(blockedHexes, ba.destinationTile)) //this obstacle covers given hex
+						{
+							obr.obstacles.insert(gs->curB->obstacles[g].uniqueID);
+						}
+					}
+					if(!obr.obstacles.empty())
+						sendAndApply(&obr);
+
+					break;
+				}
 			}
 			sendAndApply(&EndAction());
 			return true;