mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Separated battle control panel into new class, refactoring of
CGStatusBar to allow shared API with battle console
This commit is contained in:
parent
3c5858f01e
commit
7a6ad671ab
@ -3,6 +3,7 @@ set(client_SRCS
|
||||
../CCallback.cpp
|
||||
|
||||
battle/CBattleAnimations.cpp
|
||||
battle/CBattleControlPanel.cpp
|
||||
battle/CBattleInterfaceClasses.cpp
|
||||
battle/CBattleInterface.cpp
|
||||
battle/CBattleFieldController.cpp
|
||||
@ -80,6 +81,7 @@ set(client_HEADERS
|
||||
StdInc.h
|
||||
|
||||
battle/CBattleAnimations.h
|
||||
battle/CBattleControlPanel.h
|
||||
battle/CBattleInterfaceClasses.h
|
||||
battle/CBattleInterface.h
|
||||
battle/CBattleFieldController.h
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "battle/CBattleInterface.h"
|
||||
#include "battle/CBattleFieldController.h"
|
||||
#include "battle/CBattleInterfaceClasses.h"
|
||||
#include "battle/CBattleControlPanel.h"
|
||||
#include "../CCallback.h"
|
||||
#include "windows/CCastleInterface.h"
|
||||
#include "gui/CCursorHandler.h"
|
||||
@ -1028,19 +1029,19 @@ void CPlayerInterface::battleAttack(const BattleAttack * ba)
|
||||
|
||||
if(ba->lucky()) //lucky hit
|
||||
{
|
||||
battleInt->console->addText(attacker->formatGeneralMessage(-45));
|
||||
battleInt->controlPanel->console->addText(attacker->formatGeneralMessage(-45));
|
||||
battleInt->displayEffect(18, attacker->getPosition());
|
||||
CCS->soundh->playSound(soundBase::GOODLUCK);
|
||||
}
|
||||
if(ba->unlucky()) //unlucky hit
|
||||
{
|
||||
battleInt->console->addText(attacker->formatGeneralMessage(-44));
|
||||
battleInt->controlPanel->console->addText(attacker->formatGeneralMessage(-44));
|
||||
battleInt->displayEffect(48, attacker->getPosition());
|
||||
CCS->soundh->playSound(soundBase::BADLUCK);
|
||||
}
|
||||
if(ba->deathBlow())
|
||||
{
|
||||
battleInt->console->addText(attacker->formatGeneralMessage(365));
|
||||
battleInt->controlPanel->console->addText(attacker->formatGeneralMessage(365));
|
||||
for(auto & elem : ba->bsa)
|
||||
{
|
||||
const CStack * attacked = cb->battleGetStackByID(elem.stackAttacked);
|
||||
|
304
client/battle/CBattleControlPanel.cpp
Normal file
304
client/battle/CBattleControlPanel.cpp
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* CBattleControlPanel.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CBattleControlPanel.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "CBattleInterfaceClasses.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
CBattleControlPanel::CBattleControlPanel(CBattleInterface * owner):
|
||||
owner(owner)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
//preparing buttons and console
|
||||
bOptions = std::make_shared<CButton> (Point( 3, 5), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleControlPanel::bOptionsf,this), SDLK_o);
|
||||
bSurrender = std::make_shared<CButton> (Point( 54, 5), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleControlPanel::bSurrenderf,this), SDLK_s);
|
||||
bFlee = std::make_shared<CButton> (Point(105, 5), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleControlPanel::bFleef,this), SDLK_r);
|
||||
bAutofight = std::make_shared<CButton> (Point(157, 5), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleControlPanel::bAutofightf,this), SDLK_a);
|
||||
bSpell = std::make_shared<CButton> (Point(645, 5), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleControlPanel::bSpellf,this), SDLK_c);
|
||||
bWait = std::make_shared<CButton> (Point(696, 5), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleControlPanel::bWaitf,this), SDLK_w);
|
||||
bDefence = std::make_shared<CButton> (Point(747, 5), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&CBattleControlPanel::bDefencef,this), SDLK_d);
|
||||
bConsoleUp = std::make_shared<CButton> (Point(624, 5), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleControlPanel::bConsoleUpf,this), SDLK_UP);
|
||||
bConsoleDown = std::make_shared<CButton>(Point(624, 24), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleControlPanel::bConsoleDownf,this), SDLK_DOWN);
|
||||
|
||||
bDefence->assignedKeys.insert(SDLK_SPACE);
|
||||
bConsoleUp->setImageOrder(0, 1, 0, 0);
|
||||
bConsoleDown->setImageOrder(2, 3, 2, 2);
|
||||
|
||||
console = std::make_shared<CBattleConsole>(Rect(211, 4, 406,38));
|
||||
GH.statusbar = console;
|
||||
|
||||
if ( owner->tacticsMode )
|
||||
tacticPhaseStarted();
|
||||
else
|
||||
tacticPhaseEnded();
|
||||
}
|
||||
|
||||
void CBattleControlPanel::tacticPhaseStarted()
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
btactNext = std::make_shared<CButton>(Point(213, 4), "icm011.def", std::make_pair("", ""), [&]() { bTacticNextStack();}, SDLK_SPACE);
|
||||
btactEnd = std::make_shared<CButton>(Point(419, 4), "icm012.def", std::make_pair("", ""), [&](){ bTacticPhaseEnd();}, SDLK_RETURN);
|
||||
menu = std::make_shared<CPicture>("COPLACBR.BMP", 0, 0);
|
||||
menu->colorize(owner->curInt->playerID);
|
||||
}
|
||||
void CBattleControlPanel::tacticPhaseEnded()
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
menu = std::make_shared<CPicture>("CBAR.BMP", 0, 0);
|
||||
menu->colorize(owner->curInt->playerID);
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bOptionsf()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
|
||||
|
||||
Rect tempRect = genRect(431, 481, 160, 84);
|
||||
tempRect += pos.topLeft();
|
||||
GH.pushIntT<CBattleOptionsWindow>(tempRect, owner);
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bSurrenderf()
|
||||
{
|
||||
if(owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
int cost = owner->curInt->cb->battleGetSurrenderCost();
|
||||
if(cost >= 0)
|
||||
{
|
||||
std::string enemyHeroName = owner->curInt->cb->battleGetEnemyHero().name;
|
||||
if(enemyHeroName.empty())
|
||||
{
|
||||
logGlobal->warn("Surrender performed without enemy hero, should not happen!");
|
||||
enemyHeroName = "#ENEMY#";
|
||||
}
|
||||
|
||||
std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold."
|
||||
owner->curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bFleef()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if ( owner->curInt->cb->battleCanFlee() )
|
||||
{
|
||||
CFunctionList<void()> ony = std::bind(&CBattleControlPanel::reallyFlee,this);
|
||||
owner->curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat?
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::shared_ptr<CComponent>> comps;
|
||||
std::string heroName;
|
||||
//calculating fleeing hero's name
|
||||
if (owner->attackingHeroInstance)
|
||||
if (owner->attackingHeroInstance->tempOwner == owner->curInt->cb->getMyColor())
|
||||
heroName = owner->attackingHeroInstance->name;
|
||||
if (owner->defendingHeroInstance)
|
||||
if (owner->defendingHeroInstance->tempOwner == owner->curInt->cb->getMyColor())
|
||||
heroName = owner->defendingHeroInstance->name;
|
||||
//calculating text
|
||||
auto txt = boost::format(CGI->generaltexth->allTexts[340]) % heroName; //The Shackles of War are present. %s can not retreat!
|
||||
|
||||
//printing message
|
||||
owner->curInt->showInfoDialog(boost::to_string(txt), comps);
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleControlPanel::reallyFlee()
|
||||
{
|
||||
owner->giveCommand(EActionType::RETREAT);
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
|
||||
void CBattleControlPanel::reallySurrender()
|
||||
{
|
||||
if (owner->curInt->cb->getResourceAmount(Res::GOLD) < owner->curInt->cb->battleGetSurrenderCost())
|
||||
{
|
||||
owner->curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold!
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->giveCommand(EActionType::SURRENDER);
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bAutofightf()
|
||||
{
|
||||
if(owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
//Stop auto-fight mode
|
||||
if(owner->curInt->isAutoFightOn)
|
||||
{
|
||||
assert(owner->curInt->autofightingAI);
|
||||
owner->curInt->isAutoFightOn = false;
|
||||
logGlobal->trace("Stopping the autofight...");
|
||||
}
|
||||
else if(!owner->curInt->autofightingAI)
|
||||
{
|
||||
owner->curInt->isAutoFightOn = true;
|
||||
blockUI(true);
|
||||
|
||||
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String());
|
||||
ai->init(owner->curInt->env, owner->curInt->cb);
|
||||
ai->battleStart(owner->army1, owner->army2, int3(0,0,0), owner->attackingHeroInstance, owner->defendingHeroInstance, owner->curInt->cb->battleGetMySide());
|
||||
owner->curInt->autofightingAI = ai;
|
||||
owner->curInt->cb->registerBattleInterface(ai);
|
||||
|
||||
owner->requestAutofightingAIToTakeAction();
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bSpellf()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if (!owner->myTurn)
|
||||
return;
|
||||
|
||||
auto myHero = owner->currentHero();
|
||||
if(!myHero)
|
||||
return;
|
||||
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem spellCastProblem = owner->curInt->cb->battleCanCastSpell(myHero, spells::Mode::HERO);
|
||||
|
||||
if(spellCastProblem == ESpellCastProblem::OK)
|
||||
{
|
||||
GH.pushIntT<CSpellWindow>(myHero, owner->curInt.get());
|
||||
}
|
||||
else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
|
||||
{
|
||||
//TODO: move to spell mechanics, add more information to spell cast problem
|
||||
//Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible
|
||||
auto blockingBonus = owner->currentHero()->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_ALL_MAGIC));
|
||||
if (!blockingBonus)
|
||||
return;
|
||||
|
||||
if (blockingBonus->source == Bonus::ARTIFACT)
|
||||
{
|
||||
const int32_t artID = blockingBonus->sid;
|
||||
//If we have artifact, put name of our hero. Otherwise assume it's the enemy.
|
||||
//TODO check who *really* is source of bonus
|
||||
std::string heroName = myHero->hasArt(artID) ? myHero->name : owner->enemyHero().name;
|
||||
|
||||
//%s wields the %s, an ancient artifact which creates a p dead to all magic.
|
||||
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[683])
|
||||
% heroName % CGI->artifacts()->getByIndex(artID)->getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bWaitf()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if (owner->activeStack != nullptr)
|
||||
owner->giveCommand(EActionType::WAIT);
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bDefencef()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if (owner->activeStack != nullptr)
|
||||
owner->giveCommand(EActionType::DEFEND);
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bConsoleUpf()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
console->scrollUp();
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bConsoleDownf()
|
||||
{
|
||||
if (owner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
console->scrollDown();
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bTacticNextStack()
|
||||
{
|
||||
owner->tacticNextStack(nullptr);
|
||||
}
|
||||
|
||||
void CBattleControlPanel::bTacticPhaseEnd()
|
||||
{
|
||||
owner->tacticPhaseEnd();
|
||||
}
|
||||
|
||||
void CBattleControlPanel::blockUI(bool on)
|
||||
{
|
||||
bool canCastSpells = false;
|
||||
auto hero = owner->curInt->cb->battleGetMyHero();
|
||||
|
||||
if(hero)
|
||||
{
|
||||
ESpellCastProblem::ESpellCastProblem spellcastingProblem = owner->curInt->cb->battleCanCastSpell(hero, spells::Mode::HERO);
|
||||
|
||||
//if magic is blocked, we leave button active, so the message can be displayed after button click
|
||||
canCastSpells = spellcastingProblem == ESpellCastProblem::OK || spellcastingProblem == ESpellCastProblem::MAGIC_IS_BLOCKED;
|
||||
}
|
||||
|
||||
bool canWait = owner->activeStack ? !owner->activeStack->waitedThisTurn : false;
|
||||
|
||||
bOptions->block(on);
|
||||
bFlee->block(on || !owner->curInt->cb->battleCanFlee());
|
||||
bSurrender->block(on || owner->curInt->cb->battleGetSurrenderCost() < 0);
|
||||
|
||||
// block only if during enemy turn and auto-fight is off
|
||||
// otherwise - crash on accessing non-exisiting active stack
|
||||
bAutofight->block(!owner->curInt->isAutoFightOn && !owner->activeStack);
|
||||
|
||||
if (owner->tacticsMode && btactEnd && btactNext)
|
||||
{
|
||||
btactNext->block(on);
|
||||
btactEnd->block(on);
|
||||
}
|
||||
else
|
||||
{
|
||||
bConsoleUp->block(on);
|
||||
bConsoleDown->block(on);
|
||||
}
|
||||
|
||||
|
||||
bSpell->block(on || owner->tacticsMode || !canCastSpells);
|
||||
bWait->block(on || owner->tacticsMode || !canWait);
|
||||
bDefence->block(on || owner->tacticsMode);
|
||||
}
|
64
client/battle/CBattleControlPanel.h
Normal file
64
client/battle/CBattleControlPanel.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* CBattleControlPanel.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
class CStack;
|
||||
class CButton;
|
||||
class CBattleInterface;
|
||||
class CBattleConsole;
|
||||
|
||||
class CBattleControlPanel : public CIntObject
|
||||
{
|
||||
|
||||
CBattleInterface * owner;
|
||||
|
||||
std::shared_ptr<CPicture> menu;
|
||||
|
||||
std::shared_ptr<CButton> bOptions;
|
||||
std::shared_ptr<CButton> bSurrender;
|
||||
std::shared_ptr<CButton> bFlee;
|
||||
std::shared_ptr<CButton> bAutofight;
|
||||
std::shared_ptr<CButton> bSpell;
|
||||
std::shared_ptr<CButton> bWait;
|
||||
std::shared_ptr<CButton> bDefence;
|
||||
std::shared_ptr<CButton> bConsoleUp;
|
||||
std::shared_ptr<CButton> bConsoleDown;
|
||||
std::shared_ptr<CButton> btactNext;
|
||||
std::shared_ptr<CButton> btactEnd;
|
||||
|
||||
//button handle funcs:
|
||||
void bOptionsf();
|
||||
void bSurrenderf();
|
||||
void bFleef();
|
||||
void reallyFlee(); //performs fleeing without asking player
|
||||
void reallySurrender(); //performs surrendering without asking player
|
||||
void bAutofightf();
|
||||
void bSpellf();
|
||||
void bWaitf();
|
||||
void bDefencef();
|
||||
void bConsoleUpf();
|
||||
void bConsoleDownf();
|
||||
void bTacticNextStack();
|
||||
void bTacticPhaseEnd();
|
||||
|
||||
public:
|
||||
std::shared_ptr<CBattleConsole> console;
|
||||
|
||||
// block all UI elements, e.g. during enemy turn
|
||||
// unlike activate/deactivate this method will correctly grey-out all elements
|
||||
void blockUI(bool on);
|
||||
|
||||
void tacticPhaseStarted();
|
||||
void tacticPhaseEnded();
|
||||
|
||||
CBattleControlPanel(CBattleInterface * owner);
|
||||
};
|
@ -17,6 +17,7 @@
|
||||
#include "CBattleObstacleController.h"
|
||||
#include "CBattleSiegeController.h"
|
||||
#include "CBattleFieldController.h"
|
||||
#include "CBattleControlPanel.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
@ -200,37 +201,6 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
CSDL_Ext::alphaTransform(amountEffNeutral);
|
||||
transformPalette(amountEffNeutral, 1.00, 1.00, 0.18);
|
||||
|
||||
//preparing buttons and console
|
||||
bOptions = std::make_shared<CButton>(Point( 3, 561), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleInterface::bOptionsf,this), SDLK_o);
|
||||
bSurrender = std::make_shared<CButton>(Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleInterface::bSurrenderf,this), SDLK_s);
|
||||
bFlee = std::make_shared<CButton>(Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleInterface::bFleef,this), SDLK_r);
|
||||
bAutofight = std::make_shared<CButton>(Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleInterface::bAutofightf,this), SDLK_a);
|
||||
bSpell = std::make_shared<CButton>(Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleInterface::bSpellf,this), SDLK_c);
|
||||
bWait = std::make_shared<CButton>(Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleInterface::bWaitf,this), SDLK_w);
|
||||
bDefence = std::make_shared<CButton>(Point(747, 561), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&CBattleInterface::bDefencef,this), SDLK_d);
|
||||
bDefence->assignedKeys.insert(SDLK_SPACE);
|
||||
bConsoleUp = std::make_shared<CButton>(Point(624, 561), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP);
|
||||
bConsoleDown = std::make_shared<CButton>(Point(624, 580), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleDownf,this), SDLK_DOWN);
|
||||
bConsoleUp->setImageOrder(0, 1, 0, 0);
|
||||
bConsoleDown->setImageOrder(2, 3, 2, 2);
|
||||
|
||||
console = std::make_shared<CBattleConsole>();
|
||||
console->pos.x += 211;
|
||||
console->pos.y += 560;
|
||||
console->pos.w = 406;
|
||||
console->pos.h = 38;
|
||||
if(tacticsMode)
|
||||
{
|
||||
btactNext = std::make_shared<CButton>(Point(213, 560), "icm011.def", std::make_pair("", ""), [&](){ bTacticNextStack(nullptr);}, SDLK_SPACE);
|
||||
btactEnd = std::make_shared<CButton>(Point(419, 560), "icm012.def", std::make_pair("", ""), [&](){ bEndTacticPhase();}, SDLK_RETURN);
|
||||
menu = BitmapHandler::loadBitmap("COPLACBR.BMP");
|
||||
}
|
||||
else
|
||||
{
|
||||
menu = BitmapHandler::loadBitmap("CBAR.BMP");
|
||||
}
|
||||
graphics->blueToPlayersAdv(menu, curInt->playerID);
|
||||
|
||||
//loading hero animations
|
||||
if(hero1) // attacking hero
|
||||
{
|
||||
@ -281,7 +251,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
obstacleController.reset(new CBattleObstacleController(this));
|
||||
|
||||
if(tacticsMode)
|
||||
bTacticNextStack();
|
||||
tacticNextStack(nullptr);
|
||||
|
||||
CCS->musich->stopMusic();
|
||||
battleIntroSoundChannel = CCS->soundh->playSoundFromSet(CCS->soundh->battleIntroSounds);
|
||||
@ -291,7 +261,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
{
|
||||
CCS->musich->playMusicFromSet("battle", true, true);
|
||||
battleActionsStarted = true;
|
||||
blockUI(settings["session"]["spectate"].Bool());
|
||||
controlPanel->blockUI(settings["session"]["spectate"].Bool());
|
||||
battleIntroSoundChannel = -1;
|
||||
}
|
||||
};
|
||||
@ -301,7 +271,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
currentAction = PossiblePlayerBattleAction::INVALID;
|
||||
selectedAction = PossiblePlayerBattleAction::INVALID;
|
||||
addUsedEvents(RCLICK | MOVE | KEYBOARD);
|
||||
blockUI(true);
|
||||
controlPanel->blockUI(true);
|
||||
}
|
||||
|
||||
CBattleInterface::~CBattleInterface()
|
||||
@ -313,7 +283,6 @@ CBattleInterface::~CBattleInterface()
|
||||
{
|
||||
deactivate();
|
||||
}
|
||||
SDL_FreeSurface(menu);
|
||||
SDL_FreeSurface(amountNormal);
|
||||
SDL_FreeSurface(amountNegative);
|
||||
SDL_FreeSurface(amountPositive);
|
||||
@ -357,20 +326,12 @@ void CBattleInterface::setPrintMouseShadow(bool set)
|
||||
|
||||
void CBattleInterface::activate()
|
||||
{
|
||||
controlPanel->activate();
|
||||
|
||||
if (curInt->isAutoFightOn)
|
||||
{
|
||||
bAutofight->activate();
|
||||
return;
|
||||
}
|
||||
|
||||
CIntObject::activate();
|
||||
bOptions->activate();
|
||||
bSurrender->activate();
|
||||
bFlee->activate();
|
||||
bAutofight->activate();
|
||||
bSpell->activate();
|
||||
bWait->activate();
|
||||
bDefence->activate();
|
||||
|
||||
if (attackingHero)
|
||||
attackingHero->activate();
|
||||
@ -382,32 +343,14 @@ void CBattleInterface::activate()
|
||||
if (settings["battle"]["showQueue"].Bool())
|
||||
queue->activate();
|
||||
|
||||
if (tacticsMode)
|
||||
{
|
||||
btactNext->activate();
|
||||
btactEnd->activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
bConsoleUp->activate();
|
||||
bConsoleDown->activate();
|
||||
}
|
||||
|
||||
LOCPLINT->cingconsole->activate();
|
||||
}
|
||||
|
||||
void CBattleInterface::deactivate()
|
||||
{
|
||||
controlPanel->deactivate();
|
||||
CIntObject::deactivate();
|
||||
|
||||
bOptions->deactivate();
|
||||
bSurrender->deactivate();
|
||||
bFlee->deactivate();
|
||||
bAutofight->deactivate();
|
||||
bSpell->deactivate();
|
||||
bWait->deactivate();
|
||||
bDefence->deactivate();
|
||||
|
||||
fieldController->deactivate();
|
||||
|
||||
if (attackingHero)
|
||||
@ -417,17 +360,6 @@ void CBattleInterface::deactivate()
|
||||
if (settings["battle"]["showQueue"].Bool())
|
||||
queue->deactivate();
|
||||
|
||||
if (tacticsMode)
|
||||
{
|
||||
btactNext->deactivate();
|
||||
btactEnd->deactivate();
|
||||
}
|
||||
else
|
||||
{
|
||||
bConsoleUp->deactivate();
|
||||
bConsoleDown->deactivate();
|
||||
}
|
||||
|
||||
LOCPLINT->cingconsole->deactivate();
|
||||
}
|
||||
|
||||
@ -468,189 +400,6 @@ void CBattleInterface::clickRight(tribool down, bool previousState)
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::bOptionsf()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
|
||||
|
||||
Rect tempRect = genRect(431, 481, 160, 84);
|
||||
tempRect += pos.topLeft();
|
||||
GH.pushIntT<CBattleOptionsWindow>(tempRect, this);
|
||||
}
|
||||
|
||||
void CBattleInterface::bSurrenderf()
|
||||
{
|
||||
if(spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
int cost = curInt->cb->battleGetSurrenderCost();
|
||||
if(cost >= 0)
|
||||
{
|
||||
std::string enemyHeroName = curInt->cb->battleGetEnemyHero().name;
|
||||
if(enemyHeroName.empty())
|
||||
{
|
||||
logGlobal->warn("Surrender performed without enemy hero, should not happen!");
|
||||
enemyHeroName = "#ENEMY#";
|
||||
}
|
||||
|
||||
std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold."
|
||||
curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::bFleef()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if ( curInt->cb->battleCanFlee() )
|
||||
{
|
||||
CFunctionList<void()> ony = std::bind(&CBattleInterface::reallyFlee,this);
|
||||
curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat?
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::shared_ptr<CComponent>> comps;
|
||||
std::string heroName;
|
||||
//calculating fleeing hero's name
|
||||
if (attackingHeroInstance)
|
||||
if (attackingHeroInstance->tempOwner == curInt->cb->getMyColor())
|
||||
heroName = attackingHeroInstance->name;
|
||||
if (defendingHeroInstance)
|
||||
if (defendingHeroInstance->tempOwner == curInt->cb->getMyColor())
|
||||
heroName = defendingHeroInstance->name;
|
||||
//calculating text
|
||||
auto txt = boost::format(CGI->generaltexth->allTexts[340]) % heroName; //The Shackles of War are present. %s can not retreat!
|
||||
|
||||
//printing message
|
||||
curInt->showInfoDialog(boost::to_string(txt), comps);
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::reallyFlee()
|
||||
{
|
||||
giveCommand(EActionType::RETREAT);
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
|
||||
void CBattleInterface::reallySurrender()
|
||||
{
|
||||
if (curInt->cb->getResourceAmount(Res::GOLD) < curInt->cb->battleGetSurrenderCost())
|
||||
{
|
||||
curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold!
|
||||
}
|
||||
else
|
||||
{
|
||||
giveCommand(EActionType::SURRENDER);
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::bAutofightf()
|
||||
{
|
||||
if(spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
//Stop auto-fight mode
|
||||
if(curInt->isAutoFightOn)
|
||||
{
|
||||
assert(curInt->autofightingAI);
|
||||
curInt->isAutoFightOn = false;
|
||||
logGlobal->trace("Stopping the autofight...");
|
||||
}
|
||||
else if(!curInt->autofightingAI)
|
||||
{
|
||||
curInt->isAutoFightOn = true;
|
||||
blockUI(true);
|
||||
|
||||
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String());
|
||||
ai->init(curInt->env, curInt->cb);
|
||||
ai->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide());
|
||||
curInt->autofightingAI = ai;
|
||||
curInt->cb->registerBattleInterface(ai);
|
||||
|
||||
requestAutofightingAIToTakeAction();
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::bSpellf()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if (!myTurn)
|
||||
return;
|
||||
|
||||
auto myHero = currentHero();
|
||||
if(!myHero)
|
||||
return;
|
||||
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem spellCastProblem = curInt->cb->battleCanCastSpell(myHero, spells::Mode::HERO);
|
||||
|
||||
if(spellCastProblem == ESpellCastProblem::OK)
|
||||
{
|
||||
GH.pushIntT<CSpellWindow>(myHero, curInt.get());
|
||||
}
|
||||
else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
|
||||
{
|
||||
//TODO: move to spell mechanics, add more information to spell cast problem
|
||||
//Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible
|
||||
auto blockingBonus = currentHero()->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_ALL_MAGIC));
|
||||
if (!blockingBonus)
|
||||
return;
|
||||
|
||||
if (blockingBonus->source == Bonus::ARTIFACT)
|
||||
{
|
||||
const int32_t artID = blockingBonus->sid;
|
||||
//If we have artifact, put name of our hero. Otherwise assume it's the enemy.
|
||||
//TODO check who *really* is source of bonus
|
||||
std::string heroName = myHero->hasArt(artID) ? myHero->name : enemyHero().name;
|
||||
|
||||
//%s wields the %s, an ancient artifact which creates a p dead to all magic.
|
||||
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[683])
|
||||
% heroName % CGI->artifacts()->getByIndex(artID)->getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::bWaitf()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if (activeStack != nullptr)
|
||||
giveCommand(EActionType::WAIT);
|
||||
}
|
||||
|
||||
void CBattleInterface::bDefencef()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if (activeStack != nullptr)
|
||||
giveCommand(EActionType::DEFEND);
|
||||
}
|
||||
|
||||
void CBattleInterface::bConsoleUpf()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
console->scrollUp();
|
||||
}
|
||||
|
||||
void CBattleInterface::bConsoleDownf()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
console->scrollDown();
|
||||
}
|
||||
|
||||
void CBattleInterface::unitAdded(const CStack * stack)
|
||||
{
|
||||
creDir[stack->ID] = stack->side == BattleSide::ATTACKER; // must be set before getting stack position
|
||||
@ -784,7 +533,7 @@ void CBattleInterface::newRoundFirst( int round )
|
||||
|
||||
void CBattleInterface::newRound(int number)
|
||||
{
|
||||
console->addText(CGI->generaltexth->allTexts[412]);
|
||||
controlPanel->console->addText(CGI->generaltexth->allTexts[412]);
|
||||
}
|
||||
|
||||
void CBattleInterface::giveCommand(EActionType action, BattleHex tile, si32 additional)
|
||||
@ -1050,7 +799,7 @@ void CBattleInterface::displayBattleLog(const std::vector<MetaString> & battleLo
|
||||
{
|
||||
std::string formatted = line.toString();
|
||||
boost::algorithm::trim(formatted);
|
||||
if(!console->addText(formatted))
|
||||
if(!controlPanel->console->addText(formatted))
|
||||
logGlobal->warn("Too long battle log line");
|
||||
}
|
||||
}
|
||||
@ -1143,7 +892,7 @@ void CBattleInterface::battleTriggerEffect(const BattleTriggerEffect & bte)
|
||||
boost::algorithm::replace_first(hlp,"%s",(stack->getName()));
|
||||
displayEffect(20,stack->getPosition());
|
||||
CCS->soundh->playSound(soundBase::GOODMRLE);
|
||||
console->addText(hlp);
|
||||
controlPanel->console->addText(hlp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1194,7 +943,7 @@ void CBattleInterface::setActiveStack(const CStack *stack)
|
||||
if (activeStack) // update UI
|
||||
creAnims[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder());
|
||||
|
||||
blockUI(activeStack == nullptr);
|
||||
controlPanel->blockUI(activeStack == nullptr);
|
||||
}
|
||||
|
||||
void CBattleInterface::setHoveredStack(const CStack *stack)
|
||||
@ -1431,7 +1180,7 @@ void CBattleInterface::endAction(const BattleAction* action)
|
||||
queue->update();
|
||||
|
||||
if (tacticsMode) //stack ended movement in tactics phase -> select the next one
|
||||
bTacticNextStack(stack);
|
||||
tacticNextStack(stack);
|
||||
|
||||
if(action->actionType == EActionType::HERO_SPELL) //we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed
|
||||
fieldController->redrawBackgroundWithHexes(activeStack);
|
||||
@ -1439,12 +1188,12 @@ void CBattleInterface::endAction(const BattleAction* action)
|
||||
if (activeStack && !animsAreDisplayed.get() && pendingAnims.empty() && !active)
|
||||
{
|
||||
logGlobal->warn("Something wrong... interface was deactivated but there is no animation. Reactivating...");
|
||||
blockUI(false);
|
||||
controlPanel->blockUI(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// block UI if no active stack (e.g. enemy turn);
|
||||
blockUI(activeStack == nullptr);
|
||||
controlPanel->blockUI(activeStack == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1476,58 +1225,15 @@ void CBattleInterface::showQueue()
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::blockUI(bool on)
|
||||
{
|
||||
bool canCastSpells = false;
|
||||
auto hero = curInt->cb->battleGetMyHero();
|
||||
|
||||
if(hero)
|
||||
{
|
||||
ESpellCastProblem::ESpellCastProblem spellcastingProblem = curInt->cb->battleCanCastSpell(hero, spells::Mode::HERO);
|
||||
|
||||
//if magic is blocked, we leave button active, so the message can be displayed after button click
|
||||
canCastSpells = spellcastingProblem == ESpellCastProblem::OK || spellcastingProblem == ESpellCastProblem::MAGIC_IS_BLOCKED;
|
||||
}
|
||||
|
||||
bool canWait = activeStack ? !activeStack->waitedThisTurn : false;
|
||||
|
||||
bOptions->block(on);
|
||||
bFlee->block(on || !curInt->cb->battleCanFlee());
|
||||
bSurrender->block(on || curInt->cb->battleGetSurrenderCost() < 0);
|
||||
|
||||
// block only if during enemy turn and auto-fight is off
|
||||
// otherwise - crash on accessing non-exisiting active stack
|
||||
bAutofight->block(!curInt->isAutoFightOn && !activeStack);
|
||||
|
||||
if (tacticsMode && btactEnd && btactNext)
|
||||
{
|
||||
btactNext->block(on);
|
||||
btactEnd->block(on);
|
||||
}
|
||||
else
|
||||
{
|
||||
bConsoleUp->block(on);
|
||||
bConsoleDown->block(on);
|
||||
}
|
||||
|
||||
|
||||
bSpell->block(on || tacticsMode || !canCastSpells);
|
||||
bWait->block(on || tacticsMode || !canWait);
|
||||
bDefence->block(on || tacticsMode);
|
||||
}
|
||||
|
||||
void CBattleInterface::startAction(const BattleAction* action)
|
||||
{
|
||||
//setActiveStack(nullptr);
|
||||
setHoveredStack(nullptr);
|
||||
blockUI(true);
|
||||
controlPanel->blockUI(true);
|
||||
|
||||
if(action->actionType == EActionType::END_TACTIC_PHASE)
|
||||
{
|
||||
SDL_FreeSurface(menu);
|
||||
menu = BitmapHandler::loadBitmap("CBAR.bmp");
|
||||
|
||||
graphics->blueToPlayersAdv(menu, curInt->playerID);
|
||||
controlPanel->tacticPhaseEnded();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1586,7 +1292,7 @@ void CBattleInterface::startAction(const BattleAction* action)
|
||||
}
|
||||
|
||||
if(txtid != 0)
|
||||
console->addText(stack->formatGeneralMessage(txtid));
|
||||
controlPanel->console->addText(stack->formatGeneralMessage(txtid));
|
||||
|
||||
//displaying special abilities
|
||||
switch(action->actionType)
|
||||
@ -1604,10 +1310,10 @@ void CBattleInterface::waitForAnims()
|
||||
animsAreDisplayed.waitWhileTrue();
|
||||
}
|
||||
|
||||
void CBattleInterface::bEndTacticPhase()
|
||||
void CBattleInterface::tacticPhaseEnd()
|
||||
{
|
||||
setActiveStack(nullptr);
|
||||
blockUI(true);
|
||||
controlPanel->blockUI(true);
|
||||
tacticsMode = false;
|
||||
}
|
||||
|
||||
@ -1616,7 +1322,7 @@ static bool immobile(const CStack *s)
|
||||
return !s->Speed(0, true); //should bound stacks be immobile?
|
||||
}
|
||||
|
||||
void CBattleInterface::bTacticNextStack(const CStack * current)
|
||||
void CBattleInterface::tacticNextStack(const CStack * current)
|
||||
{
|
||||
if (!current)
|
||||
current = activeStack;
|
||||
@ -1628,7 +1334,7 @@ void CBattleInterface::bTacticNextStack(const CStack * current)
|
||||
vstd::erase_if (stacksOfMine, &immobile);
|
||||
if (stacksOfMine.empty())
|
||||
{
|
||||
bEndTacticPhase();
|
||||
tacticPhaseEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2099,8 +1805,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
{
|
||||
if (setCursor)
|
||||
CCS->curh->changeGraphic(cursorType, cursorFrame);
|
||||
this->console->alterText(consoleMsg);
|
||||
this->console->whoSetAlter = 0;
|
||||
controlPanel->console->write(consoleMsg);
|
||||
}
|
||||
if (eventType == LCLICK && realizeAction)
|
||||
{
|
||||
@ -2112,7 +1817,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
realizeAction();
|
||||
if (!secondaryTarget) //do not replace teleport or sacrifice cursor
|
||||
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
|
||||
this->console->alterText("");
|
||||
controlPanel->console->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2215,7 +1920,7 @@ void CBattleInterface::requestAutofightingAIToTakeAction()
|
||||
//TODO implement the possibility that the AI will be triggered for further actions
|
||||
//TODO any solution to merge tactics phase & normal phase in the way it is handled by the player and battle interface?
|
||||
setActiveStack(nullptr);
|
||||
blockUI(true);
|
||||
controlPanel->blockUI(true);
|
||||
tacticsMode = false;
|
||||
}
|
||||
else
|
||||
@ -2443,31 +2148,9 @@ void CBattleInterface::showBattleEffects(SDL_Surface *to, const std::vector<cons
|
||||
|
||||
void CBattleInterface::showInterface(SDL_Surface *to)
|
||||
{
|
||||
blitAt(menu, pos.x, 556 + pos.y, to);
|
||||
|
||||
if (tacticsMode)
|
||||
{
|
||||
btactNext->showAll(to);
|
||||
btactEnd->showAll(to);
|
||||
}
|
||||
else
|
||||
{
|
||||
console->showAll(to);
|
||||
bConsoleUp->showAll(to);
|
||||
bConsoleDown->showAll(to);
|
||||
}
|
||||
|
||||
//showing buttons
|
||||
bOptions->showAll(to);
|
||||
bSurrender->showAll(to);
|
||||
bFlee->showAll(to);
|
||||
bAutofight->showAll(to);
|
||||
bSpell->showAll(to);
|
||||
bWait->showAll(to);
|
||||
bDefence->showAll(to);
|
||||
|
||||
//showing in-game console
|
||||
LOCPLINT->cingconsole->show(to);
|
||||
controlPanel->show(to);
|
||||
|
||||
Rect posWithQueue = Rect(pos.x, pos.y, 800, 600);
|
||||
|
||||
@ -2594,7 +2277,7 @@ void CBattleInterface::updateBattleAnimations()
|
||||
if (preSize > 0 && pendingAnims.empty())
|
||||
{
|
||||
//anims ended
|
||||
blockUI(activeStack == nullptr);
|
||||
controlPanel->blockUI(activeStack == nullptr);
|
||||
|
||||
animsAreDisplayed.setn(false);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ class CBattleProjectileController;
|
||||
class CBattleSiegeController;
|
||||
class CBattleObstacleController;
|
||||
class CBattleFieldController;
|
||||
class CBattleControlPanel;
|
||||
|
||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||
struct StackAttackedInfo
|
||||
@ -118,24 +119,12 @@ enum class MouseHoveredHexContext
|
||||
class CBattleInterface : public WindowBase
|
||||
{
|
||||
private:
|
||||
SDL_Surface *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral;
|
||||
SDL_Surface *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral;
|
||||
|
||||
std::shared_ptr<CButton> bOptions;
|
||||
std::shared_ptr<CButton> bSurrender;
|
||||
std::shared_ptr<CButton> bFlee;
|
||||
std::shared_ptr<CButton> bAutofight;
|
||||
std::shared_ptr<CButton> bSpell;
|
||||
std::shared_ptr<CButton> bWait;
|
||||
std::shared_ptr<CButton> bDefence;
|
||||
std::shared_ptr<CButton> bConsoleUp;
|
||||
std::shared_ptr<CButton> bConsoleDown;
|
||||
std::shared_ptr<CButton> btactNext;
|
||||
std::shared_ptr<CButton> btactEnd;
|
||||
|
||||
std::shared_ptr<CBattleConsole> console;
|
||||
std::shared_ptr<CBattleHero> attackingHero;
|
||||
std::shared_ptr<CBattleHero> defendingHero;
|
||||
std::shared_ptr<CStackQueue> queue;
|
||||
std::shared_ptr<CBattleControlPanel> controlPanel;
|
||||
|
||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
||||
@ -236,25 +225,9 @@ public:
|
||||
|
||||
const BattleResult *bresult; //result of a battle; if non-zero then display when all animations end
|
||||
|
||||
// block all UI elements, e.g. during enemy turn
|
||||
// unlike activate/deactivate this method will correctly grey-out all elements
|
||||
void blockUI(bool on);
|
||||
void tacticNextStack(const CStack *current);
|
||||
void tacticPhaseEnd();
|
||||
|
||||
//button handle funcs:
|
||||
void bOptionsf();
|
||||
void bSurrenderf();
|
||||
void bFleef();
|
||||
void reallyFlee(); //performs fleeing without asking player
|
||||
void reallySurrender(); //performs surrendering without asking player
|
||||
void bAutofightf();
|
||||
void bSpellf();
|
||||
void bWaitf();
|
||||
void bDefencef();
|
||||
void bConsoleUpf();
|
||||
void bConsoleDownf();
|
||||
void bTacticNextStack(const CStack *current = nullptr);
|
||||
void bEndTacticPhase();
|
||||
//end of button handle funcs
|
||||
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
@ -332,4 +305,5 @@ public:
|
||||
friend class CBattleSiegeController;
|
||||
friend class CBattleObstacleController;
|
||||
friend class CBattleFieldController;
|
||||
friend class CBattleControlPanel;
|
||||
};
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "CBattleInterface.h"
|
||||
#include "CBattleSiegeController.h"
|
||||
#include "CBattleFieldController.h"
|
||||
#include "CBattleControlPanel.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
@ -50,10 +51,6 @@ void CBattleConsole::showAll(SDL_Surface * to)
|
||||
{
|
||||
graphics->fonts[FONT_SMALL]->renderTextLinesCenter(to, CMessage::breakText(ingcAlter, pos.w, FONT_SMALL), Colors::WHITE, textPos);
|
||||
}
|
||||
else if(alterTxt.size())
|
||||
{
|
||||
graphics->fonts[FONT_SMALL]->renderTextLinesCenter(to, CMessage::breakText(alterTxt, pos.w, FONT_SMALL), Colors::WHITE, textPos);
|
||||
}
|
||||
else if(texts.size())
|
||||
{
|
||||
if(texts.size()==1)
|
||||
@ -88,32 +85,6 @@ bool CBattleConsole::addText(const std::string & text)
|
||||
lastShown = (int)texts.size()-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBattleConsole::alterText(const std::string &text)
|
||||
{
|
||||
//char buf[500];
|
||||
//sprintf(buf, text.c_str());
|
||||
//alterTxt = buf;
|
||||
alterTxt = text;
|
||||
}
|
||||
|
||||
void CBattleConsole::eraseText(ui32 pos)
|
||||
{
|
||||
if(pos < texts.size())
|
||||
{
|
||||
texts.erase(texts.begin() + pos);
|
||||
if(lastShown == texts.size())
|
||||
--lastShown;
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleConsole::changeTextAt(const std::string & text, ui32 pos)
|
||||
{
|
||||
if(pos >= texts.size()) //no such pos
|
||||
return;
|
||||
texts[pos] = text;
|
||||
}
|
||||
|
||||
void CBattleConsole::scrollUp(ui32 by)
|
||||
{
|
||||
if(lastShown > static_cast<int>(by))
|
||||
@ -126,8 +97,31 @@ void CBattleConsole::scrollDown(ui32 by)
|
||||
lastShown += by;
|
||||
}
|
||||
|
||||
CBattleConsole::CBattleConsole() : lastShown(-1), alterTxt(""), whoSetAlter(0)
|
||||
{}
|
||||
CBattleConsole::CBattleConsole(const Rect & position) : lastShown(-1)
|
||||
{
|
||||
pos = position;
|
||||
}
|
||||
|
||||
void CBattleConsole::clearMatching(const std::string & Text)
|
||||
{
|
||||
if (ingcAlter == Text)
|
||||
clear();
|
||||
}
|
||||
|
||||
void CBattleConsole::clear()
|
||||
{
|
||||
ingcAlter.clear();
|
||||
}
|
||||
|
||||
void CBattleConsole::write(const std::string & Text)
|
||||
{
|
||||
ingcAlter = Text;
|
||||
}
|
||||
|
||||
void CBattleConsole::lock(bool shouldLock)
|
||||
{
|
||||
// no-op?
|
||||
}
|
||||
|
||||
void CBattleHero::show(SDL_Surface * to)
|
||||
{
|
||||
@ -627,7 +621,7 @@ void CClickableHex::hover(bool on)
|
||||
//Hoverable::hover(on);
|
||||
if(!on && setAlterText)
|
||||
{
|
||||
myInterface->console->alterTxt = std::string();
|
||||
myInterface->controlPanel->console->clear();
|
||||
setAlterText = false;
|
||||
}
|
||||
}
|
||||
@ -644,20 +638,20 @@ void CClickableHex::mouseMoved(const SDL_MouseMotionEvent &sEvent)
|
||||
if(hovered && strictHovered) //print attacked creature to console
|
||||
{
|
||||
const CStack * attackedStack = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber);
|
||||
if(myInterface->console->alterTxt.size() == 0 &&attackedStack != nullptr &&
|
||||
if( attackedStack != nullptr &&
|
||||
attackedStack->owner != myInterface->getCurrentPlayerInterface()->playerID &&
|
||||
attackedStack->alive())
|
||||
{
|
||||
MetaString text;
|
||||
text.addTxt(MetaString::GENERAL_TXT, 220);
|
||||
attackedStack->addNameReplacement(text);
|
||||
myInterface->console->alterTxt = text.toString();
|
||||
myInterface->controlPanel->console->write(text.toString());
|
||||
setAlterText = true;
|
||||
}
|
||||
}
|
||||
else if(setAlterText)
|
||||
{
|
||||
myInterface->console->alterTxt = std::string();
|
||||
myInterface->controlPanel->console->clear();
|
||||
setAlterText = false;
|
||||
}
|
||||
}
|
||||
|
@ -39,23 +39,26 @@ class CAnimImage;
|
||||
class CPlayerInterface;
|
||||
|
||||
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
|
||||
class CBattleConsole : public CIntObject
|
||||
class CBattleConsole : public CIntObject, public IStatusBar
|
||||
{
|
||||
private:
|
||||
std::vector< std::string > texts; //a place where texts are stored
|
||||
int lastShown; //last shown line of text
|
||||
public:
|
||||
std::string alterTxt; //if it's not empty, this text is displayed
|
||||
|
||||
std::string ingcAlter; //alternative text set by in-game console - very important!
|
||||
int whoSetAlter; //who set alter text; 0 - battle interface or none, 1 - button
|
||||
CBattleConsole();
|
||||
public:
|
||||
CBattleConsole(const Rect & position);
|
||||
void showAll(SDL_Surface * to = 0) override;
|
||||
|
||||
bool addText(const std::string &text); //adds text at the last position; returns false if failed (e.g. text longer than 70 characters)
|
||||
void alterText(const std::string &text); //place string at alterTxt
|
||||
void eraseText(ui32 pos); //erases added text at position pos
|
||||
void changeTextAt(const std::string &text, ui32 pos); //if we have more than pos texts, pos-th is changed to given one
|
||||
void scrollUp(ui32 by = 1); //scrolls console up by 'by' positions
|
||||
void scrollDown(ui32 by = 1); //scrolls console up by 'by' positions
|
||||
|
||||
void clearMatching(const std::string & Text) override;
|
||||
void clear() override;
|
||||
void write(const std::string & Text) override;
|
||||
void lock(bool shouldLock) override;
|
||||
|
||||
};
|
||||
|
||||
/// Hero battle animation
|
||||
|
@ -20,7 +20,7 @@ template <typename T> struct CondSh;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CFramerateManager;
|
||||
class CGStatusBar;
|
||||
class IStatusBar;
|
||||
class CIntObject;
|
||||
class IUpdateable;
|
||||
class IShowActivatable;
|
||||
@ -65,7 +65,7 @@ class CGuiHandler
|
||||
public:
|
||||
CFramerateManager * mainFPSmng; //to keep const framerate
|
||||
std::list<std::shared_ptr<IShowActivatable>> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
|
||||
std::shared_ptr<CGStatusBar> statusbar;
|
||||
std::shared_ptr<IStatusBar> statusbar;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<IShowActivatable>> disposed;
|
||||
|
@ -373,3 +373,6 @@ void WindowBase::close()
|
||||
logGlobal->error("Only top interface must be closed");
|
||||
GH.popInts(1);
|
||||
}
|
||||
|
||||
IStatusBar::~IStatusBar()
|
||||
{}
|
||||
|
@ -217,3 +217,13 @@ public:
|
||||
protected:
|
||||
void close();
|
||||
};
|
||||
|
||||
class IStatusBar
|
||||
{
|
||||
public:
|
||||
virtual ~IStatusBar();
|
||||
virtual void clear() = 0;
|
||||
virtual void clearMatching(const std::string & Text) = 0;
|
||||
virtual void write(const std::string & Text) = 0;
|
||||
virtual void lock(bool shouldLock) = 0;
|
||||
};
|
||||
|
@ -87,7 +87,7 @@ void CList::CListItem::clickLeft(tribool down, bool previousState)
|
||||
void CList::CListItem::hover(bool on)
|
||||
{
|
||||
if (on)
|
||||
GH.statusbar->setText(getHoverText());
|
||||
GH.statusbar->write(getHoverText());
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
@ -572,7 +572,7 @@ void CMinimap::clickRight(tribool down, bool previousState)
|
||||
void CMinimap::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->setText(CGI->generaltexth->zelp[291].first);
|
||||
GH.statusbar->write(CGI->generaltexth->zelp[291].first);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
@ -876,7 +876,7 @@ void CInfoBar::clickRight(tribool down, bool previousState)
|
||||
void CInfoBar::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->setText(CGI->generaltexth->zelp[292].first);
|
||||
GH.statusbar->write(CGI->generaltexth->zelp[292].first);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
@ -1129,20 +1129,17 @@ void CInGameConsole::textEdited(const SDL_TextEditingEvent & event)
|
||||
|
||||
void CInGameConsole::startEnteringText()
|
||||
{
|
||||
CSDL_Ext::startTextInput(&GH.statusbar->pos);
|
||||
auto * statusBar = dynamic_cast<CGStatusBar*>(GH.statusbar.get());
|
||||
|
||||
enteredText = "_";
|
||||
if(GH.topInt() == adventureInt)
|
||||
if (statusBar)
|
||||
{
|
||||
GH.statusbar->alignment = TOPLEFT;
|
||||
GH.statusbar->setText(enteredText);
|
||||
CSDL_Ext::startTextInput(&statusBar->pos);
|
||||
|
||||
//Prevent changes to the text from mouse interaction with the adventure map
|
||||
GH.statusbar->lock(true);
|
||||
}
|
||||
else if(LOCPLINT->battleInt)
|
||||
{
|
||||
LOCPLINT->battleInt->console->ingcAlter = enteredText;
|
||||
enteredText = "_";
|
||||
|
||||
statusBar->alignment = TOPLEFT;
|
||||
statusBar->write(enteredText);
|
||||
statusBar->lock(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1159,31 +1156,23 @@ void CInGameConsole::endEnteringText(bool printEnteredText)
|
||||
//print(txt);
|
||||
}
|
||||
enteredText.clear();
|
||||
if(GH.topInt() == adventureInt)
|
||||
|
||||
auto * statusBar = dynamic_cast<CGStatusBar*>(GH.statusbar.get());
|
||||
|
||||
if(statusBar)
|
||||
{
|
||||
GH.statusbar->alignment = CENTER;
|
||||
GH.statusbar->lock(false);
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
else if(LOCPLINT->battleInt)
|
||||
{
|
||||
LOCPLINT->battleInt->console->ingcAlter = "";
|
||||
statusBar->alignment = CENTER;
|
||||
}
|
||||
GH.statusbar->lock(false);
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
||||
void CInGameConsole::refreshEnteredText()
|
||||
{
|
||||
if(GH.topInt() == adventureInt)
|
||||
{
|
||||
GH.statusbar->lock(false);
|
||||
GH.statusbar->clear();
|
||||
GH.statusbar->setText(enteredText);
|
||||
GH.statusbar->lock(true);
|
||||
}
|
||||
else if(LOCPLINT->battleInt)
|
||||
{
|
||||
LOCPLINT->battleInt->console->ingcAlter = enteredText;
|
||||
}
|
||||
GH.statusbar->lock(false);
|
||||
GH.statusbar->clear();
|
||||
GH.statusbar->write(enteredText);
|
||||
GH.statusbar->lock(true);
|
||||
}
|
||||
|
||||
CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
|
||||
|
@ -207,26 +207,10 @@ void CButton::hover (bool on)
|
||||
|
||||
if(!name.empty() && !isBlocked()) //if there is no name, there is nothing to display also
|
||||
{
|
||||
if (LOCPLINT && LOCPLINT->battleInt) //for battle buttons
|
||||
{
|
||||
if(on && LOCPLINT->battleInt->console->alterTxt == "")
|
||||
{
|
||||
LOCPLINT->battleInt->console->alterTxt = name;
|
||||
LOCPLINT->battleInt->console->whoSetAlter = 1;
|
||||
}
|
||||
else if (LOCPLINT->battleInt->console->alterTxt == name)
|
||||
{
|
||||
LOCPLINT->battleInt->console->alterTxt = "";
|
||||
LOCPLINT->battleInt->console->whoSetAlter = 0;
|
||||
}
|
||||
}
|
||||
else if(GH.statusbar) //for other buttons
|
||||
{
|
||||
if (on)
|
||||
GH.statusbar->setText(name);
|
||||
else if ( GH.statusbar->getText()==(name) )
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
if (on)
|
||||
GH.statusbar->write(name);
|
||||
else
|
||||
GH.statusbar->clearMatching(name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,7 +514,7 @@ void CVolumeSlider::clickRight(tribool down, bool previousState)
|
||||
if(!helpBox.empty())
|
||||
CRClickPopup::createAndPush(helpBox);
|
||||
if(GH.statusbar)
|
||||
GH.statusbar->setText(helpBox);
|
||||
GH.statusbar->write(helpBox);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ void CGarrisonSlot::hover (bool on)
|
||||
temp = CGI->generaltexth->tcommands[11]; //Empty
|
||||
}
|
||||
}
|
||||
GH.statusbar->setText(temp);
|
||||
GH.statusbar->write(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -34,9 +34,9 @@
|
||||
void CHoverableArea::hover (bool on)
|
||||
{
|
||||
if (on)
|
||||
GH.statusbar->setText(hoverText);
|
||||
else if (GH.statusbar->getText()==hoverText)
|
||||
GH.statusbar->clear();
|
||||
GH.statusbar->write(hoverText);
|
||||
else
|
||||
GH.statusbar->clearMatching(hoverText);
|
||||
}
|
||||
|
||||
CHoverableArea::CHoverableArea()
|
||||
@ -150,7 +150,7 @@ void CHeroArea::clickRight(tribool down, bool previousState)
|
||||
void CHeroArea::hover(bool on)
|
||||
{
|
||||
if (on && hero)
|
||||
GH.statusbar->setText(hero->getObjectName());
|
||||
GH.statusbar->write(hero->getObjectName());
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
@ -339,12 +339,18 @@ void CTextBox::setText(const std::string & text)
|
||||
}
|
||||
}
|
||||
|
||||
void CGStatusBar::setText(const std::string & Text)
|
||||
void CGStatusBar::write(const std::string & Text)
|
||||
{
|
||||
if(!textLock)
|
||||
CLabel::setText(Text);
|
||||
}
|
||||
|
||||
void CGStatusBar::clearMatching(const std::string & Text)
|
||||
{
|
||||
if (getText() == Text)
|
||||
clear();
|
||||
}
|
||||
|
||||
void CGStatusBar::clear()
|
||||
{
|
||||
setText("");
|
||||
|
@ -114,7 +114,7 @@ public:
|
||||
};
|
||||
|
||||
/// Status bar which is shown at the bottom of the in-game screens
|
||||
class CGStatusBar : public CLabel, public std::enable_shared_from_this<CGStatusBar>
|
||||
class CGStatusBar : public CLabel, public std::enable_shared_from_this<CGStatusBar>, public IStatusBar
|
||||
{
|
||||
bool textLock; //Used for blocking changes to the text
|
||||
void init();
|
||||
@ -132,12 +132,14 @@ public:
|
||||
ret->init();
|
||||
return ret;
|
||||
}
|
||||
void clear();//clears statusbar and refreshes
|
||||
void setText(const std::string & Text) override; //prints text and refreshes statusbar
|
||||
|
||||
void clearMatching(const std::string & Text) override;
|
||||
void clear() override;//clears statusbar and refreshes
|
||||
void write(const std::string & Text) override; //prints text and refreshes statusbar
|
||||
|
||||
void show(SDL_Surface * to) override; //shows statusbar (with current text)
|
||||
|
||||
void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called
|
||||
void lock(bool shouldLock) override; //If true, current text cannot be changed until lock(false) is called
|
||||
};
|
||||
|
||||
class CFocusable;
|
||||
|
@ -261,7 +261,7 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
||||
|| (*parent->selectedBuilding)<(*this)) //or we are on top
|
||||
{
|
||||
parent->selectedBuilding = this;
|
||||
GH.statusbar->setText(getSubtitle());
|
||||
GH.statusbar->write(getSubtitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,7 +379,7 @@ void CHeroGSlot::hover(bool on)
|
||||
}
|
||||
}
|
||||
if(temp.size())
|
||||
GH.statusbar->setText(temp);
|
||||
GH.statusbar->write(temp);
|
||||
}
|
||||
|
||||
void CHeroGSlot::clickLeft(tribool down, bool previousState)
|
||||
@ -1031,11 +1031,11 @@ void CCreaInfo::hover(bool on)
|
||||
|
||||
if(on)
|
||||
{
|
||||
GH.statusbar->setText(message);
|
||||
GH.statusbar->write(message);
|
||||
}
|
||||
else if (message == GH.statusbar->getText())
|
||||
else
|
||||
{
|
||||
GH.statusbar->clear();
|
||||
GH.statusbar->clearMatching(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1105,7 +1105,7 @@ void CTownInfo::hover(bool on)
|
||||
if(on)
|
||||
{
|
||||
if(building )
|
||||
GH.statusbar->setText(building->Name());
|
||||
GH.statusbar->write(building->Name());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1326,7 +1326,7 @@ void CHallInterface::CBuildingBox::hover(bool on)
|
||||
else
|
||||
toPrint = CGI->generaltexth->hcommands[state];
|
||||
boost::algorithm::replace_first(toPrint,"%s",building->Name());
|
||||
GH.statusbar->setText(toPrint);
|
||||
GH.statusbar->write(toPrint);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1515,7 +1515,7 @@ void LabeledValue::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
GH.statusbar->setText(hoverText);
|
||||
GH.statusbar->write(hoverText);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1683,7 +1683,7 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding()
|
||||
void CFortScreen::RecruitArea::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->setText(hoverText);
|
||||
GH.statusbar->write(hoverText);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
@ -1774,7 +1774,7 @@ void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState)
|
||||
void CMageGuildScreen::Scroll::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->setText(spell->name);
|
||||
GH.statusbar->write(spell->name);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
|
||||
|
@ -244,13 +244,13 @@ void CTradeWindow::CTradeableItem::hover(bool on)
|
||||
{
|
||||
case CREATURE:
|
||||
case CREATURE_PLACEHOLDER:
|
||||
GH.statusbar->setText(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->namePl));
|
||||
GH.statusbar->write(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->namePl));
|
||||
break;
|
||||
case ARTIFACT_PLACEHOLDER:
|
||||
if(id < 0)
|
||||
GH.statusbar->setText(CGI->generaltexth->zelp[582].first);
|
||||
GH.statusbar->write(CGI->generaltexth->zelp[582].first);
|
||||
else
|
||||
GH.statusbar->setText(CGI->artifacts()->getByIndex(id)->getName());
|
||||
GH.statusbar->write(CGI->artifacts()->getByIndex(id)->getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ void CTavernWindow::HeroPortrait::hover(bool on)
|
||||
{
|
||||
//Hoverable::hover(on);
|
||||
if(on)
|
||||
GH.statusbar->setText(hoverName);
|
||||
GH.statusbar->write(hoverName);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
@ -1550,7 +1550,7 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState)
|
||||
void CUniversityWindow::CItem::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->setText(CGI->skillh->skillName(ID));
|
||||
GH.statusbar->write(CGI->skillh->skillName(ID));
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user