Browse Source

Fixed crash occurring after casting Armageddon and killing all stacks.
Removed some commented-out code.

Michał W. Urbańczyk 13 years ago
parent
commit
5a157290d9
3 changed files with 17 additions and 236 deletions
  1. 9 2
      client/BattleInterface/CBattleInterfaceClasses.cpp
  2. 0 201
      lib/BattleState.cpp
  3. 8 33
      lib/CBattleCallback.cpp

+ 9 - 2
client/BattleInterface/CBattleInterfaceClasses.cpp

@@ -614,9 +614,16 @@ void CStackQueue::update()
 {
 	stacksSorted.clear();
 	owner->curInt->cb->battleGetStackQueue(stacksSorted, stackBoxes.size());
-	for (int i = 0; i < stackBoxes.size() ; i++)
+	if(stacksSorted.size())
 	{
-		stackBoxes[i]->setStack(stacksSorted[i]);
+		for (int i = 0; i < stackBoxes.size() ; i++)
+		{
+			stackBoxes[i]->setStack(stacksSorted[i]);
+		}
+	}
+	else
+	{
+		//no stacks on battlefield... what to do with queue?
 	}
 }
 

+ 0 - 201
lib/BattleState.cpp

@@ -36,157 +36,6 @@ const CStack * BattleInfo::getNextStack() const
 		return NULL;
 }
 
