2
0
Эх сурвалжийг харах

Tactics more or less working (some improvements still needed, as proper updating battle GUI).

Michał W. Urbańczyk 14 жил өмнө
parent
commit
2f9ed138f6

+ 1 - 1
AI/GeniusAI/BattleLogic.cpp

@@ -75,7 +75,7 @@ void CBattleLogic::SetCurrentTurn(int turn)
 void CBattleLogic::MakeStatistics(int currentCreatureId)
 {
 	typedef std::vector<const CStack*> vector_stacks;
-	vector_stacks allStacks = m_cb->battleGetStacks(false);
+	vector_stacks allStacks = m_cb->battleGetStacks();
 	const CStack *currentStack = m_cb->battleGetStackByID(currentCreatureId);
 	if(currentStack->position < 0) //turret
 	{

+ 17 - 20
AI/StupidAI/StupidAI.cpp

@@ -105,34 +105,31 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
 	std::vector<int> dists = cb->battleGetDistances(stack);
 	std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
 
-	BOOST_FOREACH(const CStack *s, cb->battleGetStacks())
+	BOOST_FOREACH(const CStack *s, cb->battleGetStacks(IBattleCallback::ONLY_ENEMY))
 	{
-		if(s->owner != stack->owner)
+		if(cb->battleCanShoot(stack, s->position))
 		{
-			if(cb->battleCanShoot(stack, s->position))
-			{
-				enemiesShootable.push_back(s);
-			}
-			else
+			enemiesShootable.push_back(s);
+		}
+		else
+		{
+			BOOST_FOREACH(THex hex, avHexes)
 			{
-				BOOST_FOREACH(THex hex, avHexes)
+				if(CStack::isMeleeAttackPossible(stack, s, hex))
 				{
-					if(CStack::isMeleeAttackPossible(stack, s, hex))
+					std::vector<EnemyInfo>::iterator i = std::find(enemiesReachable.begin(), enemiesReachable.end(), s);
+					if(i == enemiesReachable.end())
 					{
-						std::vector<EnemyInfo>::iterator i = std::find(enemiesReachable.begin(), enemiesReachable.end(), s);
-						if(i == enemiesReachable.end())
-						{
-							enemiesReachable.push_back(s);
-							i = enemiesReachable.begin() + (enemiesReachable.size() - 1);
-						}
-
-						i->attackFrom.push_back(hex);
+						enemiesReachable.push_back(s);
+						i = enemiesReachable.begin() + (enemiesReachable.size() - 1);
 					}
-				}
 
-				if(!vstd::contains(enemiesReachable, s))
-					enemiesUnreachable.push_back(s);
+					i->attackFrom.push_back(hex);
+				}
 			}
+
+			if(!vstd::contains(enemiesReachable, s))
+				enemiesUnreachable.push_back(s);
 		}
 	}
 

+ 7 - 3
CCallback.cpp

@@ -539,10 +539,10 @@ THex CBattleCallback::battleGetPos(int stack)
 	return THex::INVALID;
 }
 
