mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Quick Combat system setting works… if user doesn't click in the meantime.
This commit is contained in:
@@ -66,6 +66,15 @@
|
|||||||
// They do not own any mutexes intiially.
|
// They do not own any mutexes intiially.
|
||||||
#define THREAD_CREATED_BY_CLIENT
|
#define THREAD_CREATED_BY_CLIENT
|
||||||
|
|
||||||
|
#define RETURN_IF_QUICK_COMBAT \
|
||||||
|
if(isAutoFightOn) \
|
||||||
|
return;
|
||||||
|
|
||||||
|
#define BATTLE_EVENT_POSSIBLE_RETURN\
|
||||||
|
if(LOCPLINT != this) \
|
||||||
|
return; \
|
||||||
|
RETURN_IF_QUICK_COMBAT
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
using namespace CSDL_Ext;
|
using namespace CSDL_Ext;
|
||||||
|
|
||||||
@@ -600,12 +609,19 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
|
|||||||
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
|
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
if(settings["adventure"]["quickCombat"].Bool())
|
||||||
{ //another local interface should do this
|
{
|
||||||
return;
|
autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
||||||
|
autofightingAI->init(cb);
|
||||||
|
autofightingAI->battleStart(army1, army2, int3(0,0,0), hero1, hero2, side);
|
||||||
|
isAutoFightOn = true;
|
||||||
|
cb->registerBattleInterface(autofightingAI);
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForAllDialogs();
|
waitForAllDialogs();
|
||||||
|
|
||||||
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
|
|
||||||
GH.pushInt(battleInt);
|
GH.pushInt(battleInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,10 +629,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
|
|||||||
void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)
|
void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int b=0; b<healedStacks.size(); ++b)
|
for(int b=0; b<healedStacks.size(); ++b)
|
||||||
{
|
{
|
||||||
@@ -663,10 +676,7 @@ void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, u
|
|||||||
void CPlayerInterface::battleNewStackAppeared(const CStack * stack)
|
void CPlayerInterface::battleNewStackAppeared(const CStack * stack)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->newStack(stack);
|
battleInt->newStack(stack);
|
||||||
}
|
}
|
||||||
@@ -674,10 +684,7 @@ void CPlayerInterface::battleNewStackAppeared(const CStack * stack)
|
|||||||
void CPlayerInterface::battleObstaclesRemoved(const std::set<si32> & removedObstacles)
|
void CPlayerInterface::battleObstaclesRemoved(const std::set<si32> & removedObstacles)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for(std::set<si32>::const_iterator it = removedObstacles.begin(); it != removedObstacles.end(); ++it)
|
// for(std::set<si32>::const_iterator it = removedObstacles.begin(); it != removedObstacles.end(); ++it)
|
||||||
// {
|
// {
|
||||||
@@ -697,10 +704,7 @@ void CPlayerInterface::battleObstaclesRemoved(const std::set<si32> & removedObst
|
|||||||
void CPlayerInterface::battleCatapultAttacked(const CatapultAttack & ca)
|
void CPlayerInterface::battleCatapultAttacked(const CatapultAttack & ca)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->stackIsCatapulting(ca);
|
battleInt->stackIsCatapulting(ca);
|
||||||
}
|
}
|
||||||
@@ -708,10 +712,7 @@ void CPlayerInterface::battleCatapultAttacked(const CatapultAttack & ca)
|
|||||||
void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr)
|
void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::set<ui32>::const_iterator it = bsr.stackIDs.begin(); it != bsr.stackIDs.end(); ++it) //for each removed stack
|
for(std::set<ui32>::const_iterator it = bsr.stackIDs.begin(); it != bsr.stackIDs.end(); ++it) //for each removed stack
|
||||||
{
|
{
|
||||||
@@ -723,10 +724,7 @@ void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr)
|
|||||||
void CPlayerInterface::battleNewRound(int round) //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
void CPlayerInterface::battleNewRound(int round) //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->newRound(round);
|
battleInt->newRound(round);
|
||||||
}
|
}
|
||||||
@@ -734,10 +732,7 @@ void CPlayerInterface::battleNewRound(int round) //called at the beginning of ea
|
|||||||
void CPlayerInterface::actionStarted(const BattleAction &action)
|
void CPlayerInterface::actionStarted(const BattleAction &action)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
curAction = new BattleAction(action);
|
curAction = new BattleAction(action);
|
||||||
battleInt->startAction(curAction);
|
battleInt->startAction(curAction);
|
||||||
@@ -746,10 +741,7 @@ void CPlayerInterface::actionStarted(const BattleAction &action)
|
|||||||
void CPlayerInterface::actionFinished(const BattleAction &action)
|
void CPlayerInterface::actionFinished(const BattleAction &action)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->endAction(curAction);
|
battleInt->endAction(curAction);
|
||||||
delete curAction;
|
delete curAction;
|
||||||
@@ -760,6 +752,23 @@ BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when i
|
|||||||
{
|
{
|
||||||
THREAD_CREATED_BY_CLIENT;
|
THREAD_CREATED_BY_CLIENT;
|
||||||
logGlobal->traceStream() << "Awaiting command for " << stack->nodeName();
|
logGlobal->traceStream() << "Awaiting command for " << stack->nodeName();
|
||||||
|
|
||||||
|
if(autofightingAI)
|
||||||
|
{
|
||||||
|
if(isAutoFightOn)
|
||||||
|
{
|
||||||
|
assert(autofightingAI);
|
||||||
|
auto ret = autofightingAI->activeStack(stack);
|
||||||
|
if(isAutoFightOn)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb->unregisterBattleInterface(autofightingAI);
|
||||||
|
autofightingAI = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
CBattleInterface *b = battleInt;
|
CBattleInterface *b = battleInt;
|
||||||
|
|
||||||
assert(!b->givenCommand->get()); //command buffer must be clean (we don't want to use old command)
|
assert(!b->givenCommand->get()); //command buffer must be clean (we don't want to use old command)
|
||||||
@@ -790,56 +799,56 @@ BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when i
|
|||||||
void CPlayerInterface::battleEnd(const BattleResult *br)
|
void CPlayerInterface::battleEnd(const BattleResult *br)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
if(isAutoFightOn)
|
||||||
{ //another local interface should do this
|
{
|
||||||
|
isAutoFightOn = false;
|
||||||
|
cb->unregisterBattleInterface(autofightingAI);
|
||||||
|
autofightingAI = nullptr;
|
||||||
|
|
||||||
|
SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
|
||||||
|
auto resWindow = new CBattleResultWindow(*br, temp_rect, *this);
|
||||||
|
GH.pushInt(resWindow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
|
|
||||||
battleInt->battleFinished(*br);
|
battleInt->battleFinished(*br);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance)
|
void CPlayerInterface::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->stackMoved(stack, dest, distance);
|
battleInt->stackMoved(stack, dest, distance);
|
||||||
}
|
}
|
||||||
void CPlayerInterface::battleSpellCast( const BattleSpellCast *sc )
|
void CPlayerInterface::battleSpellCast( const BattleSpellCast *sc )
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->spellCast(sc);
|
battleInt->spellCast(sc);
|
||||||
}
|
}
|
||||||
void CPlayerInterface::battleStacksEffectsSet( const SetStackEffect & sse )
|
void CPlayerInterface::battleStacksEffectsSet( const SetStackEffect & sse )
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->battleStacksEffectsSet(sse);
|
battleInt->battleStacksEffectsSet(sse);
|
||||||
}
|
}
|
||||||
void CPlayerInterface::battleTriggerEffect (const BattleTriggerEffect & bte)
|
void CPlayerInterface::battleTriggerEffect (const BattleTriggerEffect & bte)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
|
//TODO why is this different (no return on LOPLINT != this) ?
|
||||||
|
|
||||||
|
RETURN_IF_QUICK_COMBAT;
|
||||||
battleInt->battleTriggerEffect(bte);
|
battleInt->battleTriggerEffect(bte);
|
||||||
}
|
}
|
||||||
void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa)
|
void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<StackAttackedInfo> arg;
|
std::vector<StackAttackedInfo> arg;
|
||||||
for(std::vector<BattleStackAttacked>::const_iterator i = bsa.begin(); i != bsa.end(); i++)
|
for(std::vector<BattleStackAttacked>::const_iterator i = bsa.begin(); i != bsa.end(); i++)
|
||||||
@@ -866,10 +875,7 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
|||||||
void CPlayerInterface::battleAttack(const BattleAttack *ba)
|
void CPlayerInterface::battleAttack(const BattleAttack *ba)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(curAction);
|
assert(curAction);
|
||||||
if(ba->lucky()) //lucky hit
|
if(ba->lucky()) //lucky hit
|
||||||
@@ -938,10 +944,7 @@ void CPlayerInterface::battleAttack(const BattleAttack *ba)
|
|||||||
void CPlayerInterface::battleObstaclePlaced(const CObstacleInstance &obstacle)
|
void CPlayerInterface::battleObstaclePlaced(const CObstacleInstance &obstacle)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->obstaclePlaced(obstacle);
|
battleInt->obstaclePlaced(obstacle);
|
||||||
}
|
}
|
||||||
@@ -2236,10 +2239,7 @@ void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
|
|||||||
void CPlayerInterface::battleNewRoundFirst( int round )
|
void CPlayerInterface::battleNewRoundFirst( int round )
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
if(LOCPLINT != this)
|
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||||
{ //another local interface should do this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
battleInt->newRoundFirst(round);
|
battleInt->newRoundFirst(round);
|
||||||
}
|
}
|
||||||
|
@@ -111,6 +111,11 @@ public:
|
|||||||
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
|
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
|
||||||
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
|
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
|
||||||
|
|
||||||
|
//During battle is quick combat mode is used
|
||||||
|
shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
|
||||||
|
bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
|
||||||
|
|
||||||
|
|
||||||
struct SpellbookLastSetting
|
struct SpellbookLastSetting
|
||||||
{
|
{
|
||||||
int spellbookLastPageBattle, spellbokLastPageAdvmap; //on which page we left spellbook
|
int spellbookLastPageBattle, spellbokLastPageAdvmap; //on which page we left spellbook
|
||||||
|
@@ -579,16 +579,17 @@ void CClient::battleStarted(const BattleInfo * info)
|
|||||||
// if(battleCallbacks.count(side))
|
// if(battleCallbacks.count(side))
|
||||||
// battleCallbacks[side]->setBattle(info);
|
// battleCallbacks[side]->setBattle(info);
|
||||||
|
|
||||||
shared_ptr<CPlayerInterface> att, def;
|
shared_ptr<CPlayerInterface> att = nullptr, def = nullptr;
|
||||||
|
|
||||||
|
//If quick combat is not, do not prepare interfaces for battleint
|
||||||
|
if(!settings["adventure"]["quickCombat"].Bool())
|
||||||
|
{
|
||||||
if(vstd::contains(playerint, info->sides[0]) && playerint[info->sides[0]]->human)
|
if(vstd::contains(playerint, info->sides[0]) && playerint[info->sides[0]]->human)
|
||||||
att = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[0]] );
|
att = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[0]] );
|
||||||
else
|
|
||||||
att = NULL;
|
|
||||||
|
|
||||||
if(vstd::contains(playerint, info->sides[1]) && playerint[info->sides[1]]->human)
|
if(vstd::contains(playerint, info->sides[1]) && playerint[info->sides[1]]->human)
|
||||||
def = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[1]] );
|
def = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[1]] );
|
||||||
else
|
}
|
||||||
def = NULL;
|
|
||||||
|
|
||||||
if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL))
|
if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL))
|
||||||
{
|
{
|
||||||
|
@@ -97,7 +97,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
|||||||
currentlyHoveredHex(-1), attackingHex(-1), tacticianInterface(NULL), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(NULL), sp(NULL),
|
currentlyHoveredHex(-1), attackingHex(-1), tacticianInterface(NULL), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(NULL), sp(NULL),
|
||||||
siegeH(NULL), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0),
|
siegeH(NULL), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0),
|
||||||
givenCommand(NULL), myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL),
|
givenCommand(NULL), myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL),
|
||||||
autofightingAI(nullptr), isAutoFightOn(false), aiThread(nullptr), background(nullptr)
|
background(nullptr)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION;
|
OBJ_CONSTRUCTION;
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@ void CBattleInterface::setPrintMouseShadow(bool set)
|
|||||||
|
|
||||||
void CBattleInterface::activate()
|
void CBattleInterface::activate()
|
||||||
{
|
{
|
||||||
if(isAutoFightOn)
|
if(curInt->isAutoFightOn)
|
||||||
{
|
{
|
||||||
bAutofight->activate();
|
bAutofight->activate();
|
||||||
return;
|
return;
|
||||||
@@ -1277,23 +1277,23 @@ void CBattleInterface::bAutofightf()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
//Stop auto-fight mode
|
//Stop auto-fight mode
|
||||||
if(isAutoFightOn)
|
if(curInt->isAutoFightOn)
|
||||||
{
|
{
|
||||||
assert(autofightingAI);
|
assert(curInt->autofightingAI);
|
||||||
isAutoFightOn = false;
|
curInt->isAutoFightOn = false;
|
||||||
logGlobal->traceStream() << "Stopping the autofight...";
|
logGlobal->traceStream() << "Stopping the autofight...";
|
||||||
aiThread->interrupt();
|
|
||||||
aiThread->join();
|
|
||||||
|
|
||||||
autofightingAI = nullptr;
|
|
||||||
aiThread = nullptr;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isAutoFightOn = true;
|
curInt->isAutoFightOn = true;
|
||||||
autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
deactivate();
|
||||||
autofightingAI->init(curInt->cb);
|
bAutofight->activate();
|
||||||
autofightingAI->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide());
|
|
||||||
|
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
||||||
|
ai->init(curInt->cb);
|
||||||
|
ai->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide());
|
||||||
|
curInt->autofightingAI = ai;
|
||||||
|
curInt->cb->registerBattleInterface(ai);
|
||||||
|
|
||||||
requestAutofightingAIToTakeAction();
|
requestAutofightingAIToTakeAction();
|
||||||
}
|
}
|
||||||
@@ -1627,7 +1627,7 @@ void CBattleInterface::displayBattleFinished()
|
|||||||
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
|
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
|
||||||
|
|
||||||
SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
|
SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
|
||||||
resWindow = new CBattleResultWindow(*bresult, temp_rect, this);
|
resWindow = new CBattleResultWindow(*bresult, temp_rect, *this->curInt);
|
||||||
GH.pushInt(resWindow);
|
GH.pushInt(resWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2096,9 +2096,6 @@ void CBattleInterface::activateStack()
|
|||||||
if(!pendingAnims.size() && !active)
|
if(!pendingAnims.size() && !active)
|
||||||
activate();
|
activate();
|
||||||
|
|
||||||
if(isAutoFightOn)
|
|
||||||
requestAutofightingAIToTakeAction();
|
|
||||||
|
|
||||||
GH.fakeMouseMove();
|
GH.fakeMouseMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3590,20 +3587,23 @@ InfoAboutHero CBattleInterface::enemyHero() const
|
|||||||
|
|
||||||
void CBattleInterface::requestAutofightingAIToTakeAction()
|
void CBattleInterface::requestAutofightingAIToTakeAction()
|
||||||
{
|
{
|
||||||
assert(isAutoFightOn);
|
assert(curInt->isAutoFightOn);
|
||||||
|
|
||||||
deactivate();
|
auto tmp = make_unique<boost::thread>([&]
|
||||||
bAutofight->activate();
|
|
||||||
|
|
||||||
aiThread = make_unique<boost::thread>([&]
|
|
||||||
{
|
{
|
||||||
auto ba = new BattleAction(autofightingAI->activeStack(activeStack));
|
auto ba = new BattleAction(curInt->autofightingAI->activeStack(activeStack));
|
||||||
|
|
||||||
if(isAutoFightOn)
|
if(curInt->isAutoFightOn)
|
||||||
{
|
{
|
||||||
givenCommand->setn(ba);
|
givenCommand->setn(ba);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
|
activateStack();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
tmp->detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleInterface::SiegeHelper::SiegeHelper(const CGTownInstance *siegeTown, const CBattleInterface * _owner)
|
CBattleInterface::SiegeHelper::SiegeHelper(const CGTownInstance *siegeTown, const CBattleInterface * _owner)
|
||||||
|
@@ -156,10 +156,6 @@ private:
|
|||||||
PossibleActions selectedAction; //last action chosen (and saved) by player
|
PossibleActions selectedAction; //last action chosen (and saved) by player
|
||||||
PossibleActions illegalAction; //most likely action that can't be performed here
|
PossibleActions illegalAction; //most likely action that can't be performed here
|
||||||
|
|
||||||
shared_ptr<CBattleGameInterface> autofightingAI;
|
|
||||||
bool isAutoFightOn;
|
|
||||||
unique_ptr<boost::thread> aiThread;
|
|
||||||
|
|
||||||
void requestAutofightingAIToTakeAction();
|
void requestAutofightingAIToTakeAction();
|
||||||
|
|
||||||
void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
|
void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
|
||||||
|
@@ -304,13 +304,13 @@ void CBattleOptionsWindow::bExitf()
|
|||||||
GH.popIntTotally(this);
|
GH.popIntTotally(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CBattleInterface * _owner)
|
CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CPlayerInterface &_owner)
|
||||||
: owner(_owner)
|
: owner(_owner)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
this->pos = pos;
|
this->pos = pos;
|
||||||
CPicture * bg = new CPicture("CPRESULT");
|
CPicture * bg = new CPicture("CPRESULT");
|
||||||
bg->colorize(owner->curInt->playerID);
|
bg->colorize(owner.playerID);
|
||||||
|
|
||||||
exit = new CAdventureMapButton ("", "", boost::bind(&CBattleResultWindow::bExitf,this), 384, 505, "iok6432.def", SDLK_RETURN);
|
exit = new CAdventureMapButton ("", "", boost::bind(&CBattleResultWindow::bExitf,this), 384, 505, "iok6432.def", SDLK_RETURN);
|
||||||
exit->borderColor = Colors::METALLIC_GOLD;
|
exit->borderColor = Colors::METALLIC_GOLD;
|
||||||
@@ -331,59 +331,40 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
|||||||
new CLabel(232, 332, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[408]);
|
new CLabel(232, 332, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[408]);
|
||||||
new CLabel(232, 428, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[409]);
|
new CLabel(232, 428, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[409]);
|
||||||
|
|
||||||
std::string attackerName, defenderName;
|
std::string sideNames[2] = {"N/A", "N/A"};
|
||||||
|
|
||||||
if(owner->attackingHeroInstance) //a hero attacked
|
for(int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
new CAnimImage("PortraitsLarge", owner->attackingHeroInstance->portrait, 0, 21, 38);
|
auto heroInfo = owner.cb->battleGetHeroInfo(i);
|
||||||
//setting attackerName
|
const int xs[] = {21, 392};
|
||||||
attackerName = owner->attackingHeroInstance->name;
|
|
||||||
|
if(heroInfo.portrait >= 0) //attacking hero
|
||||||
|
{
|
||||||
|
new CAnimImage("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38);
|
||||||
|
sideNames[i] = heroInfo.name;
|
||||||
}
|
}
|
||||||
else //a monster attacked
|
else
|
||||||
{
|
{
|
||||||
int bestMonsterID = -1;
|
int bestMonsterID = -1;
|
||||||
ui32 bestPower = 0;
|
ui32 bestPower = 0;
|
||||||
for(TSlots::const_iterator it = owner->army1->Slots().begin(); it!=owner->army1->Slots().end(); ++it)
|
auto stacks = owner.cb->battleGetAllStacks();
|
||||||
|
vstd::erase_if(stacks, [i](const CStack *stack) //erase stack of other side and not coming from garrison
|
||||||
|
{ return stack->attackerOwned == i || !stack->base; });
|
||||||
|
|
||||||
|
auto best = vstd::maxElementByFun(stacks, [](const CStack *stack){ return stack->type->AIValue; });
|
||||||
|
if(best != stacks.end()) //should be always but to be safe...
|
||||||
{
|
{
|
||||||
if(it->second->type->AIValue > bestPower)
|
new CAnimImage("TWCRPORT", (*best)->type->idNumber+2, 0, xs[i], 38);
|
||||||
{
|
sideNames[i] = CGI->creh->creatures[(*best)->type->idNumber]->namePl;
|
||||||
bestPower = it->second->type->AIValue;
|
|
||||||
bestMonsterID = it->second->type->idNumber;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new CAnimImage("TWCRPORT", bestMonsterID+2, 0, 21, 38);
|
|
||||||
//setting attackerName
|
|
||||||
attackerName = CGI->creh->creatures[bestMonsterID]->namePl;
|
|
||||||
}
|
|
||||||
if(owner->defendingHeroInstance) //a hero defended
|
|
||||||
{
|
|
||||||
new CAnimImage("PortraitsLarge", owner->defendingHeroInstance->portrait, 0, 392, 38);
|
|
||||||
//setting defenderName
|
|
||||||
defenderName = owner->defendingHeroInstance->name;
|
|
||||||
}
|
|
||||||
else //a monster defended
|
|
||||||
{
|
|
||||||
int bestMonsterID = -1;
|
|
||||||
ui32 bestPower = 0;
|
|
||||||
for(TSlots::const_iterator it = owner->army2->Slots().begin(); it!=owner->army2->Slots().end(); ++it)
|
|
||||||
{
|
|
||||||
if( it->second->type->AIValue > bestPower)
|
|
||||||
{
|
|
||||||
bestPower = it->second->type->AIValue;
|
|
||||||
bestMonsterID = it->second->type->idNumber;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new CAnimImage("TWCRPORT", CGI->creh->creatures[bestMonsterID]->iconIndex, 0, 392, 38);
|
|
||||||
//setting defenderName
|
|
||||||
defenderName = CGI->creh->creatures[bestMonsterID]->namePl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//printing attacker and defender's names
|
//printing attacker and defender's names
|
||||||
new CLabel( 89, 37, FONT_SMALL, TOPLEFT, Colors::WHITE, attackerName);
|
new CLabel( 89, 37, FONT_SMALL, TOPLEFT, Colors::WHITE, sideNames[0]);
|
||||||
|
new CLabel( 381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, sideNames[1]);
|
||||||
|
|
||||||
new CLabel( 381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, defenderName);
|
//printing casualties
|
||||||
|
|
||||||
//printing casualities
|
|
||||||
for(int step = 0; step < 2; ++step)
|
for(int step = 0; step < 2; ++step)
|
||||||
{
|
{
|
||||||
if(br.casualties[step].size()==0)
|
if(br.casualties[step].size()==0)
|
||||||
@@ -405,7 +386,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//printing result description
|
//printing result description
|
||||||
bool weAreAttacker = (owner->curInt->playerID == owner->attackingHeroInstance->tempOwner);
|
bool weAreAttacker = !(owner.cb->battleGetMySide());
|
||||||
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
|
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
|
||||||
{
|
{
|
||||||
int text=-1;
|
int text=-1;
|
||||||
@@ -420,7 +401,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
|||||||
CCS->videoh->open("WIN3.BIK");
|
CCS->videoh->open("WIN3.BIK");
|
||||||
std::string str = CGI->generaltexth->allTexts[text];
|
std::string str = CGI->generaltexth->allTexts[text];
|
||||||
|
|
||||||
const CGHeroInstance * ourHero = weAreAttacker? owner->attackingHeroInstance : owner->defendingHeroInstance;
|
const CGHeroInstance * ourHero = owner.cb->battleGetMyHero();
|
||||||
if (ourHero)
|
if (ourHero)
|
||||||
{
|
{
|
||||||
str += CGI->generaltexth->allTexts[305];
|
str += CGI->generaltexth->allTexts[305];
|
||||||
@@ -465,7 +446,7 @@ CBattleResultWindow::~CBattleResultWindow()
|
|||||||
|
|
||||||
void CBattleResultWindow::activate()
|
void CBattleResultWindow::activate()
|
||||||
{
|
{
|
||||||
owner->curInt->showingDialog->set(true);
|
owner.showingDialog->set(true);
|
||||||
CIntObject::activate();
|
CIntObject::activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,9 +464,14 @@ void CBattleResultWindow::bExitf()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto intTmp = owner->curInt;
|
CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon
|
||||||
GH.popInts(2); //first - we; second - battle interface
|
GH.popIntTotally(this);
|
||||||
intTmp->showingDialog->setn(false);
|
if(dynamic_cast<CBattleInterface*>(GH.topInt()))
|
||||||
|
GH.popInts(1); //pop battle interface if present
|
||||||
|
|
||||||
|
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
|
||||||
|
//so we can be sure that there is no dialogs left on GUI stack.
|
||||||
|
intTmp.showingDialog->setn(false);
|
||||||
CCS->videoh->close();
|
CCS->videoh->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ class CLabel;
|
|||||||
struct BattleResult;
|
struct BattleResult;
|
||||||
class CStack;
|
class CStack;
|
||||||
class CAnimImage;
|
class CAnimImage;
|
||||||
|
class CPlayerInterface;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CBattleInterfaceClasses.h, part of VCMI engine
|
* CBattleInterfaceClasses.h, part of VCMI engine
|
||||||
@@ -87,9 +88,9 @@ class CBattleResultWindow : public CIntObject
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
CAdventureMapButton *exit;
|
CAdventureMapButton *exit;
|
||||||
CBattleInterface *owner;
|
CPlayerInterface &owner;
|
||||||
public:
|
public:
|
||||||
CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CBattleInterface * _owner); //c-tor
|
CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CPlayerInterface &_owner); //c-tor
|
||||||
~CBattleResultWindow(); //d-tor
|
~CBattleResultWindow(); //d-tor
|
||||||
|
|
||||||
void bExitf(); //exit button callback
|
void bExitf(); //exit button callback
|
||||||
|
@@ -288,7 +288,10 @@ InfoAboutHero CBattleInfoEssentials::battleGetHeroInfo( ui8 side ) const
|
|||||||
{
|
{
|
||||||
auto hero = getBattle()->heroes[side];
|
auto hero = getBattle()->heroes[side];
|
||||||
if(!hero)
|
if(!hero)
|
||||||
|
{
|
||||||
logGlobal->warnStream() << __FUNCTION__ << ": side " << (int)side << " does not have hero!";
|
logGlobal->warnStream() << __FUNCTION__ << ": side " << (int)side << " does not have hero!";
|
||||||
|
return InfoAboutHero();
|
||||||
|
}
|
||||||
|
|
||||||
return InfoAboutHero(hero, battleDoWeKnowAbout(side));
|
return InfoAboutHero(hero, battleDoWeKnowAbout(side));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user