-
-// const CStack * BattleInfo::getStackT(BattleHex tileID, bool onlyAlive) const
-// {
-// 	return const_cast<BattleInfo * const>(this)->getStackT(tileID, onlyAlive);
-// }
-
-// void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<BattleHex> & occupyable, bool flying, const CStack * stackToOmmit) const
-// {
-// 	memset(accessibility, 1, GameConstants::BFIELD_SIZE); //initialize array with trues
-//
-// 	//removing accessibility for side columns of hexes
-// 	for(int v = 0; v < GameConstants::BFIELD_SIZE; ++v)
-// 	{
-// 		if( v % GameConstants::BFIELD_WIDTH == 0 || v % GameConstants::BFIELD_WIDTH == (GameConstants::BFIELD_WIDTH - 1) )
-// 			accessibility[v] = false;
-// 	}
-//
-// 	for(ui32 g=0; g<stacks.size(); ++g)
-// 	{
-// 		if(!stacks[g]->alive() || (stackToOmmit && stacks[g]->ID==stackToOmmit->ID) || stacks[g]->position < 0) //we don't want to lock position of this stack (eg. if it's a turret)
-// 			continue;
-//
-// 		accessibility[stacks[g]->position] = false;
-// 		if(stacks[g]->doubleWide()) //if it's a double hex creature
-// 		{
-// 			if(stacks[g]->attackerOwned)
-// 				accessibility[stacks[g]->position-1] = false;
-// 			else
-// 				accessibility[stacks[g]->position+1] = false;
-// 		}
-// 	}
-// 	//obstacles
-// 	BOOST_FOREACH(const auto &obstacle, obstacles)
-// 	{
-// 		BOOST_FOREACH(BattleHex hex, obstacle->getBlockedTiles())
-// 		{
-// 			assert(hex.isValid());
-// 			accessibility[hex] = false;
-// 		}
-// 	}
-//
-// 	//walls
-// 	if(siege > 0)
-// 	{
-// 		static const int permanentlyLocked[] = {12, 45, 78, 112, 147, 165};
-// 		for(int b=0; b<ARRAY_COUNT(permanentlyLocked); ++b)
-// 		{
-// 			accessibility[permanentlyLocked[b]] = false;
-// 		}
-//
-// 		static const std::pair<int, BattleHex> lockedIfNotDestroyed[] = //(which part of wall, which hex is blocked if this part of wall is not destroyed
-// 			{std::make_pair(2, BattleHex(182)), std::make_pair(3, BattleHex(130)),
-// 			std::make_pair(4, BattleHex(62)), std::make_pair(5, BattleHex(29))};
-// 		for(int b=0; b<ARRAY_COUNT(lockedIfNotDestroyed); ++b)
-// 		{
-// 			if(si.wallState[lockedIfNotDestroyed[b].first] < 3)
-// 			{
-// 				accessibility[lockedIfNotDestroyed[b].second] = false;
-// 			}
-// 		}
-//
-// 		//gate
-// 		if(attackerOwned && si.wallState[7] < 3) //if it attacker's unit and gate is not destroyed
-// 		{
-// 			accessibility[95] = accessibility[96] = false; //block gate's hexes
-// 		}
-// 	}
-//
-// 	//occupyability
-// 	if(addOccupiable && twoHex)
-// 	{
-// 		std::set<BattleHex> rem; //tiles to unlock
-// 		for(int h=0; h<GameConstants::BFIELD_HEIGHT; ++h)
-// 		{
-// 			for(int w=1; w<GameConstants::BFIELD_WIDTH-1; ++w)
-// 			{
-// 				BattleHex hex(w, h);
-// 				if(!isAccessible(hex, accessibility, twoHex, attackerOwned, flying, true)
-// 					&& (attackerOwned ? isAccessible(hex+1, accessibility, twoHex, attackerOwned, flying, true) : isAccessible(hex-1, accessibility, twoHex, attackerOwned, flying, true) )
-// 					)
-// 					rem.insert(hex);
-// 			}
-// 		}
-// 		occupyable = rem;
-// 		/*for(std::set<int>::const_iterator it = rem.begin(); it != rem.end(); ++it)
-// 		{
-// 			accessibility[*it] = true;
-// 		}*/
-// 	}
-// }
-
-// bool BattleInfo::isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos)
-// {
-// 	if(flying && !lastPos)
-// 		return true;
-//
-// 	if(twoHex)
-// 	{
-// 		//if given hex is accessible and appropriate adjacent one is free too
-// 		return accessibility[hex] && accessibility[hex + (attackerOwned ? -1 : 1 )];
-// 	}
-// 	else
-// 	{
-// 		return accessibility[hex];
-// 	}
-// }
-
-// void BattleInfo::makeBFS(BattleHex start, bool *accessibility, BattleHex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const //both pointers must point to the at least 187-elements int arrays
-// {
-// 	std::set<BattleHex> quicksands = getStoppers(!attackerOwned);
-//
-// 	//inits
-// 	for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
-// 		predecessor[b] = -1;
-// 	for(int g=0; g<GameConstants::BFIELD_SIZE; ++g)
-// 		dists[g] = 100000000;
-//
-// 	std::queue< std::pair<BattleHex, bool> > hexq; //bfs queue <hex, accessible> (second filed used only if fillPredecessors is true)
-// 	hexq.push(std::make_pair(start, true));
-// 	dists[hexq.front().first] = 0;
-// 	int curNext = -1; //for bfs loop only (helper var)
-// 	while(!hexq.empty()) //bfs loop
-// 	{
-// 		std::pair<BattleHex, bool> curHex = hexq.front();
-// 		std::vector<BattleHex> neighbours = curHex.first.neighbouringTiles();
-// 		hexq.pop();
-// 		if(curHex.first != start && !flying && vstd::contains(quicksands, curHex.first)) //walking stack can't step past the quicksands
-// 			continue;
-//
-// 		for(ui32 nr=0; nr<neighbours.size(); nr++)
-// 		{
-// 			curNext = neighbours[nr]; //if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
-// 			bool accessible = isAccessible(curNext, accessibility, twoHex, attackerOwned, flying, dists[curHex.first]+1 == dists[curNext]);
-// 			if( dists[curHex.first]+1 >= dists[curNext] )
-// 				continue;
-// 			if(accessible && curHex.second)
-// 			{
-// 				hexq.push(std::make_pair(curNext, true));
-// 				dists[curNext] = dists[curHex.first] + 1;
-// 			}
-// 			else if(fillPredecessors && !(accessible && !curHex.second))
-// 			{
-// 				hexq.push(std::make_pair(curNext, false));
-// 				dists[curNext] = dists[curHex.first] + 1;
-// 			}
-// 			predecessor[curNext] = curHex.first;
-// 		}
-// 	}
-// };
-//
-
 BattleHex BattleInfo::getClosestTile(bool attackerOwned, BattleHex initialPos, std::set<BattleHex> & possibilities) const
 {
 	std::vector<BattleHex> sortedTiles (possibilities.begin(), possibilities.end()); //set can't be sorted properly :(
@@ -460,56 +309,6 @@ CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool at
 	return ret;
 }
 
