Selaa lähdekoodia

- Restored missing code for BattleInfo::getAvaliableHex - Elementals will now be placed correctly
- Fixes for BattleHex::getDistance returning 0 for adjacent hexes
- All stacks will now be placed after obstacles (fixes #1004)
- Removed unused code from ArtHandler

DjWarmonger 13 vuotta sitten
vanhempi
sitoutus
4d62525ff7
3 muutettua tiedostoa jossa 119 lisäystä ja 164 poistoa
  1. 1 1
      lib/BattleHex.cpp
  2. 118 107
      lib/BattleState.cpp
  3. 0 56
      lib/CArtHandler.h

+ 1 - 1
lib/BattleHex.cpp

@@ -81,7 +81,7 @@ char BattleHex::getDistance(BattleHex hex1, BattleHex hex2)
 {
 	int xDst = std::abs(hex1 % GameConstants::BFIELD_WIDTH - hex2 % GameConstants::BFIELD_WIDTH),
 		yDst = std::abs(hex1 / GameConstants::BFIELD_WIDTH - hex2 / GameConstants::BFIELD_WIDTH);
-	return std::max(xDst, yDst) + std::min(xDst, yDst) - (yDst + 1)/2;
+	return std::max(xDst, yDst) + std::min(xDst, yDst) - (yDst + (yDst + xDst < 2 ? 0 : 1))/2;
 }
 
 void BattleHex::checkAndPush(int tile, std::vector<BattleHex> & ret)

+ 118 - 107
lib/BattleState.cpp

@@ -421,8 +421,19 @@ int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initial
 	bool twoHex = VLC->creh->creatures[creID]->isDoubleWide();
 	bool flying = VLC->creh->creatures[creID]->isFlying();
 
+	int pos; 
+	if (initialPos > -1)
+		pos = initialPos;
+	else //summon elementals depending on player side
+	{ 
+ 		if (attackerOwned) 
+	 		pos = 0; //top left 
+ 		else 
+ 			pos = GameConstants::BFIELD_WIDTH - 1; //top right 
+ 	} 
+
 	std::set<BattleHex> occupyable;
-	getAccessibilityMap (ac, twoHex, attackerOwned, false, occupyable, flying);
+	getAccessibilityMap (ac, twoHex, attackerOwned, true, occupyable, flying);
 
 	for (int i = 0; i < GameConstants::BFIELD_SIZE; ++i)
 	{
@@ -432,7 +443,7 @@ int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initial
 	if (!occupyable.size())
 		return -1; //all tiles are covered
 
-	return getClosestTile (attackerOwned, initialPos, occupyable);
+	return getClosestTile (attackerOwned, pos, occupyable);
 }
 
 bool BattleInfo::isStackBlocked(const CStack * stack) const
@@ -1005,7 +1016,7 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerO
 		   (base.armyObj && base.armyObj->tempOwner == owner));
 
 	CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
-	ret->position = position;
+	ret->position = getAvaliableHex (base.getCreatureID(), attackerOwned, position); //TODO: what if no free tile on battlefield was found?
 	return ret;
 }
 CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, int slot, BattleHex position) const
@@ -1648,7 +1659,110 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
 		curB->terrainType = terrain;
 	}
 
