浏览代码

Digging: implement digging status on right click. Fix issue 401

This is also fix possibility to dig on some non-blockable objects like event.
ArseniyShestakov 10 年之前
父节点
当前提交
f55bfe41d6

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -2036,7 +2036,7 @@ void VCAI::tryRealize(Goals::BuildThis & g)
 void VCAI::tryRealize(Goals::DigAtTile & g)
 void VCAI::tryRealize(Goals::DigAtTile & g)
 {
 {
 	assert(g.hero->visitablePos() == g.tile); //surely we want to crash here?
 	assert(g.hero->visitablePos() == g.tile); //surely we want to crash here?
-	if (g.hero->diggingStatus() == CGHeroInstance::CAN_DIG)
+	if (g.hero->diggingStatus() == EDiggingStatus::CAN_DIG)
 	{
 	{
 		cb->dig(g.hero.get());
 		cb->dig(g.hero.get());
 		completeGoal(sptr(g)); // finished digging
 		completeGoal(sptr(g)); // finished digging

+ 7 - 8
client/CPlayerInterface.cpp

@@ -2315,23 +2315,22 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
 {
 {
 	std::string hlp;
 	std::string hlp;
 	CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
 	CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
-
-	int msgToShow = -1;
-	CGHeroInstance::ECanDig isDiggingPossible = h->diggingStatus();
+	auto isDiggingPossible = h->diggingStatus();
 	if(hlp.length())
 	if(hlp.length())
-		isDiggingPossible = CGHeroInstance::TILE_OCCUPIED; //TODO integrate with canDig
+		isDiggingPossible = EDiggingStatus::TILE_OCCUPIED; //TODO integrate with canDig
 
 
+	int msgToShow = -1;
 	switch(isDiggingPossible)
 	switch(isDiggingPossible)
 	{
 	{
-	case CGHeroInstance::CAN_DIG:
+	case EDiggingStatus::CAN_DIG:
 		break;
 		break;
-	case CGHeroInstance::LACK_OF_MOVEMENT:
+	case EDiggingStatus::LACK_OF_MOVEMENT:
 		msgToShow = 56; //"Digging for artifacts requires a whole day, try again tomorrow."
 		msgToShow = 56; //"Digging for artifacts requires a whole day, try again tomorrow."
 		break;
 		break;
-	case CGHeroInstance::TILE_OCCUPIED:
+	case EDiggingStatus::TILE_OCCUPIED:
 		msgToShow = 97; //Try searching on clear ground.
 		msgToShow = 97; //Try searching on clear ground.
 		break;
 		break;
-	case CGHeroInstance::WRONG_TERRAIN:
+	case EDiggingStatus::WRONG_TERRAIN:
 		msgToShow = 60; ////Try looking on land!
 		msgToShow = 60; ////Try looking on land!
 		break;
 		break;
 	default:
 	default:

+ 6 - 0
client/mapHandler.cpp

@@ -1579,7 +1579,13 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
 	if(t.hasFavourableWinds())
 	if(t.hasFavourableWinds())
 		out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
 		out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
 	else if(terName)
 	else if(terName)
+	{
 		out = CGI->generaltexth->terrainNames[t.terType];
 		out = CGI->generaltexth->terrainNames[t.terType];
+		if(t.getDiggingStatus(false) == EDiggingStatus::CAN_DIG)
+		{
+			out = boost::str(boost::format("%s %s") % out % CGI->generaltexth->allTexts[330]); /// digging ok
+		}
+	}
 }
 }
 
 
 void CMapHandler::discardWorldViewCache()
 void CMapHandler::discardWorldViewCache()

+ 22 - 0
lib/GameConstants.h

@@ -777,6 +777,28 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const ETerrainType terr
 
 
 ID_LIKE_OPERATORS(ETerrainType, ETerrainType::EETerrainType)
 ID_LIKE_OPERATORS(ETerrainType, ETerrainType::EETerrainType)
 
 
+class DLL_LINKAGE EDiggingStatus
+{
+public:
+	enum EEDiggingStatus
+	{
+		UNKNOWN = -1,
+		CAN_DIG = 0,
+		LACK_OF_MOVEMENT,
+		WRONG_TERRAIN,
+		TILE_OCCUPIED
+	};
+
+	EDiggingStatus(EEDiggingStatus _num = UNKNOWN) : num(_num)
+	{}
+
+	ID_LIKE_CLASS_COMMON(EDiggingStatus, EEDiggingStatus)
+
+	EEDiggingStatus num;
+};
+
+ID_LIKE_OPERATORS(EDiggingStatus, EDiggingStatus::EEDiggingStatus)
+
 class DLL_LINKAGE EPathfindingLayer
 class DLL_LINKAGE EPathfindingLayer
 {
 {
 public:
 public:

+ 4 - 14
lib/mapObjects/CGHeroInstance.cpp

@@ -1189,22 +1189,12 @@ int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool
 	return 0; //take all MPs otherwise
 	return 0; //take all MPs otherwise
 }
 }
 
 
-CGHeroInstance::ECanDig CGHeroInstance::diggingStatus() const
+EDiggingStatus CGHeroInstance::diggingStatus() const
 {
 {
 	if(movement < maxMovePoints(true))
 	if(movement < maxMovePoints(true))
-		return LACK_OF_MOVEMENT;
-    else if(cb->getTile(getPosition(false))->terType == ETerrainType::WATER)
-		return WRONG_TERRAIN;
-	else
-	{
-		const TerrainTile *t = cb->getTile(getPosition());
-		//TODO look for hole
-		//CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
-		if(/*hlp.length() || */t->blockingObjects.size() > 1)
-			return TILE_OCCUPIED;
-		else
-			return CAN_DIG;
-	}
+		return EDiggingStatus::LACK_OF_MOVEMENT;
+
+	return cb->getTile(getPosition(false))->getDiggingStatus();
 }
 }
 
 
 ArtBearer::ArtBearer CGHeroInstance::bearerType() const
 ArtBearer::ArtBearer CGHeroInstance::bearerType() const

+ 1 - 5
lib/mapObjects/CGHeroInstance.h

@@ -40,10 +40,6 @@ public:
 class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public ISpellCaster
 class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public ISpellCaster
 {
 {
 public:
 public:
-	enum ECanDig
-	{
-		CAN_DIG, LACK_OF_MOVEMENT, WRONG_TERRAIN, TILE_OCCUPIED
-	};
 	//////////////////////////////////////////////////////////////////////////
 	//////////////////////////////////////////////////////////////////////////
 
 
 	ui8 moveDir; //format:	123
 	ui8 moveDir; //format:	123
@@ -174,7 +170,7 @@ public:
 	bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
 	bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
 	CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
 	CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
 	void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
 	void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
-	ECanDig diggingStatus() const; //0 - can dig; 1 - lack of movement; 2 -
+	EDiggingStatus diggingStatus() const;
 
 
 	//////////////////////////////////////////////////////////////////////////
 	//////////////////////////////////////////////////////////////////////////
 
 

+ 12 - 0
lib/mapping/CMap.cpp

@@ -146,6 +146,18 @@ bool TerrainTile::isCoastal() const
 	return extTileFlags & 64;
 	return extTileFlags & 64;
 }
 }
 
 
+EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
+{
+	if(terType == ETerrainType::WATER || terType == ETerrainType::ROCK)
+		return EDiggingStatus::WRONG_TERRAIN;
+
+	int allowedBlocked = excludeTop ? 1 : 0;
+	if(blockingObjects.size() > allowedBlocked || topVisitableObj(excludeTop))
+		return EDiggingStatus::TILE_OCCUPIED;
+	else
+		return EDiggingStatus::CAN_DIG;
+}
+
 bool TerrainTile::hasFavourableWinds() const
 bool TerrainTile::hasFavourableWinds() const
 {
 {
 	return extTileFlags & 128;
 	return extTileFlags & 128;

+ 1 - 0
lib/mapping/CMap.h

@@ -277,6 +277,7 @@ struct DLL_LINKAGE TerrainTile
 	CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
 	CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
 	bool isWater() const;
 	bool isWater() const;
 	bool isCoastal() const;
 	bool isCoastal() const;
+	EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
 	bool hasFavourableWinds() const;
 	bool hasFavourableWinds() const;
 
 
 	ETerrainType terType;
 	ETerrainType terType;

+ 1 - 1
server/CGameHandler.cpp

@@ -4896,7 +4896,7 @@ bool CGameHandler::dig( const CGHeroInstance *h )
 		}
 		}
 	}
 	}
 
 
-	if(h->diggingStatus() != CGHeroInstance::CAN_DIG) //checks for terrain and movement
+	if(h->diggingStatus() != EDiggingStatus::CAN_DIG) //checks for terrain and movement
 		COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
 		COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
 
 
 	//create a hole
 	//create a hole