-// std::pair<const CStack *, BattleHex> BattleInfo::getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const
-// {
-// 	bool ac[GameConstants::BFIELD_SIZE];
-// 	std::set<BattleHex> occupyable;
-//
-// 	getAccessibilityMap(ac, closest->doubleWide(), closest->attackerOwned, false, occupyable, closest->hasBonusOfType(Bonus::FLYING), closest);
-//
-// 	BattleHex predecessor[GameConstants::BFIELD_SIZE];
-// 	int dist[GameConstants::BFIELD_SIZE];
-// 	makeBFS(closest->position, ac, predecessor, dist, closest->doubleWide(), closest->attackerOwned, closest->hasBonusOfType(Bonus::FLYING), true);
-//
-// 	std::vector< std::pair< std::pair<int, int>, const CStack *> > stackPairs; //pairs <<distance, hex>, stack>
-// 	for(int g=0; g<GameConstants::BFIELD_SIZE; ++g)
-// 	{
-// 		const CStack * atG = getStackT(g);
-// 		if(!atG || atG->ID == closest->ID) //if there is not stack or we are the closest one
-// 			continue;
-// 		if(boost::logic::indeterminate(attackerOwned) || atG->attackerOwned == attackerOwned)
-// 		{
-// 			if(predecessor[g] == -1) //TODO: is it really the best solution?
-// 				continue;
-// 			stackPairs.push_back( std::make_pair( std::make_pair(dist[predecessor[g]], g), atG) );
-// 		}
-// 	}
-//
-// 	if(stackPairs.size() > 0)
-// 	{
-// 		std::vector< std::pair< std::pair<int, int>, const CStack *> > minimalPairs;
-// 		minimalPairs.push_back(stackPairs[0]);
-//
-// 		for(int b=1; b<stackPairs.size(); ++b)
-// 		{
-// 			if(stackPairs[b].first.first < minimalPairs[0].first.first)
-// 			{
-// 				minimalPairs.clear();
-// 				minimalPairs.push_back(stackPairs[b]);
-// 			}
-// 			else if(stackPairs[b].first.first == minimalPairs[0].first.first)
-// 			{
-// 				minimalPairs.push_back(stackPairs[b]);
-// 			}
-// 		}
-//
-// 		std::pair< std::pair<int, int>, const CStack *> minPair = minimalPairs[minimalPairs.size()/2];
-//
-// 		return std::make_pair(minPair.second, predecessor[minPair.first.second]);
-// 	}
-//
-// 	return std::make_pair<const CStack * , BattleHex>(NULL, BattleHex::INVALID);
-// }
 ui32 BattleInfo::calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const
 {
 	ui32 ret = baseDamage;

+ 8 - 33
lib/CBattleCallback.cpp

@@ -405,39 +405,6 @@ si8 CBattleInfoCallback::battleCanTeleportTo(const CStack * stack, BattleHex des
 	return true;
 }
 
-// std::vector<int> CBattleInfoCallback::battleGetDistances(const CStack * stack, BattleHex hex /*= BattleHex::INVALID*/, BattleHex * predecessors /*= NULL*/)
-// {
-// 	// FIXME - This method is broken, hex argument is not used. However AI depends on that wrong behaviour.
-//
-// 	if(!hex.isValid())
-// 		hex = stack->position;
-//
-// 	std::vector<int> ret(GameConstants::BFIELD_SIZE, -1); //fill initial ret with -1's
-//
-// 	if(!hex.isValid()) //stack has bad position? probably castle turret, return initial values (they can't move)
-// 		return ret;
-//
-// 	bool ac[GameConstants::BFIELD_SIZE] = {0};
-// 	std::set<BattleHex> occupyable;
-// 	getBattle()->getAccessibilityMap(ac, stack->doubleWide(), stack->attackerOwned, false, occupyable, stack->hasBonusOfType(Bonus::FLYING), stack);
-// 	BattleHex pr[GameConstants::BFIELD_SIZE];
-// 	int dist[GameConstants::BFIELD_SIZE];
-// 	getBattle()->makeBFS(stack->position, ac, pr, dist, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), false);
-//
-// 	for(int i=0; i<GameConstants::BFIELD_SIZE; ++i)
-// 	{
-// 		if(pr[i] != -1)
-// 			ret[i] = dist[i];
-// 	}
-//
-// 	if(predecessors)
-// 	{
-// 		memcpy(predecessors, pr, GameConstants::BFIELD_SIZE * sizeof(BattleHex));
-// 	}
-//
-// 	return ret;
-// }
-
 std::set<BattleHex> CBattleInfoCallback::battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos  /*= BattleHex::INVALID*/) const
 {
 	std::set<BattleHex> attackedHexes;
@@ -564,6 +531,14 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
 			return;
 	}
 
+	auto allStacks = battleGetAllStacks();
+	if(!vstd::contains_if(allStacks, [](const CStack *stack) { return stack->willMove(100000); })) //little evil, but 100000 should be enough for all effects to disappear
+	{
+		//No stack will be able to move, battle is over.
+		out.clear();
+		return;
+	}
+
 	BOOST_FOREACH(auto s, battleGetAllStacks())
 	{
 		if((turn <= 0 && !s->willMove()) //we are considering current round and stack won't move