Browse Source

Implemented abandoned mine. Minor fixes.

Michał W. Urbańczyk 15 years ago
parent
commit
d79fa527a7
8 changed files with 138 additions and 38 deletions
  1. 103 27
      hch/CObjectHandler.cpp
  2. 10 0
      hch/CObjectHandler.h
  3. 5 0
      lib/CCreatureSet.cpp
  4. 1 0
      lib/CCreatureSet.h
  5. 6 1
      lib/CGameState.cpp
  6. 11 2
      lib/HeroBonus.cpp
  7. 1 1
      lib/NetPacks.h
  8. 1 7
      lib/map.cpp

+ 103 - 27
hch/CObjectHandler.cpp

@@ -405,6 +405,9 @@ void CGObjectInstance::setProperty( ui8 what, ui32 val )
 	case ObjProperty::ID:
 		ID = val;
 		break;
+	case ObjProperty::SUBID:
+		subID = val;
+		break;
 	}
 	setPropertyDer(what, val);
 }
@@ -2606,11 +2609,11 @@ const std::string & CGVisitableOPH::getHoverText() const
 	}
 	hoverName = VLC->generaltexth->names[ID];
 	if(pom >= 0)
-		hoverName += (" " + VLC->generaltexth->xtrainfo[pom]);
+		hoverName += ("\n" + VLC->generaltexth->xtrainfo[pom]);
 	const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
 	if(h)
 	{
-		hoverName += ' ';
+		hoverName += "\n\n";
 		hoverName += (vstd::contains(visitors,h->id)) 
 							? (VLC->generaltexth->allTexts[352])  //visited
 							: ( VLC->generaltexth->allTexts[353]); //not visited
@@ -3061,34 +3064,25 @@ void CGCreature::flee( const CGHeroInstance * h ) const
 
 void CGMine::onHeroVisit( const CGHeroInstance * h ) const
 {
-	if(subID == 7) //TODO: support for abandoned mine
-		return;
-
 	if(h->tempOwner == tempOwner) //we're visiting our mine
 	{
 		cb->showGarrisonDialog(id,h->id,true,0);
 		return; 
 	}
 
-	//TODO: check if mine is guarded
-	cb->setOwner(id,h->tempOwner); //not ours? flag it!
+	if(subID >= 7) //Abandoned mine
+	{
+		BlockingDialog ynd(true,false);
+		ynd.player = h->tempOwner;
+		ynd.text << std::pair<ui8,ui32>(MetaString::ADVOB_TXT, 84); 
+		cb->showBlockingDialog(&ynd,boost::bind(&CGMine::fight, this, _1, h));
+		return;
+	}
 
-	MetaString ms;
-	ms << std::pair<ui8,ui32>(9,subID) << " (" << std::pair<ui8,ui32>(6,23+h->tempOwner) << ")";
-	cb->setHoverName(id,&ms);
+	//TODO: check if mine is guarded
 
-	int vv=1; //amount of resource per turn	
-	if (subID==0 || subID==2)
-		vv++;
-	else if (subID==6)
-		vv = 1000;
+	flagMine(h->tempOwner);
 
-	InfoWindow iw;
-	iw.soundID = soundBase::FLAGMINE;
-	iw.text << std::pair<ui8,ui32>(10,subID);
-	iw.player = h->tempOwner;
-	iw.components.push_back(Component(2,subID,vv,-1));
-	cb->showInfoDialog(&iw);
 }
 
 void CGMine::newTurn() const
@@ -3108,13 +3102,95 @@ void CGMine::newTurn() const
 
 void CGMine::initObj()
 {
-	MetaString ms;
-	ms << std::pair<ui8,ui32>(9,subID);
-	if(tempOwner >= PLAYER_LIMIT)
-		tempOwner = NEUTRAL_PLAYER;	
+	if(subID >= 7) //Abandoned Mine
+	{
+		//set guardians
+		int howManyTroglodytes = 100 + ran()%100;
+		CStackInstance troglodytes(70, howManyTroglodytes);
+		addStack(0, troglodytes);
+
+		//after map reading tempOwner placeholds bitmask for allowed resources
+		std::vector<int> possibleResources;
+		for (int i = 0; i < 8; i++)
+			if(tempOwner & 1<<i)
+				possibleResources.push_back(i);
+
+		assert(possibleResources.size());
+		producedResource = possibleResources[ran()%possibleResources.size()];
+		tempOwner = NEUTRAL_PLAYER;
+		hoverName = VLC->generaltexth->mines[7].first + "\n" + VLC->generaltexth->allTexts[202] + " " + troglodytes.getQuantityTXT(false) + " " + troglodytes.type->namePl;
+	}
 	else
-		ms << " (" << std::pair<ui8,ui32>(6,23+tempOwner) << ")";
-	ms.toString(hoverName);
+	{
+		producedResource = subID;
+
+		MetaString ms;
+		ms << std::pair<ui8,ui32>(9,producedResource);
+		if(tempOwner >= PLAYER_LIMIT)
+			tempOwner = NEUTRAL_PLAYER;	
+		else
+			ms << " (" << std::pair<ui8,ui32>(6,23+tempOwner) << ")";
+		ms.toString(hoverName);
+	}
+
+	producedQuantity = defaultResProduction();
+}
+
+void CGMine::fight(ui32 agreed, const CGHeroInstance *h) const
+{
+	cb->startBattleI(h, this, boost::bind(&CGMine::endBattle, this, _1, h->tempOwner));
+}
+
+void CGMine::endBattle(BattleResult *result, ui8 attackingPlayer) const
+{
+	if(result->winner == 0) //attacker won
+	{
+		if(subID == 7)
+		{
+			InfoWindow iw;
+			iw.player = attackingPlayer;
+			iw.text.addTxt(MetaString::ADVOB_TXT, 85);
+			cb->showInfoDialog(&iw);
+
+		}
+		flagMine(attackingPlayer);
+	}
+}
+
+void CGMine::flagMine(ui8 player) const
+{
+	assert(tempOwner != player);
+	cb->setOwner(id,player); //not ours? flag it!
+
+	MetaString ms;
+	ms << std::pair<ui8,ui32>(9,subID) << "\n(" << std::pair<ui8,ui32>(6,23+player) << ")";
+	if(subID == 7)
+	{
+		ms << "(%s)";
+		ms.addReplacement(MetaString::RES_NAMES, producedResource);
+	}
+	cb->setHoverName(id,&ms);
+
+	InfoWindow iw;
+	iw.soundID = soundBase::FLAGMINE;
+	iw.text.addTxt(MetaString::MINE_EVNTS,producedResource); //not use subID, abandoned mines uses default mine texts
+	iw.player = player;
+	iw.components.push_back(Component(2,producedResource,producedQuantity,-1));
+	cb->showInfoDialog(&iw);
+}
+
+ui32 CGMine::defaultResProduction()
+{
+	switch(producedResource)
+	{
+	case 0: //wood
+	case 2: //ore
+		return 2;
+	case 6: //gold
+		return 1000;
+	default:
+		return 1;
+	}
 }
 
 void CGResource::initObj()

+ 10 - 0
hch/CObjectHandler.h

@@ -818,14 +818,24 @@ public:
 class DLL_EXPORT CGMine : public CArmedInstance
 {
 public: 
+	ui8 producedResource;
+	ui32 producedQuantity;
+
 	void offerLeavingGuards(const CGHeroInstance *h) const;
+	void endBattle(BattleResult *result, ui8 attackingPlayer) const;
+	void fight(ui32 agreed, const CGHeroInstance *h) const;
+
 	void onHeroVisit(const CGHeroInstance * h) const;
+
+	void flagMine(ui8 player) const;
 	void newTurn() const;
 	void initObj();	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CArmedInstance&>(*this);
+		h & producedResource & producedQuantity;
 	}
+	ui32 defaultResProduction();
 };
 
 class DLL_EXPORT CGVisitableOPW : public CGObjectInstance //objects visitable OPW