-	//reading battleStartpos
+	//setting up siege obstacles
+	if (town && town->hasFort())
+	{
+		for (int b = 0; b < ARRAY_COUNT (curB->si.wallState); ++b)
+		{
+			curB->si.wallState[b] = 1;
+		}
+	}
+
+	//randomize obstacles
+ 	if (town == NULL && !creatureBank) //do it only when it's not siege and not creature bank
+ 	{
+		const int ABSOLUTE_OBSTACLES_COUNT = 34, USUAL_OBSTACLES_COUNT = 91; //shouldn't be changes if we want H3-like obstacle placement
+
+		RandGen r;
+		auto ourRand = [&]{ return r.rand(); };
+		r.srand(tile);
+		r.rand(1,8); //battle sound ID to play... can't do anything with it here
+		int tilesToBlock = r.rand(5,12);
+		const int specialBattlefield = battlefieldTypeToBI(battlefieldType);
+
+		std::vector<BattleHex> blockedTiles;
+
+		auto appropriateAbsoluteObstacle = [&](int id)
+		{
+			return VLC->heroh->absoluteObstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
+		};
+		auto appropriateUsualObstacle = [&](int id) -> bool
+		{
+			return VLC->heroh->obstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
+		};
+
+		if(r.rand(1,100) <= 40) //put cliff-like obstacle
+		{
+			RangeGenerator obidgen(0, ABSOLUTE_OBSTACLES_COUNT-1, ourRand);
+			
+			try
+			{
+				auto obstPtr = make_shared<CObstacleInstance>();
+				obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
+				obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
+				obstPtr->uniqueID = curB->obstacles.size();
+				curB->obstacles.push_back(obstPtr);
+
+				BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
+					blockedTiles.push_back(blocked);
+				tilesToBlock -= VLC->heroh->absoluteObstacles[obstPtr->ID].blockedTiles.size() / 2;
+			}
+			catch(RangeGenerator::ExhaustedPossibilities &)
+			{
+				//silently ignore, if we can't place absolute obstacle, we'll go with the usual ones
+			}
+		}
+
+		RangeGenerator obidgen(0, USUAL_OBSTACLES_COUNT-1, ourRand);
+		try
+		{
+			while(tilesToBlock > 0)
+			{
+				const int obid = obidgen.getSuchNumber(appropriateUsualObstacle);
+				const CObstacleInfo &obi = VLC->heroh->obstacles[obid];
+
+				auto validPosition = [&](BattleHex pos) -> bool
+				{
+					if(obi.height >= pos.getY())
+						return false;
+					if(pos.getX() == 0)
+						return false;
+					if(pos.getX() + obi.width > 15)
+						return false;
+					if(vstd::contains(blockedTiles, pos))
+						return false;
+
+					BOOST_FOREACH(BattleHex blocked, obi.getBlocked(pos))
+					{
+						if(vstd::contains(blockedTiles, blocked))
+							return false;
+						int x = blocked.getX();
+						if(x <= 2 || x >= 14)
+							return false;
+					}
+
+					return true;
+				};
+
+				RangeGenerator posgenerator(18, 168, ourRand);
+
+				auto obstPtr = make_shared<CObstacleInstance>();
+				obstPtr->ID = obid;
+				obstPtr->pos = posgenerator.getSuchNumber(validPosition);
+				obstPtr->uniqueID = curB->obstacles.size();
+				curB->obstacles.push_back(obstPtr);
+
+				BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
+					blockedTiles.push_back(blocked);
+				tilesToBlock -= obi.blockedTiles.size();
+			}
+		}
+		catch(RangeGenerator::ExhaustedPossibilities &)
+		{
+		}
+	}
+
+	//reading battleStartpos - add creatures AFTER random obstacles are generated
 	//TODO: parse once to some structure
 	std::vector< std::vector<int> > attackerLoose, defenderLoose, attackerTight, defenderTight, attackerCreBank, defenderCreBank;
 	std::vector <int> commanderField, commanderBank;
@@ -1802,109 +1916,6 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
 
 	std::stable_sort(stacks.begin(),stacks.end(),cmpst);
 
