mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +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
|
../CCallback.cpp
|
||||||
|
|
||||||
battle/CBattleAnimations.cpp
|
battle/CBattleAnimations.cpp
|
||||||
|
battle/CBattleControlPanel.cpp
|
||||||
battle/CBattleInterfaceClasses.cpp
|
battle/CBattleInterfaceClasses.cpp
|
||||||
battle/CBattleInterface.cpp
|
battle/CBattleInterface.cpp
|
||||||
battle/CBattleFieldController.cpp
|
battle/CBattleFieldController.cpp
|
||||||
@ -80,6 +81,7 @@ set(client_HEADERS
|
|||||||
StdInc.h
|
StdInc.h
|
||||||
|
|
||||||
battle/CBattleAnimations.h
|
battle/CBattleAnimations.h
|
||||||
|
battle/CBattleControlPanel.h
|
||||||
battle/CBattleInterfaceClasses.h
|
battle/CBattleInterfaceClasses.h
|
||||||
battle/CBattleInterface.h
|
battle/CBattleInterface.h
|
||||||
battle/CBattleFieldController.h
|
battle/CBattleFieldController.h
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "battle/CBattleInterface.h"
|
#include "battle/CBattleInterface.h"
|
||||||
#include "battle/CBattleFieldController.h"
|
#include "battle/CBattleFieldController.h"
|
||||||
#include "battle/CBattleInterfaceClasses.h"
|
#include "battle/CBattleInterfaceClasses.h"
|
||||||
|
#include "battle/CBattleControlPanel.h"
|
||||||
#include "../CCallback.h"
|
#include "../CCallback.h"
|
||||||
#include "windows/CCastleInterface.h"
|
#include "windows/CCastleInterface.h"
|
||||||
#include "gui/CCursorHandler.h"
|
#include "gui/CCursorHandler.h"
|
||||||
@ -1028,19 +1029,19 @@ void CPlayerInterface::battleAttack(const BattleAttack * ba)
|
|||||||
|
|
||||||
if(ba->lucky()) //lucky hit
|
if(ba->lucky()) //lucky hit
|
||||||
{
|
{
|
||||||
battleInt->console->addText(attacker->formatGeneralMessage(-45));
|
battleInt->controlPanel->console->addText(attacker->formatGeneralMessage(-45));
|
||||||
battleInt->displayEffect(18, attacker->getPosition());
|
battleInt->displayEffect(18, attacker->getPosition());
|
||||||
CCS->soundh->playSound(soundBase::GOODLUCK);
|
CCS->soundh->playSound(soundBase::GOODLUCK);
|
||||||
}
|
}
|
||||||
if(ba->unlucky()) //unlucky hit
|
if(ba->unlucky()) //unlucky hit
|
||||||
{
|
{
|
||||||
battleInt->console->addText(attacker->formatGeneralMessage(-44));
|
battleInt->controlPanel->console->addText(attacker->formatGeneralMessage(-44));
|
||||||
battleInt->displayEffect(48, attacker->getPosition());
|
battleInt->displayEffect(48, attacker->getPosition());
|
||||||
CCS->soundh->playSound(soundBase::BADLUCK);
|
CCS->soundh->playSound(soundBase::BADLUCK);
|
||||||
}
|
}
|
||||||
if(ba->deathBlow())
|
if(ba->deathBlow())
|
||||||
{
|
{
|
||||||
battleInt->console->addText(attacker->formatGeneralMessage(365));
|
battleInt->controlPanel->console->addText(attacker->formatGeneralMessage(365));
|
||||||
for(auto & elem : ba->bsa)
|
for(auto & elem : ba->bsa)
|
||||||
{
|
{
|
||||||
const CStack * attacked = cb->battleGetStackByID(elem.stackAttacked);
|
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 "CBattleObstacleController.h"
|
||||||
#include "CBattleSiegeController.h"
|
#include "CBattleSiegeController.h"
|
||||||
#include "CBattleFieldController.h"
|
#include "CBattleFieldController.h"
|
||||||
|
#include "CBattleControlPanel.h"
|
||||||
|
|
||||||
#include "../CBitmapHandler.h"
|
#include "../CBitmapHandler.h"
|
||||||
#include "../CGameInfo.h"
|
#include "../CGameInfo.h"
|
||||||
@ -200,37 +201,6 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
CSDL_Ext::alphaTransform(amountEffNeutral);
|
CSDL_Ext::alphaTransform(amountEffNeutral);
|
||||||
transformPalette(amountEffNeutral, 1.00, 1.00, 0.18);
|
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
|
//loading hero animations
|
||||||
if(hero1) // attacking hero
|
if(hero1) // attacking hero
|
||||||
{
|
{
|
||||||
@ -281,7 +251,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
obstacleController.reset(new CBattleObstacleController(this));
|
obstacleController.reset(new CBattleObstacleController(this));
|
||||||
|
|
||||||
if(tacticsMode)
|
if(tacticsMode)
|
||||||
bTacticNextStack();
|
tacticNextStack(nullptr);
|
||||||
|
|
||||||
CCS->musich->stopMusic();
|
CCS->musich->stopMusic();
|
||||||
battleIntroSoundChannel = CCS->soundh->playSoundFromSet(CCS->soundh->battleIntroSounds);
|
battleIntroSoundChannel = CCS->soundh->playSoundFromSet(CCS->soundh->battleIntroSounds);
|
||||||
@ -291,7 +261,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
{
|
{
|
||||||
CCS->musich->playMusicFromSet("battle", true, true);
|
CCS->musich->playMusicFromSet("battle", true, true);
|
||||||
battleActionsStarted = true;
|
battleActionsStarted = true;
|
||||||
blockUI(settings["session"]["spectate"].Bool());
|
controlPanel->blockUI(settings["session"]["spectate"].Bool());
|
||||||
battleIntroSoundChannel = -1;
|
battleIntroSoundChannel = -1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -301,7 +271,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
currentAction = PossiblePlayerBattleAction::INVALID;
|
currentAction = PossiblePlayerBattleAction::INVALID;
|
||||||
selectedAction = PossiblePlayerBattleAction::INVALID;
|
selectedAction = PossiblePlayerBattleAction::INVALID;
|
||||||
addUsedEvents(RCLICK | MOVE | KEYBOARD);
|
addUsedEvents(RCLICK | MOVE | KEYBOARD);
|
||||||
blockUI(true);
|
controlPanel->blockUI(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleInterface::~CBattleInterface()
|
CBattleInterface::~CBattleInterface()
|
||||||
@ -313,7 +283,6 @@ CBattleInterface::~CBattleInterface()
|
|||||||
{
|
{
|
||||||
deactivate();
|
deactivate();
|
||||||
}
|
}
|
||||||
SDL_FreeSurface(menu);
|
|
||||||
SDL_FreeSurface(amountNormal);
|
SDL_FreeSurface(amountNormal);
|
||||||
SDL_FreeSurface(amountNegative);
|
SDL_FreeSurface(amountNegative);
|
||||||
SDL_FreeSurface(amountPositive);
|
SDL_FreeSurface(amountPositive);
|
||||||
@ -357,20 +326,12 @@ void CBattleInterface::setPrintMouseShadow(bool set)
|
|||||||
|
|
||||||
void CBattleInterface::activate()
|
void CBattleInterface::activate()
|
||||||
{
|
{
|
||||||
|
controlPanel->activate();
|
||||||
|
|
||||||
if (curInt->isAutoFightOn)
|
if (curInt->isAutoFightOn)
|
||||||
{
|
|
||||||
bAutofight->activate();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
CIntObject::activate();
|
CIntObject::activate();
|
||||||
bOptions->activate();
|
|
||||||
bSurrender->activate();
|
|
||||||
bFlee->activate();
|
|
||||||
bAutofight->activate();
|
|
||||||
bSpell->activate();
|
|
||||||
bWait->activate();
|
|
||||||
bDefence->activate();
|
|
||||||
|
|
||||||
if (attackingHero)
|
if (attackingHero)
|
||||||
attackingHero->activate();
|
attackingHero->activate();
|
||||||
@ -382,32 +343,14 @@ void CBattleInterface::activate()
|
|||||||
if (settings["battle"]["showQueue"].Bool())
|
if (settings["battle"]["showQueue"].Bool())
|
||||||
queue->activate();
|
queue->activate();
|
||||||
|
|
||||||
if (tacticsMode)
|
|
||||||
{
|
|
||||||
btactNext->activate();
|
|
||||||
btactEnd->activate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bConsoleUp->activate();
|
|
||||||
bConsoleDown->activate();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCPLINT->cingconsole->activate();
|
LOCPLINT->cingconsole->activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::deactivate()
|
void CBattleInterface::deactivate()
|
||||||
{
|
{
|
||||||
|
controlPanel->deactivate();
|
||||||
CIntObject::deactivate();
|
CIntObject::deactivate();
|
||||||
|
|
||||||
bOptions->deactivate();
|
|
||||||
bSurrender->deactivate();
|
|
||||||
bFlee->deactivate();
|
|
||||||
bAutofight->deactivate();
|
|
||||||
bSpell->deactivate();
|
|
||||||
bWait->deactivate();
|
|
||||||
bDefence->deactivate();
|
|
||||||
|
|
||||||
fieldController->deactivate();
|
fieldController->deactivate();
|
||||||
|
|
||||||
if (attackingHero)
|
if (attackingHero)
|
||||||
@ -417,17 +360,6 @@ void CBattleInterface::deactivate()
|
|||||||
if (settings["battle"]["showQueue"].Bool())
|
if (settings["battle"]["showQueue"].Bool())
|
||||||
queue->deactivate();
|
queue->deactivate();
|
||||||
|
|
||||||
if (tacticsMode)
|
|
||||||
{
|
|
||||||
btactNext->deactivate();
|
|
||||||
btactEnd->deactivate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bConsoleUp->deactivate();
|
|
||||||
bConsoleDown->deactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCPLINT->cingconsole->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)
|
void CBattleInterface::unitAdded(const CStack * stack)
|
||||||
{
|
{
|
||||||
creDir[stack->ID] = stack->side == BattleSide::ATTACKER; // must be set before getting stack position
|
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)
|
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)
|
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();
|
std::string formatted = line.toString();
|
||||||
boost::algorithm::trim(formatted);
|
boost::algorithm::trim(formatted);
|
||||||
if(!console->addText(formatted))
|
if(!controlPanel->console->addText(formatted))
|
||||||
logGlobal->warn("Too long battle log line");
|
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()));
|
boost::algorithm::replace_first(hlp,"%s",(stack->getName()));
|
||||||
displayEffect(20,stack->getPosition());
|
displayEffect(20,stack->getPosition());
|
||||||
CCS->soundh->playSound(soundBase::GOODMRLE);
|
CCS->soundh->playSound(soundBase::GOODMRLE);
|
||||||
console->addText(hlp);
|
controlPanel->console->addText(hlp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1194,7 +943,7 @@ void CBattleInterface::setActiveStack(const CStack *stack)
|
|||||||
if (activeStack) // update UI
|
if (activeStack) // update UI
|
||||||
creAnims[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder());
|
creAnims[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder());
|
||||||
|
|
||||||
blockUI(activeStack == nullptr);
|
controlPanel->blockUI(activeStack == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::setHoveredStack(const CStack *stack)
|
void CBattleInterface::setHoveredStack(const CStack *stack)
|
||||||
@ -1431,7 +1180,7 @@ void CBattleInterface::endAction(const BattleAction* action)
|
|||||||
queue->update();
|
queue->update();
|
||||||
|
|
||||||
if (tacticsMode) //stack ended movement in tactics phase -> select the next one
|
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
|
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);
|
fieldController->redrawBackgroundWithHexes(activeStack);
|
||||||
@ -1439,12 +1188,12 @@ void CBattleInterface::endAction(const BattleAction* action)
|
|||||||
if (activeStack && !animsAreDisplayed.get() && pendingAnims.empty() && !active)
|
if (activeStack && !animsAreDisplayed.get() && pendingAnims.empty() && !active)
|
||||||
{
|
{
|
||||||
logGlobal->warn("Something wrong... interface was deactivated but there is no animation. Reactivating...");
|
logGlobal->warn("Something wrong... interface was deactivated but there is no animation. Reactivating...");
|
||||||
blockUI(false);
|
controlPanel->blockUI(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// block UI if no active stack (e.g. enemy turn);
|
// 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)
|
void CBattleInterface::startAction(const BattleAction* action)
|
||||||
{
|
{
|
||||||
//setActiveStack(nullptr);
|
//setActiveStack(nullptr);
|
||||||
setHoveredStack(nullptr);
|
setHoveredStack(nullptr);
|
||||||
blockUI(true);
|
controlPanel->blockUI(true);
|
||||||
|
|
||||||
if(action->actionType == EActionType::END_TACTIC_PHASE)
|
if(action->actionType == EActionType::END_TACTIC_PHASE)
|
||||||
{
|
{
|
||||||
SDL_FreeSurface(menu);
|
controlPanel->tacticPhaseEnded();
|
||||||
menu = BitmapHandler::loadBitmap("CBAR.bmp");
|
|
||||||
|
|
||||||
graphics->blueToPlayersAdv(menu, curInt->playerID);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1586,7 +1292,7 @@ void CBattleInterface::startAction(const BattleAction* action)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(txtid != 0)
|
if(txtid != 0)
|
||||||
console->addText(stack->formatGeneralMessage(txtid));
|
controlPanel->console->addText(stack->formatGeneralMessage(txtid));
|
||||||
|
|
||||||
//displaying special abilities
|
//displaying special abilities
|
||||||
switch(action->actionType)
|
switch(action->actionType)
|
||||||
@ -1604,10 +1310,10 @@ void CBattleInterface::waitForAnims()
|
|||||||
animsAreDisplayed.waitWhileTrue();
|
animsAreDisplayed.waitWhileTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::bEndTacticPhase()
|
void CBattleInterface::tacticPhaseEnd()
|
||||||
{
|
{
|
||||||
setActiveStack(nullptr);
|
setActiveStack(nullptr);
|
||||||
blockUI(true);
|
controlPanel->blockUI(true);
|
||||||
tacticsMode = false;
|
tacticsMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,7 +1322,7 @@ static bool immobile(const CStack *s)
|
|||||||
return !s->Speed(0, true); //should bound stacks be immobile?
|
return !s->Speed(0, true); //should bound stacks be immobile?
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::bTacticNextStack(const CStack * current)
|
void CBattleInterface::tacticNextStack(const CStack * current)
|
||||||
{
|
{
|
||||||
if (!current)
|
if (!current)
|
||||||
current = activeStack;
|
current = activeStack;
|
||||||
@ -1628,7 +1334,7 @@ void CBattleInterface::bTacticNextStack(const CStack * current)
|
|||||||
vstd::erase_if (stacksOfMine, &immobile);
|
vstd::erase_if (stacksOfMine, &immobile);
|
||||||
if (stacksOfMine.empty())
|
if (stacksOfMine.empty())
|
||||||
{
|
{
|
||||||
bEndTacticPhase();
|
tacticPhaseEnd();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2099,8 +1805,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
{
|
{
|
||||||
if (setCursor)
|
if (setCursor)
|
||||||
CCS->curh->changeGraphic(cursorType, cursorFrame);
|
CCS->curh->changeGraphic(cursorType, cursorFrame);
|
||||||
this->console->alterText(consoleMsg);
|
controlPanel->console->write(consoleMsg);
|
||||||
this->console->whoSetAlter = 0;
|
|
||||||
}
|
}
|
||||||
if (eventType == LCLICK && realizeAction)
|
if (eventType == LCLICK && realizeAction)
|
||||||
{
|
{
|
||||||
@ -2112,7 +1817,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
realizeAction();
|
realizeAction();
|
||||||
if (!secondaryTarget) //do not replace teleport or sacrifice cursor
|
if (!secondaryTarget) //do not replace teleport or sacrifice cursor
|
||||||
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
|
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 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?
|
//TODO any solution to merge tactics phase & normal phase in the way it is handled by the player and battle interface?
|
||||||
setActiveStack(nullptr);
|
setActiveStack(nullptr);
|
||||||
blockUI(true);
|
controlPanel->blockUI(true);
|
||||||
tacticsMode = false;
|
tacticsMode = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2443,31 +2148,9 @@ void CBattleInterface::showBattleEffects(SDL_Surface *to, const std::vector<cons
|
|||||||
|
|
||||||
void CBattleInterface::showInterface(SDL_Surface *to)
|
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
|
//showing in-game console
|
||||||
LOCPLINT->cingconsole->show(to);
|
LOCPLINT->cingconsole->show(to);
|
||||||
|
controlPanel->show(to);
|
||||||
|
|
||||||
Rect posWithQueue = Rect(pos.x, pos.y, 800, 600);
|
Rect posWithQueue = Rect(pos.x, pos.y, 800, 600);
|
||||||
|
|
||||||
@ -2594,7 +2277,7 @@ void CBattleInterface::updateBattleAnimations()
|
|||||||
if (preSize > 0 && pendingAnims.empty())
|
if (preSize > 0 && pendingAnims.empty())
|
||||||
{
|
{
|
||||||
//anims ended
|
//anims ended
|
||||||
blockUI(activeStack == nullptr);
|
controlPanel->blockUI(activeStack == nullptr);
|
||||||
|
|
||||||
animsAreDisplayed.setn(false);
|
animsAreDisplayed.setn(false);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ class CBattleProjectileController;
|
|||||||
class CBattleSiegeController;
|
class CBattleSiegeController;
|
||||||
class CBattleObstacleController;
|
class CBattleObstacleController;
|
||||||
class CBattleFieldController;
|
class CBattleFieldController;
|
||||||
|
class CBattleControlPanel;
|
||||||
|
|
||||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||||
struct StackAttackedInfo
|
struct StackAttackedInfo
|
||||||
@ -118,24 +119,12 @@ enum class MouseHoveredHexContext
|
|||||||
class CBattleInterface : public WindowBase
|
class CBattleInterface : public WindowBase
|
||||||
{
|
{
|
||||||
private:
|
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> attackingHero;
|
||||||
std::shared_ptr<CBattleHero> defendingHero;
|
std::shared_ptr<CBattleHero> defendingHero;
|
||||||
std::shared_ptr<CStackQueue> queue;
|
std::shared_ptr<CStackQueue> queue;
|
||||||
|
std::shared_ptr<CBattleControlPanel> controlPanel;
|
||||||
|
|
||||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||||
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
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
|
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
|
void tacticNextStack(const CStack *current);
|
||||||
// unlike activate/deactivate this method will correctly grey-out all elements
|
void tacticPhaseEnd();
|
||||||
void blockUI(bool on);
|
|
||||||
|
|
||||||
//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
|
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
|
||||||
void activate() override;
|
void activate() override;
|
||||||
void deactivate() override;
|
void deactivate() override;
|
||||||
@ -332,4 +305,5 @@ public:
|
|||||||
friend class CBattleSiegeController;
|
friend class CBattleSiegeController;
|
||||||
friend class CBattleObstacleController;
|
friend class CBattleObstacleController;
|
||||||
friend class CBattleFieldController;
|
friend class CBattleFieldController;
|
||||||
|
friend class CBattleControlPanel;
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "CBattleInterface.h"
|
#include "CBattleInterface.h"
|
||||||
#include "CBattleSiegeController.h"
|
#include "CBattleSiegeController.h"
|
||||||
#include "CBattleFieldController.h"
|
#include "CBattleFieldController.h"
|
||||||
|
#include "CBattleControlPanel.h"
|
||||||
|
|
||||||
#include "../CBitmapHandler.h"
|
#include "../CBitmapHandler.h"
|
||||||
#include "../CGameInfo.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);
|
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())
|
else if(texts.size())
|
||||||
{
|
{
|
||||||
if(texts.size()==1)
|
if(texts.size()==1)
|
||||||
@ -88,32 +85,6 @@ bool CBattleConsole::addText(const std::string & text)
|
|||||||
lastShown = (int)texts.size()-1;
|
lastShown = (int)texts.size()-1;
|
||||||
return true;
|
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)
|
void CBattleConsole::scrollUp(ui32 by)
|
||||||
{
|
{
|
||||||
if(lastShown > static_cast<int>(by))
|
if(lastShown > static_cast<int>(by))
|
||||||
@ -126,8 +97,31 @@ void CBattleConsole::scrollDown(ui32 by)
|
|||||||
lastShown += 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)
|
void CBattleHero::show(SDL_Surface * to)
|
||||||
{
|
{
|
||||||
@ -627,7 +621,7 @@ void CClickableHex::hover(bool on)
|
|||||||
//Hoverable::hover(on);
|
//Hoverable::hover(on);
|
||||||
if(!on && setAlterText)
|
if(!on && setAlterText)
|
||||||
{
|
{
|
||||||
myInterface->console->alterTxt = std::string();
|
myInterface->controlPanel->console->clear();
|
||||||
setAlterText = false;
|
setAlterText = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -644,20 +638,20 @@ void CClickableHex::mouseMoved(const SDL_MouseMotionEvent &sEvent)
|
|||||||
if(hovered && strictHovered) //print attacked creature to console
|
if(hovered && strictHovered) //print attacked creature to console
|
||||||
{
|
{
|
||||||
const CStack * attackedStack = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber);
|
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->owner != myInterface->getCurrentPlayerInterface()->playerID &&
|
||||||
attackedStack->alive())
|
attackedStack->alive())
|
||||||
{
|
{
|
||||||
MetaString text;
|
MetaString text;
|
||||||
text.addTxt(MetaString::GENERAL_TXT, 220);
|
text.addTxt(MetaString::GENERAL_TXT, 220);
|
||||||
attackedStack->addNameReplacement(text);
|
attackedStack->addNameReplacement(text);
|
||||||
myInterface->console->alterTxt = text.toString();
|
myInterface->controlPanel->console->write(text.toString());
|
||||||
setAlterText = true;
|
setAlterText = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(setAlterText)
|
else if(setAlterText)
|
||||||
{
|
{
|
||||||
myInterface->console->alterTxt = std::string();
|
myInterface->controlPanel->console->clear();
|
||||||
setAlterText = false;
|
setAlterText = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,23 +39,26 @@ class CAnimImage;
|
|||||||
class CPlayerInterface;
|
class CPlayerInterface;
|
||||||
|
|
||||||
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
|
/// 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:
|
private:
|
||||||
std::vector< std::string > texts; //a place where texts are stored
|
std::vector< std::string > texts; //a place where texts are stored
|
||||||
int lastShown; //last shown line of text
|
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!
|
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
|
public:
|
||||||
CBattleConsole();
|
CBattleConsole(const Rect & position);
|
||||||
void showAll(SDL_Surface * to = 0) override;
|
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)
|
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 scrollUp(ui32 by = 1); //scrolls console up by 'by' positions
|
||||||
void scrollDown(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
|
/// Hero battle animation
|
||||||
|
@ -20,7 +20,7 @@ template <typename T> struct CondSh;
|
|||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
class CFramerateManager;
|
class CFramerateManager;
|
||||||
class CGStatusBar;
|
class IStatusBar;
|
||||||
class CIntObject;
|
class CIntObject;
|
||||||
class IUpdateable;
|
class IUpdateable;
|
||||||
class IShowActivatable;
|
class IShowActivatable;
|
||||||
@ -65,7 +65,7 @@ class CGuiHandler
|
|||||||
public:
|
public:
|
||||||
CFramerateManager * mainFPSmng; //to keep const framerate
|
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::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:
|
private:
|
||||||
std::vector<std::shared_ptr<IShowActivatable>> disposed;
|
std::vector<std::shared_ptr<IShowActivatable>> disposed;
|
||||||
|
@ -373,3 +373,6 @@ void WindowBase::close()
|
|||||||
logGlobal->error("Only top interface must be closed");
|
logGlobal->error("Only top interface must be closed");
|
||||||
GH.popInts(1);
|
GH.popInts(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IStatusBar::~IStatusBar()
|
||||||
|
{}
|
||||||
|
@ -217,3 +217,13 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void close();
|
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)
|
void CList::CListItem::hover(bool on)
|
||||||
{
|
{
|
||||||
if (on)
|
if (on)
|
||||||
GH.statusbar->setText(getHoverText());
|
GH.statusbar->write(getHoverText());
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
@ -572,7 +572,7 @@ void CMinimap::clickRight(tribool down, bool previousState)
|
|||||||
void CMinimap::hover(bool on)
|
void CMinimap::hover(bool on)
|
||||||
{
|
{
|
||||||
if(on)
|
if(on)
|
||||||
GH.statusbar->setText(CGI->generaltexth->zelp[291].first);
|
GH.statusbar->write(CGI->generaltexth->zelp[291].first);
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
@ -876,7 +876,7 @@ void CInfoBar::clickRight(tribool down, bool previousState)
|
|||||||
void CInfoBar::hover(bool on)
|
void CInfoBar::hover(bool on)
|
||||||
{
|
{
|
||||||
if(on)
|
if(on)
|
||||||
GH.statusbar->setText(CGI->generaltexth->zelp[292].first);
|
GH.statusbar->write(CGI->generaltexth->zelp[292].first);
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
@ -1129,20 +1129,17 @@ void CInGameConsole::textEdited(const SDL_TextEditingEvent & event)
|
|||||||
|
|
||||||
void CInGameConsole::startEnteringText()
|
void CInGameConsole::startEnteringText()
|
||||||
{
|
{
|
||||||
CSDL_Ext::startTextInput(&GH.statusbar->pos);
|
auto * statusBar = dynamic_cast<CGStatusBar*>(GH.statusbar.get());
|
||||||
|
|
||||||
enteredText = "_";
|
if (statusBar)
|
||||||
if(GH.topInt() == adventureInt)
|
|
||||||
{
|
{
|
||||||
GH.statusbar->alignment = TOPLEFT;
|
CSDL_Ext::startTextInput(&statusBar->pos);
|
||||||
GH.statusbar->setText(enteredText);
|
|
||||||
|
|
||||||
//Prevent changes to the text from mouse interaction with the adventure map
|
enteredText = "_";
|
||||||
GH.statusbar->lock(true);
|
|
||||||
}
|
statusBar->alignment = TOPLEFT;
|
||||||
else if(LOCPLINT->battleInt)
|
statusBar->write(enteredText);
|
||||||
{
|
statusBar->lock(true);
|
||||||
LOCPLINT->battleInt->console->ingcAlter = enteredText;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1159,31 +1156,23 @@ void CInGameConsole::endEnteringText(bool printEnteredText)
|
|||||||
//print(txt);
|
//print(txt);
|
||||||
}
|
}
|
||||||
enteredText.clear();
|
enteredText.clear();
|
||||||
if(GH.topInt() == adventureInt)
|
|
||||||
|
auto * statusBar = dynamic_cast<CGStatusBar*>(GH.statusbar.get());
|
||||||
|
|
||||||
|
if(statusBar)
|
||||||
{
|
{
|
||||||
GH.statusbar->alignment = CENTER;
|
statusBar->alignment = CENTER;
|
||||||
GH.statusbar->lock(false);
|
|
||||||
GH.statusbar->clear();
|
|
||||||
}
|
|
||||||
else if(LOCPLINT->battleInt)
|
|
||||||
{
|
|
||||||
LOCPLINT->battleInt->console->ingcAlter = "";
|
|
||||||
}
|
}
|
||||||
|
GH.statusbar->lock(false);
|
||||||
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInGameConsole::refreshEnteredText()
|
void CInGameConsole::refreshEnteredText()
|
||||||
{
|
{
|
||||||
if(GH.topInt() == adventureInt)
|
GH.statusbar->lock(false);
|
||||||
{
|
GH.statusbar->clear();
|
||||||
GH.statusbar->lock(false);
|
GH.statusbar->write(enteredText);
|
||||||
GH.statusbar->clear();
|
GH.statusbar->lock(true);
|
||||||
GH.statusbar->setText(enteredText);
|
|
||||||
GH.statusbar->lock(true);
|
|
||||||
}
|
|
||||||
else if(LOCPLINT->battleInt)
|
|
||||||
{
|
|
||||||
LOCPLINT->battleInt->console->ingcAlter = enteredText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
|
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(!name.empty() && !isBlocked()) //if there is no name, there is nothing to display also
|
||||||
{
|
{
|
||||||
if (LOCPLINT && LOCPLINT->battleInt) //for battle buttons
|
if (on)
|
||||||
{
|
GH.statusbar->write(name);
|
||||||
if(on && LOCPLINT->battleInt->console->alterTxt == "")
|
else
|
||||||
{
|
GH.statusbar->clearMatching(name);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +514,7 @@ void CVolumeSlider::clickRight(tribool down, bool previousState)
|
|||||||
if(!helpBox.empty())
|
if(!helpBox.empty())
|
||||||
CRClickPopup::createAndPush(helpBox);
|
CRClickPopup::createAndPush(helpBox);
|
||||||
if(GH.statusbar)
|
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
|
temp = CGI->generaltexth->tcommands[11]; //Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GH.statusbar->setText(temp);
|
GH.statusbar->write(temp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -34,9 +34,9 @@
|
|||||||
void CHoverableArea::hover (bool on)
|
void CHoverableArea::hover (bool on)
|
||||||
{
|
{
|
||||||
if (on)
|
if (on)
|
||||||
GH.statusbar->setText(hoverText);
|
GH.statusbar->write(hoverText);
|
||||||
else if (GH.statusbar->getText()==hoverText)
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clearMatching(hoverText);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHoverableArea::CHoverableArea()
|
CHoverableArea::CHoverableArea()
|
||||||
@ -150,7 +150,7 @@ void CHeroArea::clickRight(tribool down, bool previousState)
|
|||||||
void CHeroArea::hover(bool on)
|
void CHeroArea::hover(bool on)
|
||||||
{
|
{
|
||||||
if (on && hero)
|
if (on && hero)
|
||||||
GH.statusbar->setText(hero->getObjectName());
|
GH.statusbar->write(hero->getObjectName());
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
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)
|
if(!textLock)
|
||||||
CLabel::setText(Text);
|
CLabel::setText(Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGStatusBar::clearMatching(const std::string & Text)
|
||||||
|
{
|
||||||
|
if (getText() == Text)
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
void CGStatusBar::clear()
|
void CGStatusBar::clear()
|
||||||
{
|
{
|
||||||
setText("");
|
setText("");
|
||||||
|
@ -114,7 +114,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Status bar which is shown at the bottom of the in-game screens
|
/// 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
|
bool textLock; //Used for blocking changes to the text
|
||||||
void init();
|
void init();
|
||||||
@ -132,12 +132,14 @@ public:
|
|||||||
ret->init();
|
ret->init();
|
||||||
return ret;
|
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 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;
|
class CFocusable;
|
||||||
|
@ -261,7 +261,7 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
|||||||
|| (*parent->selectedBuilding)<(*this)) //or we are on top
|
|| (*parent->selectedBuilding)<(*this)) //or we are on top
|
||||||
{
|
{
|
||||||
parent->selectedBuilding = this;
|
parent->selectedBuilding = this;
|
||||||
GH.statusbar->setText(getSubtitle());
|
GH.statusbar->write(getSubtitle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,7 +379,7 @@ void CHeroGSlot::hover(bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(temp.size())
|
if(temp.size())
|
||||||
GH.statusbar->setText(temp);
|
GH.statusbar->write(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHeroGSlot::clickLeft(tribool down, bool previousState)
|
void CHeroGSlot::clickLeft(tribool down, bool previousState)
|
||||||
@ -1031,11 +1031,11 @@ void CCreaInfo::hover(bool on)
|
|||||||
|
|
||||||
if(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(on)
|
||||||
{
|
{
|
||||||
if(building )
|
if(building )
|
||||||
GH.statusbar->setText(building->Name());
|
GH.statusbar->write(building->Name());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1326,7 +1326,7 @@ void CHallInterface::CBuildingBox::hover(bool on)
|
|||||||
else
|
else
|
||||||
toPrint = CGI->generaltexth->hcommands[state];
|
toPrint = CGI->generaltexth->hcommands[state];
|
||||||
boost::algorithm::replace_first(toPrint,"%s",building->Name());
|
boost::algorithm::replace_first(toPrint,"%s",building->Name());
|
||||||
GH.statusbar->setText(toPrint);
|
GH.statusbar->write(toPrint);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1515,7 +1515,7 @@ void LabeledValue::hover(bool on)
|
|||||||
{
|
{
|
||||||
if(on)
|
if(on)
|
||||||
{
|
{
|
||||||
GH.statusbar->setText(hoverText);
|
GH.statusbar->write(hoverText);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1683,7 +1683,7 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding()
|
|||||||
void CFortScreen::RecruitArea::hover(bool on)
|
void CFortScreen::RecruitArea::hover(bool on)
|
||||||
{
|
{
|
||||||
if(on)
|
if(on)
|
||||||
GH.statusbar->setText(hoverText);
|
GH.statusbar->write(hoverText);
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
@ -1774,7 +1774,7 @@ void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState)
|
|||||||
void CMageGuildScreen::Scroll::hover(bool on)
|
void CMageGuildScreen::Scroll::hover(bool on)
|
||||||
{
|
{
|
||||||
if(on)
|
if(on)
|
||||||
GH.statusbar->setText(spell->name);
|
GH.statusbar->write(spell->name);
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
|
|
||||||
|
@ -244,13 +244,13 @@ void CTradeWindow::CTradeableItem::hover(bool on)
|
|||||||
{
|
{
|
||||||
case CREATURE:
|
case CREATURE:
|
||||||
case CREATURE_PLACEHOLDER:
|
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;
|
break;
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case ARTIFACT_PLACEHOLDER:
|
||||||
if(id < 0)
|
if(id < 0)
|
||||||
GH.statusbar->setText(CGI->generaltexth->zelp[582].first);
|
GH.statusbar->write(CGI->generaltexth->zelp[582].first);
|
||||||
else
|
else
|
||||||
GH.statusbar->setText(CGI->artifacts()->getByIndex(id)->getName());
|
GH.statusbar->write(CGI->artifacts()->getByIndex(id)->getName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,7 +799,7 @@ void CTavernWindow::HeroPortrait::hover(bool on)
|
|||||||
{
|
{
|
||||||
//Hoverable::hover(on);
|
//Hoverable::hover(on);
|
||||||
if(on)
|
if(on)
|
||||||
GH.statusbar->setText(hoverName);
|
GH.statusbar->write(hoverName);
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
@ -1550,7 +1550,7 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState)
|
|||||||
void CUniversityWindow::CItem::hover(bool on)
|
void CUniversityWindow::CItem::hover(bool on)
|
||||||
{
|
{
|
||||||
if(on)
|
if(on)
|
||||||
GH.statusbar->setText(CGI->skillh->skillName(ID));
|
GH.statusbar->write(CGI->skillh->skillName(ID));
|
||||||
else
|
else
|
||||||
GH.statusbar->clear();
|
GH.statusbar->clear();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user