+ 5 - 0
lib/CCreatureSet.cpp

@@ -285,4 +285,9 @@ ui32 CStackInstance::getMinDamage() const
 ui32 CStackInstance::getMaxDamage() const
 {
 	return type->damageMax + valOfBonuses(Bonus::CREATURE_DAMAGE, 0) + valOfBonuses(Bonus::CREATURE_DAMAGE, 2);
+}
+
+std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const
+{
+	return VLC->generaltexth->arraytxt[174 + getQuantityID()*3 + 2 - capitalized];
 }

+ 1 - 0
lib/CCreatureSet.h

@@ -40,6 +40,7 @@ public:
 	void getParents(TCNodes &out, const CBonusSystemNode *source = NULL) const;  //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
 
 	int getQuantityID() const;
+	std::string getQuantityTXT(bool capitalized = true) const;
 	void init();
 	CStackInstance();
 	CStackInstance(TCreature id, TQuantity count, const CArmedInstance *ArmyObj = NULL);

+ 6 - 1
lib/CGameState.cpp

@@ -1668,6 +1668,11 @@ int CGameState::battleGetBattlefieldType(int3 tile)
 	else if(tile==int3() && !curB)
 		return -1;
 
+	const TerrainTile &t = map->getTile(tile);
+	//fight in mine -> subterranean
+	if(const CGMine *mine = dynamic_cast<const CGMine *>(t.visitableObjects.front()))
+		return 12;
+
 	const std::vector <CGObjectInstance*> & objs = map->objects;
 	for(int g=0; g<objs.size(); ++g)
 	{
@@ -1701,7 +1706,7 @@ int CGameState::battleGetBattlefieldType(int3 tile)
 		}
 	}
 
-	switch(map->terrain[tile.x][tile.y][tile.z].tertype)
+	switch(t.tertype)
 	{
 	case TerrainTile::dirt:
 		return rand()%3+3;

+ 11 - 2
lib/HeroBonus.cpp

@@ -84,13 +84,22 @@ void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector,
 
 void BonusList::limit(const CBonusSystemNode &node)
 {
+limit_start:
 	for(iterator i = begin(); i != end(); i++)
 	{
 		if(i->limiter && i->limiter->limit(*i, node))
 		{
 			iterator toErase = i;
-			i--;
-			erase(toErase);
+			if(i != begin())
+			{
+				i--;
+				erase(toErase);
+			}
+			else
+			{
+				erase(toErase);
+				goto limit_start;
+			}
 		}
 	}
 }

+ 1 - 1
lib/NetPacks.h

@@ -747,7 +747,7 @@ struct InfoWindow : public CPackForClient //103  - displays simple info window
 namespace ObjProperty
 {
 	//TODO: move non general properties out to the appropriate objs classes
-	enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7};
+	enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8};
 }
 
 struct SetObjectProperty : public CPackForClient//1001

+ 1 - 7
lib/map.cpp

@@ -1653,6 +1653,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				break;
 			}
 		case 53: 
+		case 220://mine (?)
 			{
 				nobj = new CGMine();
 				nobj->setOwner(bufor[i++]);
@@ -1672,13 +1673,6 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				nobj = new CGDwelling();
 				break;
 			}
-		case 220://mine (?)
-			{
-				nobj = new CGObjectInstance();
-				nobj->setOwner(bufor[i++]);
-				i+=3;
-				break;
-			}
 		case 88: case 89: case 90: //spell shrine
 			{
 				CGShrine * shr = new CGShrine();