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:
parent
99a7320e99
commit
2f9ed138f6
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
16
CCallback.h
16
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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user