1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

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

This commit is contained in:
Michał W. Urbańczyk 2011-02-14 20:31:53 +00:00
parent 99a7320e99
commit 2f9ed138f6
6 changed files with 120 additions and 60 deletions

View File

@ -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
{

View File

@ -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
{
BOOST_FOREACH(THex hex, avHexes)
{
enemiesShootable.push_back(s);
}
else
{
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);
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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