-	//setting up siege
-	if(town && town->hasFort())
-	{
-		for(int b=0; b<ARRAY_COUNT(curB->si.wallState); ++b)
-		{
-			curB->si.wallState[b] = 1;
-		}
-	}
-
-	//randomize obstacles
- 	if(town == NULL && !creatureBank) //do it only when it's not siege and not creature bank
- 	{
-		const int ABSOLUTE_OBSTACLES_COUNT = 34, USUAL_OBSTACLES_COUNT = 91; //shouldn't be changes if we want H3-like obstacle placement
-
-		RandGen r;
-		auto ourRand = [&]{ return r.rand(); };
-		r.srand(tile);
-		r.rand(1,8); //battle sound ID to play... can't do anything with it here
-		int tilesToBlock = r.rand(5,12);
-		const int specialBattlefield = battlefieldTypeToBI(battlefieldType);
-
-		std::vector<BattleHex> blockedTiles;
-
-		auto appropriateAbsoluteObstacle = [&](int id)
-		{
-			return VLC->heroh->absoluteObstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
-		};
-		auto appropriateUsualObstacle = [&](int id) -> bool
-		{
-			return VLC->heroh->obstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
-		};
-
-		if(r.rand(1,100) <= 40) //put cliff-like obstacle
-		{
-			RangeGenerator obidgen(0, ABSOLUTE_OBSTACLES_COUNT-1, ourRand);
-			
-			try
-			{
-				auto obstPtr = make_shared<CObstacleInstance>();
-				obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
-				obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
-				obstPtr->uniqueID = curB->obstacles.size();
-				curB->obstacles.push_back(obstPtr);
-
-				BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
-					blockedTiles.push_back(blocked);
-				tilesToBlock -= VLC->heroh->absoluteObstacles[obstPtr->ID].blockedTiles.size() / 2;
-			}
-			catch(RangeGenerator::ExhaustedPossibilities &)
-			{
-				//silently ignore, if we can't place absolute obstacle, we'll go with the usual ones
-			}
-		}
-
-		RangeGenerator obidgen(0, USUAL_OBSTACLES_COUNT-1, ourRand);
-		try
-		{
-			while(tilesToBlock > 0)
-			{
-				const int obid = obidgen.getSuchNumber(appropriateUsualObstacle);
-				const CObstacleInfo &obi = VLC->heroh->obstacles[obid];
-
-				auto validPosition = [&](BattleHex pos) -> bool
-				{
-					if(obi.height >= pos.getY())
-						return false;
-					if(pos.getX() == 0)
-						return false;
-					if(pos.getX() + obi.width > 15)
-						return false;
-					if(vstd::contains(blockedTiles, pos))
-						return false;
-
-					BOOST_FOREACH(BattleHex blocked, obi.getBlocked(pos))
-					{
-						if(vstd::contains(blockedTiles, blocked))
-							return false;
-						int x = blocked.getX();
-						if(x <= 2 || x >= 14)
-							return false;
-					}
-
-					return true;
-				};
-
-				RangeGenerator posgenerator(18, 168, ourRand);
-
-				auto obstPtr = make_shared<CObstacleInstance>();
-				obstPtr->ID = obid;
-				obstPtr->pos = posgenerator.getSuchNumber(validPosition);
-				obstPtr->uniqueID = curB->obstacles.size();
-				curB->obstacles.push_back(obstPtr);
-
-				BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
-					blockedTiles.push_back(blocked);
-				tilesToBlock -= obi.blockedTiles.size();
-			}
-		}
-		catch(RangeGenerator::ExhaustedPossibilities &)
-		{
-		}
-	}
-
 	//spell level limiting bonus
 	curB->addNewBonus(new Bonus(Bonus::ONE_BATTLE, Bonus::LEVEL_SPELL_IMMUNITY, Bonus::OTHER,
 		0, -1, -1, Bonus::INDEPENDENT_MAX));

+ 0 - 56
lib/CArtHandler.h

@@ -161,62 +161,6 @@ public:
 	}
 };
 
-// class DLL_LINKAGE IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner
-// { //used only for dynamic cast :P
-// public:
-// 	si32 ID; //used for smart serialization
-// 
-// 	template <typename Handler> void serialize(Handler &h, const int version)
-// 	{
-// 		h & static_cast<CArtifact&>(*this);
-// 		h & ID;
-// 	}
-// };
-// 
-// class DLL_LINKAGE CScroll : public IModableArt // Spell Scroll
-// {
-// public:
-// 	CScroll(){spellid=0;};
-// 	CScroll(spelltype sid){spellid = sid;};
-// 	spelltype spellid;
-// 	void Init();
-// 	void SetProperty (int mod){spellid = mod;};
-// 	template <typename Handler> void serialize(Handler &h, const int version)
-// 	{
-// 		h & static_cast<IModableArt&>(*this);
-// 		h & spellid;
-// 	}
-// };
-// 
-// class DLL_LINKAGE CCustomizableArt : public IModableArt // Warlord's Banner with multiple options
-// {
-// public:
-// 	ui8 mode;
-// 	CCustomizableArt(){mode=0;};
-// 	void Init(){};
-// 	void SetProperty (int mod){};
-// 	template <typename Handler> void serialize(Handler &h, const int version)
-// 	{
-// 		h & static_cast<IModableArt&>(*this);
-// 		h & mode;
-// 	}
-// };
-// 
-// class DLL_LINKAGE CCommanderArt : public IModableArt // Growing with time
-// {
-// public:
-// 	ui32 level;
-// 	CCommanderArt(){level = 0;};
-// 	void Init(){};
-// 	void SetProperty (int mod){level = mod;};
-// 	void Upgrade(){level++;};
-// 	template <typename Handler> void serialize(Handler &h, const int version)
-// 	{
-// 		h & static_cast<IModableArt&>(*this);
-// 		h & level;
-// 	}
-// };
-
 class DLL_LINKAGE CArtHandler //handles artifacts
 {
 	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER, ILimiter * limiter = NULL, int additionalinfo = 0);