-std::vector<const CStack*> CBattleCallback::battleGetStacks(bool onlyAlive /*= true*/)
+TStacks CBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AND_ENEMY*/, bool onlyAlive /*= true*/)
 {
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	std::vector<const CStack*> ret;
+	TStacks ret;
 	if(!gs->curB) //there is no battle
 	{
 		tlog2<<"battleGetStacks called when there is no battle!"<<std::endl;
@@ -550,8 +550,12 @@ std::vector<const CStack*> CBattleCallback::battleGetStacks(bool onlyAlive /*= t
 	}
 
 	BOOST_FOREACH(const CStack *s, gs->curB->stacks)
-		if(s->alive()  ||  !onlyAlive)
+	{
+		bool ownerMatches = whose == MINE_AND_ENEMY || whose == ONLY_MINE && s->owner == player;
+		bool alivenessMatches = s->alive()  ||  !onlyAlive;
+		if(ownerMatches && alivenessMatches)
 			ret.push_back(s);
+	}
 
 	return ret;
 }

+ 14 - 2
CCallback.h

@@ -44,6 +44,7 @@ struct CGPathNode;
 struct CGPath;
 class CGGarrison;
 class CObstacleInstance;
+typedef std::vector<const CStack*> TStacks;
 
 struct InfoAboutTown
 {
@@ -79,6 +80,11 @@ public:
 		OK, GENERAL_CASTING_PROBLEM, ANOTHER_ELEMENTAL_SUMMONED
 	};
 
+	enum EStackOwnership
+	{
+		ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
+	};
+
 	bool waitTillRealize; //if true, request functions will return after they are realized by server
 	//battle
 	virtual int battleGetBattlefieldType()=0; //   1. sand/shore   2. sand/mesas   3. dirt/birches   4. dirt/hills   5. dirt/pines   6. grass/hills   7. grass/pines   8. lava   9. magic plains   10. snow/mountains   11. snow/trees   12. subterranean   13. swamp/trees   14. fiery fields   15. rock lands   16. magic clouds   17. lucid pools   18. holy ground   19. clover field   20. evil fog   21. "favourable winds" text on magic plains background   22. cursed ground   23. rough   24. ship to ship   25. ship
@@ -88,7 +94,7 @@ public:
 	virtual const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true)=0; //returns stack info by given pos
 	virtual THex battleGetPos(int stack)=0; //returns position (tile ID) of stack
 	virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
-	virtual std::vector<const CStack*> battleGetStacks(bool onlyAlive = true)=0; //returns stacks on battlefield
+	virtual TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true)=0; //returns stacks on battlefield
 	virtual void getStackQueue( std::vector<const CStack *> &out, int howMany )=0; //returns vector of stack in order of their move sequence
 	virtual std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable)=0; //returns numbers of hexes reachable by creature with id ID
 	virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
@@ -108,6 +114,12 @@ public:
 	virtual si8 battleGetTacticDist() =0; //returns tactic distance for calling player or 0 if player is not in tactic phase
 	virtual ui8 battleGetMySide() =0; //return side of player in battle (attacker/defender)
 	virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions
+
+	//convienience methods using the ones above
+	TStacks battleGetAllStacks() //returns all stacks, alive or dead or undead or mechanical :)
+	{
+		return battleGetStacks(MINE_AND_ENEMY, false);
+	}
 };
 
 class ICallback : public virtual IBattleCallback
@@ -220,7 +232,7 @@ public:
 	const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true) OVERRIDE; //returns stack info by given pos
 	THex battleGetPos(int stack) OVERRIDE; //returns position (tile ID) of stack
 	int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
-	std::vector<const CStack*> battleGetStacks(bool onlyAlive = true) OVERRIDE; //returns stacks on battlefield
+	TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) OVERRIDE; //returns stacks on battlefield
 	void getStackQueue( std::vector<const CStack *> &out, int howMany ) OVERRIDE; //returns vector of stack in order of their move sequence
 	std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable) OVERRIDE; //reutrns numbers of hexes reachable by creature with id ID
 	std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory

+ 80 - 33
client/CBattleInterface.cpp

@@ -1134,7 +1134,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 	//initializing armies
 	this->army1 = army1;
 	this->army2 = army2;
-	std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(false);
+	std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks();
 	BOOST_FOREACH(const CStack *s, stacks)
 	{
 		newStack(s);
@@ -1170,8 +1170,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 	}
 	
 	//preparing menu background
-	menu = BitmapHandler::loadBitmap("CBAR.BMP");
-	graphics->blueToPlayersAdv(menu, hero1->tempOwner);
+	//graphics->blueToPlayersAdv(menu, hero1->tempOwner);
 
 	//preparing graphics for displaying amounts of creatures
 	amountNormal = BitmapHandler::loadBitmap("CMNUMWIN.BMP");
@@ -1191,9 +1190,9 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 	transformPalette(amountEffNeutral, 1.00f, 1.00f, 0.18f);
 
 	////blitting menu background and terrain
-	blitAt(background, pos.x, pos.y);
-	blitAt(menu, pos.x, 556 + pos.y);
-	CSDL_Ext::update();
+// 	blitAt(background, pos.x, pos.y);
+// 	blitAt(menu, pos.x, 556 + pos.y);
+// 	CSDL_Ext::update();
 
 	//preparing buttons and console
 	bOptions = new AdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3 + pos.x, 561 + pos.y, "icm003.def", SDLK_o);
@@ -1221,7 +1220,14 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 		btactEnd = new AdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bEndTacticPhase,this), 419 + pos.x, 560 + pos.y, "icm012.def", SDLK_RETURN);
 		bDefence->block(true);
 		bWait->block(true);
+		menu = BitmapHandler::loadBitmap("COPLACBR.BMP");
 	}
+	else
+	{
+		menu = BitmapHandler::loadBitmap("CBAR.BMP");
+		btactEnd = btactNext = NULL;
+	}
+	graphics->blueToPlayersAdv(menu, curInt->playerID);
 
 	//loading hero animations
 	if(hero1) // attacking hero
@@ -1340,18 +1346,11 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 		children.push_back(&bfield[i]);
 	}
 
-	if(curInt->cb->battleGetTacticDist())
+	if(tacticsMode)
 	{
-		BOOST_FOREACH(const CStack *s, curInt->cb->battleGetStacks())
-		{
-			if(s->owner == curInt->playerID)
-			{
-				active = 1;
-				stackActivated(s);
-				active = 0;
-				break;
-			}
-		}
+		active = 1;
+		bTacticNextStack();
+		active = 0;
 	}
 }
 
@@ -1435,8 +1434,6 @@ void CBattleInterface::activate()
 	bSpell->activate();
 	bWait->activate();
 	bDefence->activate();
-	bConsoleUp->activate();
-	bConsoleDown->activate();
 	for(int b=0; b<BFIELD_SIZE; ++b)
 	{
 		bfield[b].activate();
@@ -1448,6 +1445,17 @@ void CBattleInterface::activate()
 	if(curInt->sysOpts.showQueue)
 		queue->activate();
 
+	if(tacticsMode)
+	{
+		btactNext->activate();
+		btactEnd->activate();
+	}
+	else
+	{
+		bConsoleUp->activate();
+		bConsoleDown->activate();
+	}
+
 	LOCPLINT->cingconsole->activate();
 }
 
@@ -1463,8 +1471,6 @@ void CBattleInterface::deactivate()
 	bSpell->deactivate();
 	bWait->deactivate();
 	bDefence->deactivate();
-	bConsoleUp->deactivate();
-	bConsoleDown->deactivate();
 	for(int b=0; b<BFIELD_SIZE; ++b)
 	{
 		bfield[b].deactivate();
@@ -1476,12 +1482,23 @@ void CBattleInterface::deactivate()
 	if(curInt->sysOpts.showQueue)
 		queue->deactivate();
 
+	if(tacticsMode)
+	{
+		btactNext->deactivate();
+		btactEnd->deactivate();
+	}
+	else
+	{
+		bConsoleUp->deactivate();
+		bConsoleDown->deactivate();
+	}
+
 	LOCPLINT->cingconsole->deactivate();
 }
 
 void CBattleInterface::show(SDL_Surface * to)
 {
-	std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(false); //used in a few places
+	std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks(); //used in a few places
 	++animCount;
 	if(!to) //"evaluating" to
 		to = screen;
@@ -1694,7 +1711,18 @@ void CBattleInterface::show(SDL_Surface * to)
 
 	//showing menu background and console
 	blitAt(menu, pos.x, 556 + pos.y, to);
-	console->show(to);
+	
+	if(tacticsMode)
+	{
+		btactNext->show(to);
+		btactEnd->show(to);
+	}
+	else
+	{
+		console->show(to);
+		bConsoleUp->show(to);
+		bConsoleDown->show(to);
+	}
 
 	//showing buttons
 	bOptions->show(to);
@@ -1704,8 +1732,6 @@ void CBattleInterface::show(SDL_Surface * to)
 	bSpell->show(to);
 	bWait->show(to);
 	bDefence->show(to);
-	bConsoleUp->show(to);
-	bConsoleDown->show(to);
 
 	//showing window with result of battle
 	if(resWindow)
@@ -2293,7 +2319,7 @@ void CBattleInterface::stackAttacking( const CStack * attacker, THex dest, const
 void CBattleInterface::newRoundFirst( int round )
 {
 	//handle regeneration
-	std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(false);
+	std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(); //gets only alive stacks
 	BOOST_FOREACH(const CStack *s, stacks)
 	{
 		//don't show animation when no HP is regenerated
@@ -2302,13 +2328,13 @@ void CBattleInterface::newRoundFirst( int round )
 			continue;
 		}
 
-		if( s->hasBonusOfType(Bonus::HP_REGENERATION) && s->alive() )
+		if( s->hasBonusOfType(Bonus::HP_REGENERATION))
 			displayEffect(74, s->position);
 
-		if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 0) && s->alive() )
+		if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 0))
 			displayEffect(4, s->position);
 
-		if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 1) && s->alive() )
+		if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 1))
 			displayEffect(74, s->position);
 	}
 	waitForAnims();
@@ -2358,8 +2384,7 @@ void CBattleInterface::giveCommand(ui8 action, THex tile, ui32 stack, si32 addit
 	{
 		curInt->cb->battleMakeTacticAction(ba);
 		delNull(ba);
-		// TODO:
-		// activate next stack
+		bTacticNextStack();
 	}
 }
 
@@ -3341,6 +3366,23 @@ void CBattleInterface::showQueue()
 
 void CBattleInterface::startAction(const BattleAction* action)
 {
+	if(action->actionType == BattleAction::END_TACTIC_PHASE)
+	{
+		menu = BitmapHandler::loadBitmap("CBAR.bmp");
+		graphics->blueToPlayersAdv(menu, curInt->playerID);
+		if(active)
+		{
+			tacticsMode = false;
+			btactEnd->deactivate();
+			btactNext->deactivate();
+			bConsoleDown->activate();
+			bConsoleUp->activate();
+		}
+		redraw();
+
+		return;
+	}
+
 	const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber);
 
 	if(stack)
@@ -3423,12 +3465,17 @@ void CBattleInterface::bEndTacticPhase()
 {
 	BattleAction endt = BattleAction::makeEndOFTacticPhase(curInt->cb->battleGetMySide());
 	curInt->cb->battleMakeTacticAction(&endt);
-
+	btactEnd->block(true);
 }
 
 void CBattleInterface::bTacticNextStack()
 {
-
+	TStacks stacksOfMine = curInt->cb->battleGetStacks(IBattleCallback::ONLY_MINE);
+	TStacks::iterator it = vstd::find(stacksOfMine, activeStack);
+	if(it != stacksOfMine.end() && ++it != stacksOfMine.end())
+		stackActivated(*it);
+	else
+		stackActivated(stacksOfMine.front());
 }
 
 void CBattleHero::show(SDL_Surface *to)

+ 1 - 1
lib/BattleAction.h

@@ -23,7 +23,7 @@ struct DLL_EXPORT BattleAction
 	{
 		END_TACTIC_PHASE = -2, INVALID = -1, NO_ACTION = 0, HERO_SPELL, WALK, DEFEND, RETREAT, SURRENDER, WALK_AND_ATTACK, SHOOT, WAIT, CATAPULT, MONSTER_SPELL, BAD_MORALE, STACK_HEAL
 	};
-	ui8 actionType; //use ActionType enum for values
+	si8 actionType; //use ActionType enum for values
 		//10 = Monster casts a spell (i.e. Faerie Dragons)	11 - Bad morale freeze	12 - stacks heals another stack
 	THex destinationTile;
 	si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6