mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge pull request #1645 from rilian-la-te/infobox-pickups
Allow rewardables to show its rewards in info bar
This commit is contained in:
commit
e764a7255d
@ -390,7 +390,7 @@ void AIGateway::advmapSpellCast(const CGHeroInstance * caster, int spellID)
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void AIGateway::showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID)
|
||||
void AIGateway::showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "soundID '%i'", soundID);
|
||||
NET_EVENT_HANDLER;
|
||||
@ -632,7 +632,7 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vector<C
|
||||
// TODO: Find better way to understand it is Chest of Treasures
|
||||
if(hero.validAndSet()
|
||||
&& components.size() == 2
|
||||
&& components.front().id == Component::RESOURCE
|
||||
&& components.front().id == Component::EComponentType::RESOURCE
|
||||
&& (nullkiller->heroManager->getHeroRole(hero) != HeroRole::MAIN
|
||||
|| nullkiller->buildAnalyzer->getGoldPreasure() > MAX_GOLD_PEASURE))
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ public:
|
||||
void playerBonusChanged(const Bonus & bonus, bool gain) override;
|
||||
void heroCreated(const CGHeroInstance *) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
|
||||
void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void requestRealized(PackageApplied * pa) override;
|
||||
void receivedResource() override;
|
||||
void objectRemoved(const CGObjectInstance * obj) override;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/NetPacksBase.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/serializer/CTypeList.h"
|
||||
#include "../../lib/serializer/BinarySerializer.h"
|
||||
@ -475,7 +476,7 @@ void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID)
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void VCAI::showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID)
|
||||
void VCAI::showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "soundID '%i'", soundID);
|
||||
NET_EVENT_HANDLER;
|
||||
|
@ -186,7 +186,7 @@ public:
|
||||
void playerBonusChanged(const Bonus & bonus, bool gain) override;
|
||||
void heroCreated(const CGHeroInstance *) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
|
||||
void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void requestRealized(PackageApplied * pa) override;
|
||||
void receivedResource() override;
|
||||
void objectRemoved(const CGObjectInstance * obj) override;
|
||||
|
@ -47,6 +47,8 @@
|
||||
"vcmi.systemOptions.framerateButton.hover" : "Show FPS",
|
||||
"vcmi.systemOptions.framerateButton.help" : "{Show FPS}\n\n Toggles visibility of Frames Per Second counter in corner of game window.",
|
||||
|
||||
"vcmi.adventureOptions.infoBarPick.hover" : "Show Messages in Info Panel",
|
||||
"vcmi.adventureOptions.infoBarPick.help" : "{Show Messages in Info Panel}\n\nWhenever possible, game messages from visiting map objects will be shown in info bar instead of showing up as popup windows",
|
||||
"vcmi.adventureOptions.numericQuantities.hover" : "Numeric Creature Quantities",
|
||||
"vcmi.adventureOptions.numericQuantities.help" : "{Numeric Creature Quantities}\n\n Shows approximate enemy creatures quantities in numeric A-B format.",
|
||||
"vcmi.adventureOptions.forceMovementInfo.hover" : "Always Show Movement Cost",
|
||||
|
@ -25,13 +25,69 @@
|
||||
"vcmi.server.errors.modsIncompatibility" : "Требуемые моды для загрузки игры:",
|
||||
"vcmi.server.confirmReconnect" : "Подключиться к предыдущей сессии?",
|
||||
|
||||
"vcmi.settingsMainWindow.generalTab.hover" : "Общее",
|
||||
"vcmi.settingsMainWindow.generalTab.help" : "Переключиться на вкладку \"Общее\", содержащее общие настройки клиента игры",
|
||||
"vcmi.settingsMainWindow.battleTab.hover" : "Бой",
|
||||
"vcmi.settingsMainWindow.battleTab.help" : "Переключиться на вкладку \"Бой\", содержащее настройки поведения клиента игры в ходе битв",
|
||||
"vcmi.settingsMainWindow.adventureTab.hover" : "Карта",
|
||||
"vcmi.settingsMainWindow.adventureTab.help" : "Переключиться на вкладку \"Карта\", содержащее настройки поведения клиента на карте - там, где перемещаются герои",
|
||||
|
||||
"vcmi.systemOptions.videoGroup" : "Видео",
|
||||
"vcmi.systemOptions.audioGroup" : "Аудио",
|
||||
"vcmi.systemOptions.otherGroup" : "Иное", // unused right now
|
||||
"vcmi.systemOptions.townsGroup" : "Экран города",
|
||||
|
||||
"vcmi.systemOptions.fullscreenButton.hover" : "Полный экран",
|
||||
"vcmi.systemOptions.fullscreenButton.help" : "{Полный экран}\n\n Если выбрано, то VCMI будет работать в полноэкранном режиме, если нет - в окне",
|
||||
"vcmi.systemOptions.resolutionButton.hover" : "Разрешение экрана",
|
||||
"vcmi.systemOptions.resolutionButton.hover" : "Разрешение %wx%h",
|
||||
"vcmi.systemOptions.resolutionButton.help" : "{Разрешение экрана}\n\n Изменение разрешения экрана. Для применения нового разрешения требуется перезапуск игры.",
|
||||
"vcmi.systemOptions.resolutionMenu.hover" : "Выбрать разрешения экрана",
|
||||
"vcmi.systemOptions.resolutionMenu.help" : "Изменение разрешения экрана в игре.",
|
||||
"vcmi.systemOptions.fullscreenFailed" : "{Полный экран}\n\n Невозможно переключиться в полноэкранный режим - выбранное разрешение не поддерживается дисплеем!",
|
||||
"vcmi.systemOptions.framerateButton.hover" : "Показывать частоту кадров",
|
||||
"vcmi.systemOptions.framerateButton.help" : "{Показывать частоту кадров}\n\n Включить счетчик частоты кадров в углу игрового клиента",
|
||||
|
||||
"vcmi.adventureOptions.infoBarPick.hover" : "Сообщения в информационной панели",
|
||||
"vcmi.adventureOptions.infoBarPick.help" : "{Сообщения в информационной панели}\n\n Если сообщения помещаются, то показывать их в информационной панели (только на интерфейсе карты).",
|
||||
"vcmi.adventureOptions.numericQuantities.hover" : "Приблизительное число существ",
|
||||
"vcmi.adventureOptions.numericQuantities.help" : "{Приблизительное число существ}\n\n Показывать приблизительное число существ в формате A-B вместо словесный обозначений",
|
||||
"vcmi.adventureOptions.forceMovementInfo.hover" : "Всегда показывать стоимость перемещения",
|
||||
"vcmi.adventureOptions.forceMovementInfo.help" : "{Всегда показывать стоимость перемещения}\n\n Заменить информацию в статусной строке на информацию о перемещении без необходимости нажатия {ALT}",
|
||||
"vcmi.adventureOptions.showGrid.hover" : "Сетка",
|
||||
"vcmi.adventureOptions.showGrid.help" : "{Сетка}\n\n Показывать сетку на видимой части карты.",
|
||||
"vcmi.adventureOptions.mapSwipe.hover" : "Перемещение карты жестами",
|
||||
"vcmi.adventureOptions.mapSwipe.help" : "{Перемещение карты жестами}\n\n Включает перемещение карты жестами на системах с сенсорным экраном. Сейчас также активируется левой кнопкой мыши.",
|
||||
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed1.help": "Очень медленная прокрутка карты.",
|
||||
"vcmi.adventureOptions.mapScrollSpeed5.help": "Очень быстрая прокрутка карты.",
|
||||
"vcmi.adventureOptions.mapScrollSpeed6.help": "Мгновенная прокрутка карты.",
|
||||
|
||||
"vcmi.battleOptions.queueSizeLabel.hover": "Показывать очередь хода существ",
|
||||
"vcmi.battleOptions.queueSizeNoneButton.hover": "ВЫКЛ",
|
||||
"vcmi.battleOptions.queueSizeAutoButton.hover": "АВТО",
|
||||
"vcmi.battleOptions.queueSizeSmallButton.hover": "МАЛ",
|
||||
"vcmi.battleOptions.queueSizeBigButton.hover": "БОЛ",
|
||||
"vcmi.battleOptions.queueSizeNoneButton.help": "Полностью выключает видимость очереди хода существ в битве",
|
||||
"vcmi.battleOptions.queueSizeAutoButton.help": "Размер очереди существ зависит от разрешения (малая при высоте экрана меньше 700 пикселей, иначе большая)",
|
||||
"vcmi.battleOptions.queueSizeSmallButton.help": "Уменьшенный размер очереди существ",
|
||||
"vcmi.battleOptions.queueSizeBigButton.help": "Увеличенный размер очереди существ (не поддерживается при разрешении менее 700 пикселей в высоту)",
|
||||
"vcmi.battleOptions.animationsSpeed1.hover": "",
|
||||
"vcmi.battleOptions.animationsSpeed5.hover": "",
|
||||
"vcmi.battleOptions.animationsSpeed6.hover": "",
|
||||
"vcmi.battleOptions.animationsSpeed1.help": "Очень медленная скорость анимации.",
|
||||
"vcmi.battleOptions.animationsSpeed5.help": "Очень быстрая скорость анимации.",
|
||||
"vcmi.battleOptions.animationsSpeed6.help": "Мгновенная скорость анимации.",
|
||||
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Пропускать вступительную музыку",
|
||||
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Пропускать вступительную музыку}\n\n Пропускать музыку, которая проигрывается в начале каждой битвы. Также может быть пропущена по нажатию {ESC}",
|
||||
|
||||
"vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover" : "Показывать доступных существ",
|
||||
"vcmi.otherOptions.availableCreaturesAsDwellingLabel.help" : "{Показывать доступных существ}\n\n Показывать число доступных существ вместо прироста на экране города (в левом нижнем углу).",
|
||||
"vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover" : "Показывать прирост существ",
|
||||
"vcmi.otherOptions.creatureGrowthAsDwellingLabel.help" : "{Показывать прирост существ}\n\n Показывать прирост существ вместо числа доступных существ на экране города (в левом нижнем углу).",
|
||||
"vcmi.otherOptions.compactTownCreatureInfo.hover": "Компактное окно информации о существах",
|
||||
"vcmi.otherOptions.compactTownCreatureInfo.help": "{Компактное окно информации о существах}\n\n Уменьшить окно информации о существах в информации о городе",
|
||||
|
||||
"vcmi.townHall.missingBase" : "Сначала необходимо построить: %s",
|
||||
"vcmi.townHall.noCreaturesToRecruit" : "Нет существ для найма!",
|
||||
@ -66,10 +122,24 @@
|
||||
"vcmi.questLog.hideComplete.hover" : "Скрыть завершенное",
|
||||
"vcmi.questLog.hideComplete.help" : "Скрыть все завершенные квесты",
|
||||
|
||||
"vcmi.randomMapTab.widgets.defaultTemplate" : "default",
|
||||
"vcmi.randomMapTab.widgets.templateLabel" : "Template",
|
||||
"vcmi.randomMapTab.widgets.teamAlignmentsButton" : "Setup...",
|
||||
"vcmi.randomMapTab.widgets.teamAlignmentsLabel" : "Team alignments",
|
||||
"vcmi.randomMapTab.widgets.defaultTemplate" : "(по умолчанию)",
|
||||
"vcmi.randomMapTab.widgets.templateLabel" : "Шаблон",
|
||||
"vcmi.randomMapTab.widgets.teamAlignmentsButton" : "Настройка...",
|
||||
"vcmi.randomMapTab.widgets.teamAlignmentsLabel" : "Распределение команд",
|
||||
"vcmi.randomMapTab.widgets.roadTypesLabel" : "Виды дорог",
|
||||
|
||||
"mapObject.core.creatureBank.cyclopsStockpile.name" : "Хранилище циклопов",
|
||||
"mapObject.core.creatureBank.dragonFlyHive.name" : "Улей летучих змиев",
|
||||
"mapObject.core.creatureBank.dwarvenTreasury.name" : "Сокровищница гномов",
|
||||
"mapObject.core.creatureBank.griffinConservatory.name" : "Консерватория грифонов",
|
||||
"mapObject.core.creatureBank.inpCache.name" : "Яма бесов",
|
||||
"mapObject.core.creatureBank.medusaStore.name" : "Склады медуз",
|
||||
"mapObject.core.creatureBank.nagaBank.name" : "Хранилище наг",
|
||||
"mapObject.core.crypt.crypt.name" : "Склеп",
|
||||
"mapObject.core.derelictShip.derelictShip.name" : "Заброшенный корабль",
|
||||
"mapObject.core.dragonUtopia.dragonUtopia.name" : "Утопия драконов",
|
||||
"mapObject.core.pyramid.pyramid.name" : "Пирамида",
|
||||
"mapObject.core.shipwreck.shipwreck.name" : "Кораблекрушение",
|
||||
|
||||
// few strings from WoG used by vcmi
|
||||
"vcmi.stackExperience.description" : "» О п ы т с у щ е с т в «\n\nТип существа ................... : %s\nРанг опыта ................. : %s (%i)\nОчки опыта ............... : %i\nДо следующего .. : %i\nМаксимум за битву ... : %i%% (%i)\nЧисло в отряде .... : %i\nМаксимум новичков\n без потери ранга .... : %i\nМножитель опыта ........... : %.2f\nМножитель улучшения .......... : %.2f\nОпыт после 10 ранга ........ : %i\nМаксимум новичков для сохранения\n ранга 10 при максимальном опыте : %i",
|
||||
|
@ -32,7 +32,6 @@
|
||||
"author" : "Команда VCMI",
|
||||
"modType" : "Графический",
|
||||
|
||||
"skipValidation" : true,
|
||||
"translations" : [
|
||||
"config/vcmi/russian.json"
|
||||
]
|
||||
|
@ -77,13 +77,6 @@ CSoundHandler::CSoundHandler():
|
||||
{
|
||||
listener(std::bind(&CSoundHandler::onVolumeChange, this, _1));
|
||||
|
||||
// Vectors for helper(s)
|
||||
pickupSounds =
|
||||
{
|
||||
soundBase::pickup01, soundBase::pickup02, soundBase::pickup03,
|
||||
soundBase::pickup04, soundBase::pickup05, soundBase::pickup06, soundBase::pickup07
|
||||
};
|
||||
|
||||
battleIntroSounds =
|
||||
{
|
||||
soundBase::battle00, soundBase::battle01,
|
||||
|
@ -78,7 +78,6 @@ public:
|
||||
void ambientStopAllChannels();
|
||||
|
||||
// Sets
|
||||
std::vector<soundBase::soundID> pickupSounds;
|
||||
std::vector<soundBase::soundID> battleIntroSounds;
|
||||
};
|
||||
|
||||
|
@ -324,6 +324,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
if (!hero)
|
||||
return;
|
||||
|
||||
adventureInt->infoBar->requestPopAll();
|
||||
if (details.result == TryMoveHero::EMBARK || details.result == TryMoveHero::DISEMBARK)
|
||||
{
|
||||
if (hero->getRemovalSound())
|
||||
@ -1031,18 +1032,23 @@ void CPlayerInterface::yourTacticPhase(int distance)
|
||||
boost::this_thread::sleep(boost::posix_time::millisec(1));
|
||||
}
|
||||
|
||||
void CPlayerInterface::showComp(const Component &comp, std::string message)
|
||||
void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &text, const std::vector<Component> & components, int soundID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
waitWhileDialog(); //Fix for mantis #98
|
||||
|
||||
CCS->soundh->playSoundFromSet(CCS->soundh->pickupSounds);
|
||||
adventureInt->infoBar->showComponent(comp, message);
|
||||
}
|
||||
bool autoTryHover = settings["gameTweaks"]["infoBarPick"].Bool() && type == EInfoWindowMode::AUTO;
|
||||
auto timer = type == EInfoWindowMode::INFO ? 3000 : 4500; //Implement long info windows like in HD mod
|
||||
|
||||
if(autoTryHover || type == EInfoWindowMode::INFO)
|
||||
{
|
||||
waitWhileDialog(); //Fix for mantis #98
|
||||
adventureInt->infoBar->pushComponents(components, text, timer);
|
||||
|
||||
if (makingTurn && GH.listInt.size() && LOCPLINT == this)
|
||||
CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
|
||||
return;
|
||||
}
|
||||
|
||||
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component> & components, int soundID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
if (settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())
|
||||
{
|
||||
return;
|
||||
@ -1093,7 +1099,7 @@ void CPlayerInterface::showInfoDialogAndWait(std::vector<Component> & components
|
||||
std::string str;
|
||||
text.toString(str);
|
||||
|
||||
showInfoDialog(str, components, 0);
|
||||
showInfoDialog(EInfoWindowMode::MODAL, str, components, 0);
|
||||
waitWhileDialog();
|
||||
}
|
||||
|
||||
@ -1715,7 +1721,7 @@ void CPlayerInterface::acceptTurn()
|
||||
auto playerColor = *cb->getPlayerID();
|
||||
|
||||
std::vector<Component> components;
|
||||
components.push_back(Component(Component::FLAG, playerColor.getNum(), 0, 0));
|
||||
components.emplace_back(Component::EComponentType::FLAG, playerColor.getNum(), 0, 0);
|
||||
MetaString text;
|
||||
|
||||
const auto & optDaysWithoutCastle = cb->getPlayerState(playerColor)->daysWithoutCastle;
|
||||
@ -1773,6 +1779,16 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance * h)
|
||||
|
||||
void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
|
||||
{
|
||||
bool isHero = dynamic_cast<const CGHeroInstance *>(specific) != nullptr;
|
||||
bool changedHero = dynamic_cast<const CGHeroInstance *>(specific) != adventureInt->curHero();
|
||||
bool isTown = dynamic_cast<const CGTownInstance *>(specific) != nullptr;
|
||||
|
||||
bool update = (isHero && changedHero) || (isTown);
|
||||
// If infobar is showing components and we request an update to hero
|
||||
// do not force infobar tick here, it will prevents us to show components just picked up
|
||||
if(adventureInt->infoBar->showingComponents() && !update)
|
||||
return;
|
||||
|
||||
adventureInt->infoBar->showSelection();
|
||||
}
|
||||
|
||||
@ -1883,14 +1899,16 @@ void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
|
||||
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->infoBar->showSelection();
|
||||
auto hero = boost::apply_visitor(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
askToAssembleArtifact(al);
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->infoBar->showSelection();
|
||||
auto hero = boost::apply_visitor(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
for(auto isa : GH.listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
@ -1904,7 +1922,8 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->infoBar->showSelection();
|
||||
auto hero = boost::apply_visitor(HeroObjectRetriever(), dst.artHolder);
|
||||
updateInfo(hero);
|
||||
|
||||
bool redraw = true;
|
||||
// If a bulk transfer has arrived, then redrawing only the last art movement.
|
||||
@ -1932,7 +1951,8 @@ void CPlayerInterface::bulkArtMovementStart(size_t numOfArts)
|
||||
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->infoBar->showSelection();
|
||||
auto hero = boost::apply_visitor(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
for(auto isa : GH.listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
@ -1944,7 +1964,8 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
||||
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->infoBar->showSelection();
|
||||
auto hero = boost::apply_visitor(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
for(auto isa : GH.listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
|
@ -168,7 +168,7 @@ public:
|
||||
void heroMovePointsChanged(const CGHeroInstance * hero) override;
|
||||
void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
|
||||
void receivedResource() override;
|
||||
void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
@ -201,7 +201,6 @@ public:
|
||||
void playerBlocked(int reason, bool start) override;
|
||||
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
|
||||
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
|
||||
void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox
|
||||
void saveGame(BinarySerializer & h, const int version) override; //saving
|
||||
void loadGame(BinaryDeserializer & h, const int version) override; //loading
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
||||
|
@ -217,7 +217,6 @@ public:
|
||||
void removeArtifact(const ArtifactLocation & al) override {};
|
||||
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;};
|
||||
|
||||
void showCompInfo(ShowInInfobox * comp) override {};
|
||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
|
||||
void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
|
||||
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
|
||||
|
@ -96,7 +96,6 @@ public:
|
||||
void visitYourTurn(YourTurn & pack) override;
|
||||
void visitSaveGameClient(SaveGameClient & pack) override;
|
||||
void visitPlayerMessageClient(PlayerMessageClient & pack) override;
|
||||
void visitShowInInfobox(ShowInInfobox & pack) override;
|
||||
void visitAdvmapSpellCast(AdvmapSpellCast & pack) override;
|
||||
void visitShowWorldViewEx(ShowWorldViewEx & pack) override;
|
||||
void visitOpenWindow(OpenWindow & pack) override;
|
||||
|
@ -592,7 +592,7 @@ void ApplyClientNetPackVisitor::visitInfoWindow(InfoWindow & pack)
|
||||
std::string str;
|
||||
pack.text.toString(str);
|
||||
|
||||
if(!callInterfaceIfPresent(cl, pack.player, &CGameInterface::showInfoDialog, str, pack.components,(soundBase::soundID)pack.soundID))
|
||||
if(!callInterfaceIfPresent(cl, pack.player, &CGameInterface::showInfoDialog, pack.type, str, pack.components,(soundBase::soundID)pack.soundID))
|
||||
logNetwork->warn("We received InfoWindow for not our player...");
|
||||
}
|
||||
|
||||
@ -855,11 +855,6 @@ void ApplyClientNetPackVisitor::visitPlayerMessageClient(PlayerMessageClient & p
|
||||
LOCPLINT->cingconsole->print(str.str());
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitShowInInfobox(ShowInInfobox & pack)
|
||||
{
|
||||
callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::showComp, pack.c, pack.text.toString());
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitAdvmapSpellCast(AdvmapSpellCast & pack)
|
||||
{
|
||||
cl.invalidatePaths();
|
||||
@ -880,28 +875,28 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
{
|
||||
switch(pack.window)
|
||||
{
|
||||
case OpenWindow::RECRUITMENT_FIRST:
|
||||
case OpenWindow::RECRUITMENT_ALL:
|
||||
case EOpenWindowMode::RECRUITMENT_FIRST:
|
||||
case EOpenWindowMode::RECRUITMENT_ALL:
|
||||
{
|
||||
const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl.getObj(ObjectInstanceID(pack.id1)));
|
||||
const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl.getObj(ObjectInstanceID(pack.id2)));
|
||||
callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, pack.window == OpenWindow::RECRUITMENT_FIRST ? 0 : -1);
|
||||
callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, pack.window == EOpenWindowMode::RECRUITMENT_FIRST ? 0 : -1);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::SHIPYARD_WINDOW:
|
||||
case EOpenWindowMode::SHIPYARD_WINDOW:
|
||||
{
|
||||
const IShipyard *sy = IShipyard::castFrom(cl.getObj(ObjectInstanceID(pack.id1)));
|
||||
callInterfaceIfPresent(cl, sy->o->tempOwner, &IGameEventsReceiver::showShipyardDialog, sy);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::THIEVES_GUILD:
|
||||
case EOpenWindowMode::THIEVES_GUILD:
|
||||
{
|
||||
//displays Thieves' Guild window (when hero enters Den of Thieves)
|
||||
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id2));
|
||||
callInterfaceIfPresent(cl, PlayerColor(pack.id1), &IGameEventsReceiver::showThievesGuildWindow, obj);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::UNIVERSITY_WINDOW:
|
||||
case EOpenWindowMode::UNIVERSITY_WINDOW:
|
||||
{
|
||||
//displays University window (when hero enters University on adventure map)
|
||||
const IMarket *market = IMarket::castFrom(cl.getObj(ObjectInstanceID(pack.id1)));
|
||||
@ -909,7 +904,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::MARKET_WINDOW:
|
||||
case EOpenWindowMode::MARKET_WINDOW:
|
||||
{
|
||||
//displays Thieves' Guild window (when hero enters Den of Thieves)
|
||||
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id1));
|
||||
@ -918,7 +913,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::HILL_FORT_WINDOW:
|
||||
case EOpenWindowMode::HILL_FORT_WINDOW:
|
||||
{
|
||||
//displays Hill fort window
|
||||
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id1));
|
||||
@ -926,12 +921,12 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showHillFortWindow, obj, hero);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::PUZZLE_MAP:
|
||||
case EOpenWindowMode::PUZZLE_MAP:
|
||||
{
|
||||
callInterfaceIfPresent(cl, PlayerColor(pack.id1), &IGameEventsReceiver::showPuzzleMap);
|
||||
}
|
||||
break;
|
||||
case OpenWindow::TAVERN_WINDOW:
|
||||
case EOpenWindowMode::TAVERN_WINDOW:
|
||||
const CGObjectInstance *obj1 = cl.getObj(ObjectInstanceID(pack.id1)),
|
||||
*obj2 = cl.getObj(ObjectInstanceID(pack.id2));
|
||||
callInterfaceIfPresent(cl, obj1->tempOwner, &IGameEventsReceiver::showTavernWindow, obj2);
|
||||
|
@ -86,7 +86,7 @@ CAdvMapInt::CAdvMapInt():
|
||||
statusbar(CGStatusBar::create(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG)),
|
||||
heroList(new CHeroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD)),
|
||||
townList(new CTownList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD)),
|
||||
infoBar(new CInfoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192))),
|
||||
infoBar(new CInfoBar(Point(ADVOPT.infoboxX, ADVOPT.infoboxY))),
|
||||
resdatabar(new CResDataBar),
|
||||
mapAudio(new MapAudioPlayer()),
|
||||
terrain(new MapView(Point(ADVOPT.advmapX, ADVOPT.advmapY), Point(ADVOPT.advmapW, ADVOPT.advmapH))),
|
||||
@ -869,6 +869,8 @@ boost::optional<Point> CAdvMapInt::keyToMoveDirection(const SDL_Keycode & key)
|
||||
void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
|
||||
{
|
||||
assert(sel);
|
||||
if(selection != sel)
|
||||
infoBar->popAll();
|
||||
selection = sel;
|
||||
mapAudio->onSelectionChanged(sel);
|
||||
if(centerView)
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
@ -29,7 +30,7 @@
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
CInfoBar::CVisibleInfo::CVisibleInfo()
|
||||
: CIntObject(0, Point(8, 12))
|
||||
: CIntObject(0, Point(offset_x, offset_y))
|
||||
{
|
||||
}
|
||||
|
||||
@ -163,16 +164,67 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
|
||||
}
|
||||
}
|
||||
|
||||
CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const Component & compToDisplay, std::string message)
|
||||
CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message, int textH, bool tiny)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
background = std::make_shared<CPicture>("ADSTATOT", 1, 0);
|
||||
auto fullRect = Rect(0, 0, data_width, data_height);
|
||||
auto textRect = fullRect;
|
||||
auto imageRect = fullRect;
|
||||
auto font = FONT_SMALL;
|
||||
auto maxComponents = 2;
|
||||
|
||||
comp = std::make_shared<CComponent>(compToDisplay);
|
||||
comp->moveTo(Point(pos.x+47, pos.y+50));
|
||||
if(!compsToDisplay.empty())
|
||||
{
|
||||
auto size = CComponent::large;
|
||||
if(compsToDisplay.size() > 2)
|
||||
{
|
||||
size = CComponent::medium;
|
||||
font = FONT_TINY;
|
||||
}
|
||||
if(!message.empty())
|
||||
{
|
||||
textRect = Rect(CInfoBar::offset,
|
||||
CInfoBar::offset,
|
||||
data_width - 2 * CInfoBar::offset,
|
||||
textH);
|
||||
imageRect = Rect(CInfoBar::offset,
|
||||
textH,
|
||||
data_width - 2 * CInfoBar::offset,
|
||||
CInfoBar::data_height - 2* CInfoBar::offset - textH);
|
||||
}
|
||||
|
||||
if(compsToDisplay.size() > 4) {
|
||||
maxComponents = 3;
|
||||
size = CComponent::small;
|
||||
}
|
||||
if(compsToDisplay.size() > 6)
|
||||
maxComponents = 4;
|
||||
|
||||
text = std::make_shared<CTextBox>(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
std::vector<std::shared_ptr<CComponent>> vect;
|
||||
|
||||
for(const auto & c : compsToDisplay)
|
||||
vect.emplace_back(std::make_shared<CComponent>(c, size, font));
|
||||
|
||||
comps = std::make_shared<CComponentBox>(vect, imageRect, 4, 4, 1, maxComponents);
|
||||
}
|
||||
else
|
||||
font = tiny ? FONT_TINY : font;
|
||||
|
||||
if(!message.empty())
|
||||
text = std::make_shared<CTextBox>(message, textRect, 0, font, ETextAlignment::CENTER, Colors::WHITE);
|
||||
}
|
||||
|
||||
int CInfoBar::getEstimatedComponentHeight(int numComps) const
|
||||
{
|
||||
if (numComps > 8) //Bigger than 8 components - return invalid value
|
||||
return std::numeric_limits<int>::max();
|
||||
else if (numComps > 2)
|
||||
return 160; // 32px * 1 row + 20 to offset
|
||||
else if (numComps)
|
||||
return 118; // 118 px to offset
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CInfoBar::playNewDaySound()
|
||||
@ -216,7 +268,7 @@ void CInfoBar::tick()
|
||||
{
|
||||
removeUsedEvents(TIME);
|
||||
if(GH.topInt() == adventureInt)
|
||||
showSelection();
|
||||
popComponents(true);
|
||||
}
|
||||
|
||||
void CInfoBar::clickLeft(tribool down, bool previousState)
|
||||
@ -228,7 +280,7 @@ void CInfoBar::clickLeft(tribool down, bool previousState)
|
||||
else if(state == GAME)
|
||||
showDate();
|
||||
else
|
||||
showSelection();
|
||||
popComponents(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,6 +308,10 @@ CInfoBar::CInfoBar(const Rect & position)
|
||||
reset();
|
||||
}
|
||||
|
||||
CInfoBar::CInfoBar(const Point & position): CInfoBar(Rect(position.x, position.y, width, height))
|
||||
{
|
||||
}
|
||||
|
||||
void CInfoBar::showDate()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
@ -266,13 +322,144 @@ void CInfoBar::showDate()
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showComponent(const Component & comp, std::string message)
|
||||
|
||||
void CInfoBar::pushComponents(const std::vector<Component> & components, std::string message, int timer)
|
||||
{
|
||||
auto actualPush = [&](const std::vector<Component> & components, std::string message, int timer, size_t max){
|
||||
std::vector<Component> vect = components; //I do not know currently how to avoid copy here
|
||||
while(!vect.empty())
|
||||
{
|
||||
std::vector<Component> sender = {vect.begin(), vect.begin() + std::min(vect.size(), max)};
|
||||
prepareComponents(sender, message, timer);
|
||||
vect.erase(vect.begin(), vect.begin() + std::min(vect.size(), max));
|
||||
};
|
||||
};
|
||||
if(shouldPopAll)
|
||||
popAll();
|
||||
if(components.empty())
|
||||
prepareComponents(components, message, timer);
|
||||
else
|
||||
{
|
||||
std::array<std::pair<std::vector<Component>, int>, 10> reward_map;
|
||||
for(const auto & c : components)
|
||||
{
|
||||
switch(c.id)
|
||||
{
|
||||
case Component::EComponentType::PRIM_SKILL:
|
||||
case Component::EComponentType::EXPERIENCE:
|
||||
reward_map.at(0).first.push_back(c);
|
||||
reward_map.at(0).second = 8; //At most 8, cannot be more
|
||||
break;
|
||||
case Component::EComponentType::SEC_SKILL:
|
||||
reward_map.at(1).first.push_back(c);
|
||||
reward_map.at(1).second = 4; //At most 4
|
||||
break;
|
||||
case Component::EComponentType::SPELL:
|
||||
reward_map.at(2).first.push_back(c);
|
||||
reward_map.at(2).second = 4; //At most 4
|
||||
break;
|
||||
case Component::EComponentType::ARTIFACT:
|
||||
reward_map.at(3).first.push_back(c);
|
||||
reward_map.at(3).second = 4; //At most 4, too long names
|
||||
break;
|
||||
case Component::EComponentType::CREATURE:
|
||||
reward_map.at(4).first.push_back(c);
|
||||
reward_map.at(4).second = 4; //At most 4, too long names
|
||||
break;
|
||||
case Component::EComponentType::RESOURCE:
|
||||
reward_map.at(5).first.push_back(c);
|
||||
reward_map.at(5).second = 7; //At most 7
|
||||
break;
|
||||
case Component::EComponentType::MORALE:
|
||||
case Component::EComponentType::LUCK:
|
||||
reward_map.at(6).first.push_back(c);
|
||||
reward_map.at(6).second = 2; //At most 2 - 1 for morale + 1 for luck
|
||||
break;
|
||||
case Component::EComponentType::BUILDING:
|
||||
reward_map.at(7).first.push_back(c);
|
||||
reward_map.at(7).second = 1; //At most 1 - only large icons available AFAIK
|
||||
break;
|
||||
case Component::EComponentType::HERO_PORTRAIT:
|
||||
reward_map.at(8).first.push_back(c);
|
||||
reward_map.at(8).second = 1; //I do not think than we even can get more than 1 hero
|
||||
break;
|
||||
case Component::EComponentType::FLAG:
|
||||
reward_map.at(9).first.push_back(c);
|
||||
reward_map.at(9).second = 1; //I do not think than we even can get more than 1 player in notification
|
||||
break;
|
||||
default:
|
||||
logGlobal->warn("Invalid component received!");
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto & kv : reward_map)
|
||||
if(!kv.first.empty())
|
||||
actualPush(kv.first, message, timer, kv.second);
|
||||
}
|
||||
popComponents();
|
||||
}
|
||||
|
||||
void CInfoBar::prepareComponents(const std::vector<Component> & components, std::string message, int timer)
|
||||
{
|
||||
auto imageH = getEstimatedComponentHeight(components.size()) + (components.empty() ? 0 : 2 * CInfoBar::offset);
|
||||
auto textH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL);
|
||||
auto tinyH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_TINY);
|
||||
auto header = CMessage::guessHeader(message);
|
||||
auto headerH = CMessage::guessHeight(header, CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL);
|
||||
auto headerTinyH = CMessage::guessHeight(header, CInfoBar::data_width - 2 * CInfoBar::offset, FONT_TINY);
|
||||
|
||||
// Order matters - priority form should be chosen first
|
||||
if(imageH + textH < CInfoBar::data_height)
|
||||
pushComponents(components, message, textH, false, timer);
|
||||
else if(!imageH && tinyH < CInfoBar::data_height)
|
||||
pushComponents(components, message, tinyH, true, timer);
|
||||
else if(imageH + headerH < CInfoBar::data_height)
|
||||
pushComponents(components, header, headerH, false, timer);
|
||||
else if(imageH + headerTinyH < CInfoBar::data_height - 2 * CInfoBar::offset)
|
||||
pushComponents(components, header, headerTinyH, true, timer);
|
||||
else
|
||||
pushComponents(components, "", 0, false, timer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void CInfoBar::requestPopAll()
|
||||
{
|
||||
shouldPopAll = true;
|
||||
}
|
||||
|
||||
void CInfoBar::popAll()
|
||||
{
|
||||
componentsQueue = {};
|
||||
shouldPopAll = false;
|
||||
}
|
||||
|
||||
void CInfoBar::popComponents(bool remove)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
state = COMPONENT;
|
||||
visibleInfo = std::make_shared<VisibleComponentInfo>(comp, message);
|
||||
setTimer(3000);
|
||||
redraw();
|
||||
if(remove && !componentsQueue.empty())
|
||||
componentsQueue.pop();
|
||||
if(!componentsQueue.empty())
|
||||
{
|
||||
state = COMPONENT;
|
||||
const auto & extracted = componentsQueue.front();
|
||||
visibleInfo = std::make_shared<VisibleComponentInfo>(extracted.first);
|
||||
setTimer(extracted.second);
|
||||
redraw();
|
||||
return;
|
||||
}
|
||||
showSelection();
|
||||
}
|
||||
|
||||
void CInfoBar::pushComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
componentsQueue.emplace(VisibleComponentInfo::Cache(comps, message, textH, tiny), timer);
|
||||
}
|
||||
|
||||
bool CInfoBar::showingComponents()
|
||||
{
|
||||
return state == COMPONENT;
|
||||
}
|
||||
|
||||
void CInfoBar::startEnemyTurn(PlayerColor color)
|
||||
|
@ -23,6 +23,7 @@ VCMI_LIB_NAMESPACE_END
|
||||
class CAnimImage;
|
||||
class CShowableAnim;
|
||||
class CComponent;
|
||||
class CComponentBox;
|
||||
class CHeroTooltip;
|
||||
class CTownTooltip;
|
||||
class CLabel;
|
||||
@ -31,10 +32,20 @@ class CTextBox;
|
||||
/// Info box which shows next week/day information, hold the current date
|
||||
class CInfoBar : public CIntObject
|
||||
{
|
||||
private:
|
||||
/// Infobar actually have a fixed size
|
||||
/// Declare before to compute correct size of widgets
|
||||
static constexpr int width = 192;
|
||||
static constexpr int height = 192;
|
||||
static constexpr int offset = 4;
|
||||
|
||||
//all visible information located in one object - for ease of replacing
|
||||
class CVisibleInfo : public CIntObject
|
||||
{
|
||||
public:
|
||||
static constexpr int offset_x = 8;
|
||||
static constexpr int offset_y = 12;
|
||||
|
||||
void show(SDL_Surface * to) override;
|
||||
|
||||
protected:
|
||||
@ -44,6 +55,9 @@ class CInfoBar : public CIntObject
|
||||
CVisibleInfo();
|
||||
};
|
||||
|
||||
static constexpr int data_width = width - 2 * CVisibleInfo::offset_x;
|
||||
static constexpr int data_height = height - 2 * CVisibleInfo::offset_y;
|
||||
|
||||
class EmptyVisibleInfo : public CVisibleInfo
|
||||
{
|
||||
public:
|
||||
@ -97,10 +111,24 @@ class CInfoBar : public CIntObject
|
||||
|
||||
class VisibleComponentInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CComponent> comp;
|
||||
std::shared_ptr<CComponentBox> comps;
|
||||
std::shared_ptr<CTextBox> text;
|
||||
public:
|
||||
VisibleComponentInfo(const Component & compToDisplay, std::string message);
|
||||
struct Cache
|
||||
{
|
||||
std::vector<Component> compsToDisplay;
|
||||
std::string message;
|
||||
int textH;
|
||||
bool tiny;
|
||||
Cache(std::vector<Component> comps, std::string msg, int textH, bool tiny):
|
||||
compsToDisplay(std::move(comps)),
|
||||
message(std::move(msg)),
|
||||
textH(textH),
|
||||
tiny(tiny)
|
||||
{}
|
||||
};
|
||||
VisibleComponentInfo(const Cache & c): VisibleComponentInfo(c.compsToDisplay, c.message, c.textH, c.tiny) {}
|
||||
VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message, int textH, bool tiny);
|
||||
};
|
||||
|
||||
enum EState
|
||||
@ -110,6 +138,15 @@ class CInfoBar : public CIntObject
|
||||
|
||||
std::shared_ptr<CVisibleInfo> visibleInfo;
|
||||
EState state;
|
||||
bool shouldPopAll = false;
|
||||
|
||||
std::queue<std::pair<VisibleComponentInfo::Cache, int>> componentsQueue;
|
||||
|
||||
//private helper for showing components
|
||||
void showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer);
|
||||
void pushComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer);
|
||||
void prepareComponents(const std::vector<Component> & comps, std::string message, int timer);
|
||||
void popComponents(bool remove = false);
|
||||
|
||||
//removes all information about current state, deactivates timer (if any)
|
||||
void reset();
|
||||
@ -123,12 +160,19 @@ class CInfoBar : public CIntObject
|
||||
void playNewDaySound();
|
||||
public:
|
||||
CInfoBar(const Rect & pos);
|
||||
CInfoBar(const Point & pos);
|
||||
|
||||
/// show new day/week animation
|
||||
void showDate();
|
||||
|
||||
/// show component for 3 seconds. Used to display picked up resources
|
||||
void showComponent(const Component & comp, std::string message);
|
||||
/// show components for 3 seconds. Used to display picked up resources. Can display up to 8 components
|
||||
void pushComponents(const std::vector<Component> & comps, std::string message, int timer = 3000);
|
||||
|
||||
/// Remove all queued components
|
||||
void popAll();
|
||||
|
||||
/// Request infobar to pop all after next InfoWindow arrives.
|
||||
void requestPopAll();
|
||||
|
||||
/// print enemy turn progress
|
||||
void startEnemyTurn(PlayerColor color);
|
||||
@ -142,5 +186,11 @@ public:
|
||||
|
||||
/// for 3 seconds shows amount of town halls and players status
|
||||
void showGameStatus();
|
||||
|
||||
/// check if infobar is showed something about pickups
|
||||
bool showingComponents();
|
||||
|
||||
/// get estimated component height for InfoBar
|
||||
int getEstimatedComponentHeight(int numComps) const;
|
||||
};
|
||||
|
||||
|
@ -33,22 +33,22 @@
|
||||
#include "../../lib/NetPacksBase.h"
|
||||
#include "../../lib/CArtHandler.h"
|
||||
|
||||
CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize)
|
||||
: perDay(false)
|
||||
CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize, EFonts font):
|
||||
perDay(false)
|
||||
{
|
||||
init(Type, Subtype, Val, imageSize);
|
||||
init(Type, Subtype, Val, imageSize, font);
|
||||
}
|
||||
|
||||
CComponent::CComponent(const Component & c, ESize imageSize)
|
||||
CComponent::CComponent(const Component & c, ESize imageSize, EFonts font)
|
||||
: perDay(false)
|
||||
{
|
||||
if(c.id == Component::RESOURCE && c.when==-1)
|
||||
if(c.id == Component::EComponentType::RESOURCE && c.when==-1)
|
||||
perDay = true;
|
||||
|
||||
init((Etype)c.id, c.subtype, c.val, imageSize);
|
||||
init((Etype)c.id, c.subtype, c.val, imageSize, font);
|
||||
}
|
||||
|
||||
void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize)
|
||||
void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize, EFonts fnt)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
@ -58,6 +58,7 @@ void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize)
|
||||
subtype = Subtype;
|
||||
val = Val;
|
||||
size = imageSize;
|
||||
font = fnt;
|
||||
|
||||
assert(compType < typeInvalid);
|
||||
assert(size < sizeInvalid);
|
||||
@ -67,13 +68,20 @@ void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize)
|
||||
pos.w = image->pos.w;
|
||||
pos.h = image->pos.h;
|
||||
|
||||
EFonts font = FONT_SMALL;
|
||||
if (imageSize < small)
|
||||
font = FONT_TINY; //other sizes?
|
||||
font = FONT_TINY; //for tiny images - tiny font
|
||||
|
||||
pos.h += 4; //distance between text and image
|
||||
|
||||
std::vector<std::string> textLines = CMessage::breakText(getSubtitle(), std::max<int>(80, pos.w), font);
|
||||
auto max = 80;
|
||||
if (size < large)
|
||||
max = 72;
|
||||
if (size < medium)
|
||||
max = 40;
|
||||
if (size < small)
|
||||
max = 30;
|
||||
|
||||
std::vector<std::string> textLines = CMessage::breakText(getSubtitle(), std::max<int>(max, pos.w), font);
|
||||
for(auto & line : textLines)
|
||||
{
|
||||
int height = static_cast<int>(graphics->fonts[font]->getLineHeight());
|
||||
@ -93,13 +101,13 @@ const std::vector<std::string> CComponent::getFileName()
|
||||
{
|
||||
static const std::string primSkillsArr [] = {"PSKIL32", "PSKIL32", "PSKIL42", "PSKILL"};
|
||||
static const std::string secSkillsArr [] = {"SECSK32", "SECSK32", "SECSKILL", "SECSK82"};
|
||||
static const std::string resourceArr [] = {"SMALRES", "RESOURCE", "RESOUR82", "RESOUR82"};
|
||||
static const std::string creatureArr [] = {"CPRSMALL", "CPRSMALL", "TWCRPORT", "TWCRPORT"};
|
||||
static const std::string resourceArr [] = {"SMALRES", "RESOURCE", "RESOURCE", "RESOUR82"};
|
||||
static const std::string creatureArr [] = {"CPRSMALL", "CPRSMALL", "CPRSMALL", "TWCRPORT"};
|
||||
static const std::string artifactArr[] = {"Artifact", "Artifact", "Artifact", "Artifact"};
|
||||
static const std::string spellsArr [] = {"SpellInt", "SpellInt", "SPELLSCR", "SPELLSCR"};
|
||||
static const std::string spellsArr [] = {"SpellInt", "SpellInt", "SpellInt", "SPELLSCR"};
|
||||
static const std::string moraleArr [] = {"IMRL22", "IMRL30", "IMRL42", "imrl82"};
|
||||
static const std::string luckArr [] = {"ILCK22", "ILCK30", "ILCK42", "ilck82"};
|
||||
static const std::string heroArr [] = {"PortraitsSmall", "PortraitsSmall", "PortraitsLarge", "PortraitsLarge"};
|
||||
static const std::string heroArr [] = {"PortraitsSmall", "PortraitsSmall", "PortraitsSmall", "PortraitsLarge"};
|
||||
static const std::string flagArr [] = {"CREST58", "CREST58", "CREST58", "CREST58"};
|
||||
|
||||
auto gen = [](const std::string * arr)
|
||||
@ -136,7 +144,7 @@ size_t CComponent::getIndex()
|
||||
case creature: return CGI->creatures()->getByIndex(subtype)->getIconIndex();
|
||||
case artifact: return CGI->artifacts()->getByIndex(subtype)->getIconIndex();
|
||||
case experience: return 4;
|
||||
case spell: return subtype;
|
||||
case spell: return (size < large) ? subtype + 1 : subtype;
|
||||
case morale: return val+3;
|
||||
case luck: return val+3;
|
||||
case building: return val;
|
||||
@ -336,9 +344,6 @@ Point CComponentBox::getOrTextPos(CComponent *left, CComponent *right)
|
||||
|
||||
int CComponentBox::getDistance(CComponent *left, CComponent *right)
|
||||
{
|
||||
static const int betweenImagesMin = 20;
|
||||
static const int betweenSubtitlesMin = 10;
|
||||
|
||||
int leftSubtitle = ( left->pos.w - left->image->pos.w) / 2;
|
||||
int rightSubtitle = (right->pos.w - right->image->pos.w) / 2;
|
||||
int subtitlesOffset = leftSubtitle + rightSubtitle;
|
||||
@ -348,8 +353,6 @@ int CComponentBox::getDistance(CComponent *left, CComponent *right)
|
||||
|
||||
void CComponentBox::placeComponents(bool selectable)
|
||||
{
|
||||
static const int betweenRows = 22;
|
||||
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
if (components.empty())
|
||||
return;
|
||||
@ -384,7 +387,7 @@ void CComponentBox::placeComponents(bool selectable)
|
||||
|
||||
//start next row
|
||||
if ((pos.w != 0 && rows.back().width + comp->pos.w + distance > pos.w) // row is full
|
||||
|| rows.back().comps >= 4) // no more than 4 comps per row
|
||||
|| rows.back().comps >= componentsInRow)
|
||||
{
|
||||
prevComp = nullptr;
|
||||
rows.push_back (RowData (0,0,0));
|
||||
@ -450,7 +453,16 @@ void CComponentBox::placeComponents(bool selectable)
|
||||
}
|
||||
|
||||
CComponentBox::CComponentBox(std::vector<std::shared_ptr<CComponent>> _components, Rect position):
|
||||
components(_components)
|
||||
CComponentBox(_components, position, defaultBetweenImagesMin, defaultBetweenSubtitlesMin, defaultBetweenRows, defaultComponentsInRow)
|
||||
{
|
||||
}
|
||||
|
||||
CComponentBox::CComponentBox(std::vector<std::shared_ptr<CComponent>> _components, Rect position, int betweenImagesMin, int betweenSubtitlesMin, int betweenRows, int componentsInRow):
|
||||
components(_components),
|
||||
betweenImagesMin(betweenImagesMin),
|
||||
betweenSubtitlesMin(betweenSubtitlesMin),
|
||||
betweenRows(betweenRows),
|
||||
componentsInRow(componentsInRow)
|
||||
{
|
||||
type |= REDRAW_PARENT;
|
||||
pos = position + pos.topLeft();
|
||||
@ -458,8 +470,17 @@ CComponentBox::CComponentBox(std::vector<std::shared_ptr<CComponent>> _component
|
||||
}
|
||||
|
||||
CComponentBox::CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> _components, Rect position, std::function<void(int newID)> _onSelect):
|
||||
CComponentBox(_components, position, _onSelect, defaultBetweenImagesMin, defaultBetweenSubtitlesMin, defaultBetweenRows, defaultComponentsInRow)
|
||||
{
|
||||
}
|
||||
|
||||
CComponentBox::CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> _components, Rect position, std::function<void(int newID)> _onSelect, int betweenImagesMin, int betweenSubtitlesMin, int betweenRows, int componentsInRow):
|
||||
components(_components.begin(), _components.end()),
|
||||
onSelect(_onSelect)
|
||||
onSelect(_onSelect),
|
||||
betweenImagesMin(betweenImagesMin),
|
||||
betweenSubtitlesMin(betweenSubtitlesMin),
|
||||
betweenRows(betweenRows),
|
||||
componentsInRow(componentsInRow)
|
||||
{
|
||||
type |= REDRAW_PARENT;
|
||||
pos = position + pos.topLeft();
|
||||
|
@ -47,13 +47,14 @@ private:
|
||||
void setSurface(std::string defName, int imgPos);
|
||||
std::string getSubtitleInternal();
|
||||
|
||||
void init(Etype Type, int Subtype, int Val, ESize imageSize);
|
||||
void init(Etype Type, int Subtype, int Val, ESize imageSize, EFonts font = FONT_SMALL);
|
||||
|
||||
public:
|
||||
std::shared_ptr<CAnimImage> image;
|
||||
|
||||
Etype compType; //component type
|
||||
ESize size; //component size.
|
||||
EFonts font; //Font size of label
|
||||
int subtype; //type-dependant subtype. See getSomething methods for details
|
||||
int val; // value \ strength \ amount of component. See getSomething methods for details
|
||||
bool perDay; // add "per day" text to subtitle
|
||||
@ -61,8 +62,8 @@ public:
|
||||
std::string getDescription();
|
||||
std::string getSubtitle();
|
||||
|
||||
CComponent(Etype Type, int Subtype, int Val = 0, ESize imageSize=large);
|
||||
CComponent(const Component &c, ESize imageSize=large);
|
||||
CComponent(Etype Type, int Subtype, int Val = 0, ESize imageSize=large, EFonts font = FONT_SMALL);
|
||||
CComponent(const Component &c, ESize imageSize=large, EFonts font = FONT_SMALL);
|
||||
|
||||
void clickRight(tribool down, bool previousState) override; //call-in
|
||||
};
|
||||
@ -94,6 +95,16 @@ class CComponentBox : public CIntObject
|
||||
std::shared_ptr<CSelectableComponent> selected;
|
||||
std::function<void(int newID)> onSelect;
|
||||
|
||||
static constexpr int defaultBetweenImagesMin = 20;
|
||||
static constexpr int defaultBetweenSubtitlesMin = 10;
|
||||
static constexpr int defaultBetweenRows = 22;
|
||||
static constexpr int defaultComponentsInRow = 4;
|
||||
|
||||
int betweenImagesMin;
|
||||
int betweenSubtitlesMin;
|
||||
int betweenRows;
|
||||
int componentsInRow;
|
||||
|
||||
void selectionChanged(std::shared_ptr<CSelectableComponent> newSelection);
|
||||
|
||||
//get position of "or" text between these comps
|
||||
@ -108,11 +119,13 @@ public:
|
||||
/// return index of selected item
|
||||
int selectedIndex();
|
||||
|
||||
/// constructor for non-selectable components
|
||||
/// constructors for non-selectable components
|
||||
CComponentBox(std::vector<std::shared_ptr<CComponent>> components, Rect position);
|
||||
CComponentBox(std::vector<std::shared_ptr<CComponent>> components, Rect position, int betweenImagesMin, int betweenSubtitlesMin, int betweenRows, int componentsInRow);
|
||||
|
||||
/// constructor for selectable components
|
||||
/// will also create "or" labels between components
|
||||
/// onSelect - optional function that will be called every time on selection change
|
||||
CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> components, Rect position, std::function<void(int newID)> onSelect = nullptr);
|
||||
CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> components, Rect position, std::function<void(int newID)> onSelect, int betweenImagesMin, int betweenSubtitlesMin, int betweenRows, int componentsInRow);
|
||||
};
|
||||
|
@ -270,7 +270,7 @@ void CArmyTooltip::init(const InfoAboutArmy &army)
|
||||
}
|
||||
}
|
||||
|
||||
subtitles.push_back(std::make_shared<CLabel>(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 41, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, subtitle));
|
||||
subtitles.push_back(std::make_shared<CLabel>(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 39, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, subtitle));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -202,6 +202,25 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineWi
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CMessage::guessHeader(const std::string & msg)
|
||||
{
|
||||
size_t begin = 0;
|
||||
std::string delimeters = "{}";
|
||||
size_t start = msg.find_first_of(delimeters[0], begin);
|
||||
size_t end = msg.find_first_of(delimeters[1], start);
|
||||
if(start > msg.size() || end > msg.size())
|
||||
return "";
|
||||
return msg.substr(begin, end);
|
||||
}
|
||||
|
||||
int CMessage::guessHeight(const std::string & txt, int width, EFonts font)
|
||||
{
|
||||
const auto f = graphics->fonts[font];
|
||||
auto lines = CMessage::breakText(txt, width, font);
|
||||
int lineHeight = static_cast<int>(f->getLineHeight());
|
||||
return lineHeight * (int)lines.size();
|
||||
}
|
||||
|
||||
void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player)
|
||||
{
|
||||
bool blitOr = false;
|
||||
|
@ -32,6 +32,12 @@ public:
|
||||
/// split text in lines
|
||||
static std::vector<std::string> breakText(std::string text, size_t maxLineWidth, EFonts font);
|
||||
|
||||
/// Try to guess a header of a message
|
||||
static std::string guessHeader(const std::string & msg);
|
||||
|
||||
/// For convenience
|
||||
static int guessHeight(const std::string & string, int width, EFonts fnt);
|
||||
|
||||
/// constructor
|
||||
static void init();
|
||||
/// destructor
|
||||
|
@ -105,11 +105,15 @@ AdventureOptionsTab::AdventureOptionsTab()
|
||||
addCallback("mapSwipeChanged", [](bool value)
|
||||
{
|
||||
#if defined(VCMI_MOBILE)
|
||||
setBoolSetting("general", "swipe", value);
|
||||
return setBoolSetting("general", "swipe", value);
|
||||
#else
|
||||
setBoolSetting("general", "swipeDesktop", value);
|
||||
return setBoolSetting("general", "swipeDesktop", value);
|
||||
#endif
|
||||
});
|
||||
addCallback("infoBarPickChanged", [](bool value)
|
||||
{
|
||||
return setBoolSetting("gameTweaks", "infoBarPick", value);
|
||||
});
|
||||
build(config);
|
||||
|
||||
std::shared_ptr<CToggleGroup> playerHeroSpeedToggle = widget<CToggleGroup>("heroMovementSpeedPicker");
|
||||
@ -142,4 +146,6 @@ AdventureOptionsTab::AdventureOptionsTab()
|
||||
#else
|
||||
mapSwipeCheckbox->setSelected(settings["general"]["swipeDesktop"].Bool());
|
||||
#endif
|
||||
std::shared_ptr<CToggleButton> infoBarPickCheckbox = widget<CToggleButton>("infoBarPickCheckbox");
|
||||
infoBarPickCheckbox->setSelected(settings["gameTweaks"]["infoBarPick"].Bool());
|
||||
}
|
||||
|
@ -125,7 +125,7 @@
|
||||
{ "heroLevel" : 4, "secondary" : { "diplomacy" : 3 } }
|
||||
]
|
||||
},
|
||||
"message" : 59,
|
||||
"message" : 66,
|
||||
"primary" : {
|
||||
"attack" : 2,
|
||||
"defence" : 2,
|
||||
|
@ -503,6 +503,7 @@
|
||||
"numericCreaturesQuantities",
|
||||
"availableCreaturesAsDwellingLabel",
|
||||
"compactTownCreatureInfo",
|
||||
"infoBarPick",
|
||||
"skipBattleIntroMusic"
|
||||
],
|
||||
"properties": {
|
||||
@ -526,6 +527,10 @@
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
},
|
||||
"infoBarPick" : {
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
},
|
||||
"skipBattleIntroMusic" : {
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
|
@ -364,6 +364,10 @@
|
||||
{
|
||||
"position": {"x": 45, "y": 385},
|
||||
"text": "vcmi.adventureOptions.mapSwipe.hover"
|
||||
},
|
||||
{
|
||||
"position": {"x": 45, "y": 415},
|
||||
"text": "vcmi.adventureOptions.infoBarPick.hover"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -399,6 +403,13 @@
|
||||
"position": {"x": 10, "y": 383},
|
||||
"callback": "mapSwipeChanged"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "infoBarPickCheckbox",
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "vcmi.adventureOptions.infoBarPick",
|
||||
"position": {"x": 10, "y": 413},
|
||||
"callback": "infoBarPickChanged"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ struct GiveBonus;
|
||||
struct BlockingDialog;
|
||||
struct TeleportDialog;
|
||||
struct MetaString;
|
||||
struct ShowInInfobox;
|
||||
struct StackLocation;
|
||||
struct ArtifactLocation;
|
||||
class CCreatureSet;
|
||||
@ -113,7 +112,6 @@ public:
|
||||
virtual void removeArtifact(const ArtifactLocation &al) = 0;
|
||||
virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
|
||||
|
||||
virtual void showCompInfo(ShowInInfobox * comp)=0;
|
||||
virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
||||
virtual void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
||||
virtual void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "NetPacksBase.h"
|
||||
#include "battle/BattleHex.h"
|
||||
#include "GameConstants.h"
|
||||
#include "int3.h"
|
||||
@ -103,7 +104,7 @@ public:
|
||||
virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement
|
||||
virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
|
||||
virtual void receivedResource(){};
|
||||
virtual void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID){};
|
||||
virtual void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID){};
|
||||
virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
|
||||
virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
|
||||
|
||||
@ -132,7 +133,6 @@ public:
|
||||
virtual void playerBlocked(int reason, bool start){}; //reason: 0 - upcoming battle
|
||||
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) {}; //player lost or won the game
|
||||
virtual void playerStartsTurn(PlayerColor player){};
|
||||
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox
|
||||
|
||||
//TODO shouldn't be moved down the tree?
|
||||
virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID){};
|
||||
|
@ -106,7 +106,6 @@ public:
|
||||
virtual void visitBattleSetStackProperty(BattleSetStackProperty & pack) {}
|
||||
virtual void visitBattleTriggerEffect(BattleTriggerEffect & pack) {}
|
||||
virtual void visitBattleUpdateGateState(BattleUpdateGateState & pack) {}
|
||||
virtual void visitShowInInfobox(ShowInInfobox & pack) {}
|
||||
virtual void visitAdvmapSpellCast(AdvmapSpellCast & pack) {}
|
||||
virtual void visitShowWorldViewEx(ShowWorldViewEx & pack) {}
|
||||
virtual void visitEndTurn(EndTurn & pack) {}
|
||||
|
@ -718,12 +718,7 @@ struct DLL_LINKAGE GiveHero : public CPackForClient
|
||||
|
||||
struct DLL_LINKAGE OpenWindow : public CPackForClient
|
||||
{
|
||||
enum EWindow
|
||||
{
|
||||
EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD,
|
||||
UNIVERSITY_WINDOW, HILL_FORT_WINDOW, MARKET_WINDOW, PUZZLE_MAP, TAVERN_WINDOW
|
||||
};
|
||||
ui8 window;
|
||||
EOpenWindowMode window;
|
||||
si32 id1 = -1;
|
||||
si32 id2 = -1;
|
||||
|
||||
@ -1150,6 +1145,7 @@ struct DLL_LINKAGE NewTurn : public CPackForClient
|
||||
|
||||
struct DLL_LINKAGE InfoWindow : public CPackForClient //103 - displays simple info window
|
||||
{
|
||||
EInfoWindowMode type = EInfoWindowMode::MODAL;
|
||||
MetaString text;
|
||||
std::vector<Component> components;
|
||||
PlayerColor player;
|
||||
@ -1159,6 +1155,7 @@ struct DLL_LINKAGE InfoWindow : public CPackForClient //103 - displays simple i
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & type;
|
||||
h & text;
|
||||
h & components;
|
||||
h & player;
|
||||
@ -1873,22 +1870,6 @@ protected:
|
||||
virtual void visitTyped(ICPackVisitor & visitor) override;
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE ShowInInfobox : public CPackForClient
|
||||
{
|
||||
PlayerColor player;
|
||||
Component c;
|
||||
MetaString text;
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & player;
|
||||
h & c;
|
||||
h & text;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitTyped(ICPackVisitor & visitor) override;
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE AdvmapSpellCast : public CPackForClient
|
||||
{
|
||||
ObjectInstanceID casterID;
|
||||
|
@ -35,6 +35,27 @@ struct ArtSlotInfo;
|
||||
|
||||
class ICPackVisitor;
|
||||
|
||||
enum class EInfoWindowMode : uint8_t
|
||||
{
|
||||
AUTO,
|
||||
MODAL,
|
||||
INFO
|
||||
};
|
||||
|
||||
enum class EOpenWindowMode : uint8_t
|
||||
{
|
||||
EXCHANGE_WINDOW,
|
||||
RECRUITMENT_FIRST,
|
||||
RECRUITMENT_ALL,
|
||||
SHIPYARD_WINDOW,
|
||||
THIEVES_GUILD,
|
||||
UNIVERSITY_WINDOW,
|
||||
HILL_FORT_WINDOW,
|
||||
MARKET_WINDOW,
|
||||
PUZZLE_MAP,
|
||||
TAVERN_WINDOW
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE CPack
|
||||
{
|
||||
std::shared_ptr<CConnection> c; // Pointer to connection that pack received from
|
||||
@ -176,8 +197,24 @@ public:
|
||||
|
||||
struct Component
|
||||
{
|
||||
enum EComponentType {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE, LUCK, BUILDING, HERO_PORTRAIT, FLAG};
|
||||
ui16 id = 0, subtype = 0; //id uses ^^^ enums, when id==EXPPERIENCE subtype==0 means exp points and subtype==1 levels)
|
||||
enum class EComponentType : uint8_t
|
||||
{
|
||||
PRIM_SKILL,
|
||||
SEC_SKILL,
|
||||
RESOURCE,
|
||||
CREATURE,
|
||||
ARTIFACT,
|
||||
EXPERIENCE,
|
||||
SPELL,
|
||||
MORALE,
|
||||
LUCK,
|
||||
BUILDING,
|
||||
HERO_PORTRAIT,
|
||||
FLAG,
|
||||
INVALID //should be last
|
||||
};
|
||||
EComponentType id = EComponentType::INVALID;
|
||||
ui16 subtype = 0; //id==EXPPERIENCE subtype==0 means exp points and subtype==1 levels
|
||||
si32 val = 0; // + give; - take
|
||||
si16 when = 0; // 0 - now; +x - within x days; -x - per x days
|
||||
|
||||
|
@ -492,11 +492,6 @@ void BattleUpdateGateState::visitTyped(ICPackVisitor & visitor)
|
||||
visitor.visitBattleUpdateGateState(*this);
|
||||
}
|
||||
|
||||
void ShowInInfobox::visitTyped(ICPackVisitor & visitor)
|
||||
{
|
||||
visitor.visitShowInInfobox(*this);
|
||||
}
|
||||
|
||||
void AdvmapSpellCast::visitTyped(ICPackVisitor & visitor)
|
||||
{
|
||||
visitor.visitAdvmapSpellCast(*this);
|
||||
@ -2503,7 +2498,7 @@ void YourTurn::applyGs(CGameState * gs) const
|
||||
}
|
||||
|
||||
Component::Component(const CStackBasicDescriptor & stack)
|
||||
: id(CREATURE)
|
||||
: id(EComponentType::CREATURE)
|
||||
, subtype(stack.type->idNumber)
|
||||
, val(stack.count)
|
||||
{
|
||||
|
@ -132,6 +132,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
{
|
||||
int textID = -1;
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = hero->getOwner();
|
||||
MetaString loot;
|
||||
|
||||
@ -189,7 +190,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
break;
|
||||
}
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
iw.components.emplace_back(Component::MORALE, 0, -1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::MORALE, 0, -1, 0);
|
||||
iw.soundID = soundBase::GRAVEYARD;
|
||||
break;
|
||||
}
|
||||
@ -200,7 +201,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
gb.id = hero->id.getNum();
|
||||
cb->giveHeroBonus(&gb);
|
||||
textID = 107;
|
||||
iw.components.emplace_back(Component::LUCK, 0, -2, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::LUCK, 0, -2, 0);
|
||||
break;
|
||||
}
|
||||
case Obj::CREATURE_BANK:
|
||||
@ -224,7 +225,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
{
|
||||
if (bc->resources[it] != 0)
|
||||
{
|
||||
iw.components.emplace_back(Component::RESOURCE, it, bc->resources[it], 0);
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE, it, bc->resources[it], 0);
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(iw.components.back().val);
|
||||
loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype);
|
||||
@ -234,7 +235,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
//grant artifacts
|
||||
for (auto & elem : bc->artifacts)
|
||||
{
|
||||
iw.components.emplace_back(Component::ARTIFACT, elem, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0);
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, elem);
|
||||
cb->giveHeroNewArtifact(hero, VLC->arth->objects[elem], ArtifactPosition::FIRST_AVAILABLE);
|
||||
@ -278,7 +279,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
if(hero->canLearnSpell(spell))
|
||||
{
|
||||
spells.insert(spellId);
|
||||
iw.components.emplace_back(Component::SPELL, spellId, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, spellId, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -36,23 +36,6 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
///helpers
|
||||
static void showInfoDialog(const PlayerColor & playerID, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
static int lowestSpeed(const CGHeroInstance * chi)
|
||||
{
|
||||
static const CSelector selectorSTACKS_SPEED = Selector::type()(Bonus::STACKS_SPEED);
|
||||
@ -462,7 +445,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
|
||||
txt_id = 103;
|
||||
}
|
||||
|
||||
showInfoDialog(h,txt_id);
|
||||
h->showInfoDialog(txt_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -876,6 +859,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
|
||||
void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedStack, CRandomGenerator & rand) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.soundID = soundBase::pickup01 + rand.nextInt(6);
|
||||
iw.player = tempOwner;
|
||||
iw.components.emplace_back(raisedStack);
|
||||
|
@ -22,16 +22,6 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
///helpers
|
||||
static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.window = type;
|
||||
ow.id1 = id1;
|
||||
ow.id2 = id2;
|
||||
IObjectInterface::cb->sendAndApply(&ow);
|
||||
}
|
||||
|
||||
bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
@ -205,7 +195,7 @@ std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
|
||||
|
||||
void CGMarket::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
openWindow(OpenWindow::MARKET_WINDOW,id.getNum(),h->id.getNum());
|
||||
openWindow(EOpenWindowMode::MARKET_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
||||
|
||||
int CGMarket::getMarketEfficiency() const
|
||||
@ -339,7 +329,7 @@ std::vector<int> CGUniversity::availableItemsIds(EMarketMode::EMarketMode mode)
|
||||
|
||||
void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
openWindow(OpenWindow::UNIVERSITY_WINDOW,id.getNum(),h->id.getNum());
|
||||
openWindow(EOpenWindowMode::UNIVERSITY_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -25,22 +25,6 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
///helpers
|
||||
static void showInfoDialog(const PlayerColor & playerID, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
void CGPandoraBox::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = (ID==Obj::PANDORAS_BOX); //block only if it's really pandora's box (events also derive from that class)
|
||||
@ -60,6 +44,7 @@ void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const
|
||||
afterSuccessfulVisit();
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->getOwner();
|
||||
|
||||
bool changesPrimSkill = false;
|
||||
@ -98,14 +83,14 @@ void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const
|
||||
iw.text.addReplacement(h->getNameTranslated());
|
||||
|
||||
if(expVal)
|
||||
iw.components.emplace_back(Component::EXPERIENCE, 0, static_cast<si32>(expVal), 0);
|
||||
iw.components.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(expVal), 0);
|
||||
|
||||
for(int i=0; i<primskills.size(); i++)
|
||||
if(primskills[i])
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, i, primskills[i], 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, i, primskills[i], 0);
|
||||
|
||||
for(const auto & abilityData : unpossessedAbilities)
|
||||
iw.components.emplace_back(Component::SEC_SKILL, abilityData.first, abilityData.second, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, abilityData.first, abilityData.second, 0);
|
||||
|
||||
cb->showInfoDialog(&iw);
|
||||
|
||||
@ -139,6 +124,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
|
||||
std::string msg = message; //in case box is removed in the meantime
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->getOwner();
|
||||
|
||||
//TODO: reuse this code for Scholar skill
|
||||
@ -158,7 +144,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
const auto * spell = (*i).toSpell(VLC->spells());
|
||||
if(h->canLearnSpell(spell))
|
||||
{
|
||||
iw.components.emplace_back(Component::SPELL, *i, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, *i, 0, 0);
|
||||
spellsToGive.insert(*i);
|
||||
}
|
||||
if(spellsToGive.size() == 8) //display up to 8 spells at once
|
||||
@ -186,7 +172,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
if(manaDiff)
|
||||
{
|
||||
getText(iw,hadGuardians,manaDiff,176,177,h);
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, 5, manaDiff, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, 5, manaDiff, 0);
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->setManaPoints(h->id, h->mana + manaDiff);
|
||||
}
|
||||
@ -194,7 +180,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
if(moraleDiff)
|
||||
{
|
||||
getText(iw,hadGuardians,moraleDiff,178,179,h);
|
||||
iw.components.emplace_back(Component::MORALE, 0, moraleDiff, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::MORALE, 0, moraleDiff, 0);
|
||||
cb->showInfoDialog(&iw);
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::MORALE,Bonus::OBJECT,moraleDiff,id.getNum(),"");
|
||||
@ -205,7 +191,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
if(luckDiff)
|
||||
{
|
||||
getText(iw,hadGuardians,luckDiff,180,181,h);
|
||||
iw.components.emplace_back(Component::LUCK, 0, luckDiff, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::LUCK, 0, luckDiff, 0);
|
||||
cb->showInfoDialog(&iw);
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,luckDiff,id.getNum(),"");
|
||||
@ -218,7 +204,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
for(int i=0; i<resources.size(); i++)
|
||||
{
|
||||
if(resources[i] < 0)
|
||||
iw.components.emplace_back(Component::RESOURCE, i, resources[i], 0);
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE, i, resources[i], 0);
|
||||
}
|
||||
if(!iw.components.empty())
|
||||
{
|
||||
@ -231,7 +217,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
for(int i=0; i<resources.size(); i++)
|
||||
{
|
||||
if(resources[i] > 0)
|
||||
iw.components.emplace_back(Component::RESOURCE, i, resources[i], 0);
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE, i, resources[i], 0);
|
||||
}
|
||||
if(!iw.components.empty())
|
||||
{
|
||||
@ -245,7 +231,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
iw.text.addReplacement(h->getNameTranslated());
|
||||
for(const auto & elem : artifacts)
|
||||
{
|
||||
iw.components.emplace_back(Component::ARTIFACT, elem, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0);
|
||||
if(iw.components.size() >= 14)
|
||||
{
|
||||
cb->showInfoDialog(&iw);
|
||||
@ -339,7 +325,7 @@ void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answe
|
||||
{
|
||||
if(stacksCount() > 0) //if pandora's box is protected by army
|
||||
{
|
||||
showInfoDialog(hero,16,0);
|
||||
hero->showInfoDialog(16, 0, EInfoWindowMode::MODAL);
|
||||
cb->startBattleI(hero, this); //grants things after battle
|
||||
}
|
||||
else if(message.empty() && resources.empty()
|
||||
@ -348,7 +334,7 @@ void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answe
|
||||
&& spells.empty() && creatures.stacksCount() > 0
|
||||
&& gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle
|
||||
{
|
||||
showInfoDialog(hero,15,0);
|
||||
hero->showInfoDialog(15);
|
||||
cb->removeObject(this);
|
||||
}
|
||||
else //if it gives something without battle
|
||||
|
@ -173,6 +173,7 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
|
||||
if(ID == Obj::REFUGEE_CAMP && !creatures[0].first) //Refugee Camp, no available cres
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 44); //{%s} \n\n The camp is deserted. Perhaps you should try next week.
|
||||
iw.text.addReplacement(MetaString::OBJ_NAMES, ID);
|
||||
@ -328,6 +329,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
|
||||
if(!slot.validSlot()) //no available slot
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text.addTxt(MetaString::GENERAL_TXT, 425);//The %s would join your hero, but there aren't enough provisions to support them.
|
||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid);
|
||||
@ -342,6 +344,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
|
||||
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text.addTxt(MetaString::GENERAL_TXT, 423); //%d %s join your army.
|
||||
iw.text.addReplacement(count);
|
||||
@ -355,6 +358,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
|
||||
else //there no creatures
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.text.addTxt(MetaString::GENERAL_TXT, 422); //There are no %s here to recruit.
|
||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid);
|
||||
iw.player = h->tempOwner;
|
||||
@ -379,8 +383,8 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
|
||||
ow.id1 = id.getNum();
|
||||
ow.id2 = h->id.getNum();
|
||||
ow.window = (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::REFUGEE_CAMP)
|
||||
? OpenWindow::RECRUITMENT_FIRST
|
||||
: OpenWindow::RECRUITMENT_ALL;
|
||||
? EOpenWindowMode::RECRUITMENT_FIRST
|
||||
: EOpenWindowMode::RECRUITMENT_ALL;
|
||||
cb->sendAndApply(&ow);
|
||||
}
|
||||
}
|
||||
@ -1731,31 +1735,31 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
|
||||
case BuildingSubID::KNOWLEDGE_VISITING_BONUS: //wall of knowledge
|
||||
what = PrimarySkill::KNOWLEDGE;
|
||||
val = 1;
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, 3, 1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, 3, 1, 0);
|
||||
break;
|
||||
|
||||
case BuildingSubID::SPELL_POWER_VISITING_BONUS: //order of fire
|
||||
what = PrimarySkill::SPELL_POWER;
|
||||
val = 1;
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, 2, 1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, 2, 1, 0);
|
||||
break;
|
||||
|
||||
case BuildingSubID::ATTACK_VISITING_BONUS: //hall of Valhalla
|
||||
what = PrimarySkill::ATTACK;
|
||||
val = 1;
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, 0, 1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, 0, 1, 0);
|
||||
break;
|
||||
|
||||
case BuildingSubID::EXPERIENCE_VISITING_BONUS: //academy of battle scholars
|
||||
what = PrimarySkill::EXPERIENCE;
|
||||
val = static_cast<int>(h->calculateXp(1000));
|
||||
iw.components.emplace_back(Component::EXPERIENCE, 0, val, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::EXPERIENCE, 0, val, 0);
|
||||
break;
|
||||
|
||||
case BuildingSubID::DEFENSE_VISITING_BONUS: //cage of warlords
|
||||
what = PrimarySkill::DEFENSE;
|
||||
val = 1;
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, 1, 1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, 1, 1, 0);
|
||||
break;
|
||||
|
||||
case BuildingSubID::CUSTOM_VISITING_BONUS:
|
||||
|
@ -32,7 +32,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
IGameCallback * IObjectInterface::cb = nullptr;
|
||||
|
||||
///helpers
|
||||
static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
|
||||
void IObjectInterface::openWindow(const EOpenWindowMode type, const int id1, const int id2)
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.window = type;
|
||||
@ -41,27 +41,16 @@ static void openWindow(const OpenWindow::EWindow type, const int id1, const int
|
||||
IObjectInterface::cb->sendAndApply(&ow);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const PlayerColor & playerID, const ui32 txtID, const ui16 soundID)
|
||||
void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.player = getOwner();
|
||||
iw.type = mode;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
/*static void showInfoDialog(const ObjectInstanceID heroID, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
const PlayerColor playerID = IObjectInterface::cb->getOwner(heroID);
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}*/
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
///IObjectInterface
|
||||
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
|
||||
{}
|
||||
@ -340,18 +329,18 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
case Obj::HILL_FORT:
|
||||
{
|
||||
openWindow(OpenWindow::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
|
||||
openWindow(EOpenWindowMode::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
||||
break;
|
||||
case Obj::SANCTUARY:
|
||||
{
|
||||
//You enter the sanctuary and immediately feel as if a great weight has been lifted off your shoulders. You feel safe here.
|
||||
showInfoDialog(h, 114);
|
||||
h->showInfoDialog(114);
|
||||
}
|
||||
break;
|
||||
case Obj::TAVERN:
|
||||
{
|
||||
openWindow(OpenWindow::TAVERN_WINDOW,h->id.getNum(),id.getNum());
|
||||
openWindow(EOpenWindowMode::TAVERN_WINDOW,h->id.getNum(),id.getNum());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "../int3.h"
|
||||
#include "../HeroBonus.h"
|
||||
#include "../NetPacksBase.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -57,7 +58,13 @@ public:
|
||||
virtual void garrisonDialogClosed(const CGHeroInstance *hero) const;
|
||||
virtual void heroLevelUpDone(const CGHeroInstance *hero) const;
|
||||
|
||||
//unified interface, AI helpers
|
||||
//unified helper to show info dialog for object owner
|
||||
virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
|
||||
|
||||
//unified helper to show a specific window
|
||||
static void openWindow(const EOpenWindowMode type, const int id1, const int id2 = -1);
|
||||
|
||||
//unified interface, AI helpers
|
||||
virtual bool wasVisited (PlayerColor player) const;
|
||||
virtual bool wasVisited (const CGHeroInstance * h) const;
|
||||
|
||||
|
@ -50,22 +50,6 @@ CQuest::CQuest():
|
||||
{
|
||||
}
|
||||
|
||||
///helpers
|
||||
static void showInfoDialog(const PlayerColor & playerID, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
static std::string visitedTxt(const bool visited)
|
||||
{
|
||||
int id = visited ? 352 : 353;
|
||||
@ -204,7 +188,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
|
||||
switch (missionType)
|
||||
{
|
||||
case MISSION_LEVEL:
|
||||
components.emplace_back(Component::EXPERIENCE, 0, m13489val, 0);
|
||||
components.emplace_back(Component::EComponentType::EXPERIENCE, 0, m13489val, 0);
|
||||
if(!isCustom)
|
||||
iwText.addReplacement(m13489val);
|
||||
break;
|
||||
@ -215,7 +199,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
|
||||
{
|
||||
if(m2stats[i])
|
||||
{
|
||||
components.emplace_back(Component::PRIM_SKILL, i, m2stats[i], 0);
|
||||
components.emplace_back(Component::EComponentType::PRIM_SKILL, i, m2stats[i], 0);
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
@ -226,13 +210,13 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
components.emplace_back(Component::HERO_PORTRAIT, heroPortrait, 0, 0);
|
||||
components.emplace_back(Component::EComponentType::HERO_PORTRAIT, heroPortrait, 0, 0);
|
||||
if(!isCustom)
|
||||
addReplacements(iwText, text);
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
//FIXME: portrait may not match hero, if custom portrait was set in map editor
|
||||
components.emplace_back(Component::HERO_PORTRAIT, VLC->heroh->objects[m13489val]->imageIndex, 0, 0);
|
||||
components.emplace_back(Component::EComponentType::HERO_PORTRAIT, VLC->heroh->objects[m13489val]->imageIndex, 0, 0);
|
||||
if(!isCustom)
|
||||
iwText.addReplacement(VLC->heroh->objects[m13489val]->getNameTranslated());
|
||||
break;
|
||||
@ -250,7 +234,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
|
||||
MetaString loot;
|
||||
for(const auto & elem : m5arts)
|
||||
{
|
||||
components.emplace_back(Component::ARTIFACT, elem, 0, 0);
|
||||
components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0);
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, elem);
|
||||
}
|
||||
@ -278,7 +262,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
|
||||
{
|
||||
if(m7resources[i])
|
||||
{
|
||||
components.emplace_back(Component::RESOURCE, i, m7resources[i], 0);
|
||||
components.emplace_back(Component::EComponentType::RESOURCE, i, m7resources[i], 0);
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m7resources[i]);
|
||||
loot.addReplacement(MetaString::RES_NAMES, i);
|
||||
@ -289,7 +273,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
|
||||
}
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
components.emplace_back(Component::FLAG, m13489val, 0, 0);
|
||||
components.emplace_back(Component::EComponentType::FLAG, m13489val, 0, 0);
|
||||
if(!isCustom)
|
||||
iwText.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
break;
|
||||
@ -662,34 +646,34 @@ void CGSeerHut::getCompletionText(MetaString &text, std::vector<Component> &comp
|
||||
switch(rewardType)
|
||||
{
|
||||
case EXPERIENCE:
|
||||
components.emplace_back(Component::EXPERIENCE, 0, static_cast<si32>(h->calculateXp(rVal)), 0);
|
||||
components.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(h->calculateXp(rVal)), 0);
|
||||
break;
|
||||
case MANA_POINTS:
|
||||
components.emplace_back(Component::PRIM_SKILL, 5, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::PRIM_SKILL, 5, rVal, 0);
|
||||
break;
|
||||
case MORALE_BONUS:
|
||||
components.emplace_back(Component::MORALE, 0, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::MORALE, 0, rVal, 0);
|
||||
break;
|
||||
case LUCK_BONUS:
|
||||
components.emplace_back(Component::LUCK, 0, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::LUCK, 0, rVal, 0);
|
||||
break;
|
||||
case RESOURCES:
|
||||
components.emplace_back(Component::RESOURCE, rID, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::RESOURCE, rID, rVal, 0);
|
||||
break;
|
||||
case PRIMARY_SKILL:
|
||||
components.emplace_back(Component::PRIM_SKILL, rID, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::PRIM_SKILL, rID, rVal, 0);
|
||||
break;
|
||||
case SECONDARY_SKILL:
|
||||
components.emplace_back(Component::SEC_SKILL, rID, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::SEC_SKILL, rID, rVal, 0);
|
||||
break;
|
||||
case ARTIFACT:
|
||||
components.emplace_back(Component::ARTIFACT, rID, 0, 0);
|
||||
components.emplace_back(Component::EComponentType::ARTIFACT, rID, 0, 0);
|
||||
break;
|
||||
case SPELL:
|
||||
components.emplace_back(Component::SPELL, rID, 0, 0);
|
||||
components.emplace_back(Component::EComponentType::SPELL, rID, 0, 0);
|
||||
break;
|
||||
case CREATURE:
|
||||
components.emplace_back(Component::CREATURE, rID, rVal, 0);
|
||||
components.emplace_back(Component::EComponentType::CREATURE, rID, rVal, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1146,7 +1130,7 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
else
|
||||
txt_id=20;
|
||||
showInfoDialog(h, txt_id);
|
||||
h->showInfoDialog(txt_id);
|
||||
}
|
||||
|
||||
void CGBorderGuard::initObj(CRandomGenerator & rand)
|
||||
@ -1182,7 +1166,7 @@ void CGBorderGuard::onHeroVisit(const CGHeroInstance * h) const
|
||||
}
|
||||
else
|
||||
{
|
||||
showInfoDialog(h, 18);
|
||||
h->showInfoDialog(18);
|
||||
|
||||
AddQuest aq;
|
||||
aq.quest = QuestInfo (quest, this, visitablePos());
|
||||
@ -1207,7 +1191,7 @@ void CGBorderGate::onHeroVisit(const CGHeroInstance * h) const //TODO: passabili
|
||||
{
|
||||
if (!wasMyColorVisited (h->getOwner()) )
|
||||
{
|
||||
showInfoDialog(h,18,0);
|
||||
h->showInfoDialog(18);
|
||||
|
||||
AddQuest aq;
|
||||
aq.quest = QuestInfo (quest, this, visitablePos());
|
||||
|
@ -116,9 +116,9 @@ void CRandomRewardObjectInfo::configureReward(CRewardableObject * object, CRando
|
||||
bonus.sid = object->ID;
|
||||
//TODO: bonus.description = object->getObjectName();
|
||||
if (bonus.type == Bonus::MORALE)
|
||||
reward.extraComponents.emplace_back(Component::MORALE, 0, bonus.val, 0);
|
||||
reward.extraComponents.emplace_back(Component::EComponentType::MORALE, 0, bonus.val, 0);
|
||||
if (bonus.type == Bonus::LUCK)
|
||||
reward.extraComponents.emplace_back(Component::LUCK, 0, bonus.val, 0);
|
||||
reward.extraComponents.emplace_back(Component::EComponentType::LUCK, 0, bonus.val, 0);
|
||||
}
|
||||
|
||||
reward.primary = JsonRandom::loadPrimary(source["primary"], rng);
|
||||
@ -137,7 +137,7 @@ void CRandomRewardObjectInfo::configureReward(CRewardableObject * object, CRando
|
||||
CreatureID from (VLC->modh->identifiers.getIdentifier (node.second.meta, "creature", node.first) .get());
|
||||
CreatureID dest (VLC->modh->identifiers.getIdentifier (node.second.meta, "creature", node.second.String()).get());
|
||||
|
||||
reward.extraComponents.emplace_back(Component::CREATURE, dest.getNum(), 0, 0);
|
||||
reward.extraComponents.emplace_back(Component::EComponentType::CREATURE, dest.getNum(), 0, 0);
|
||||
|
||||
reward.creaturesChange[from] = dest;
|
||||
}
|
||||
@ -230,6 +230,11 @@ void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRando
|
||||
configureResetInfo(object, rng, object->resetParameters, parameters["resetParameters"]);
|
||||
|
||||
object->canRefuse = parameters["canRefuse"].Bool();
|
||||
|
||||
if(parameters["showInInfobox"].isNull())
|
||||
object->infoWindowType = EInfoWindowMode::AUTO;
|
||||
else
|
||||
object->infoWindowType = parameters["showInInfobox"].Bool() ? EInfoWindowMode::INFO : EInfoWindowMode::MODAL;
|
||||
|
||||
auto visitMode = parameters["visitMode"].String();
|
||||
for(int i = 0; i < Rewardable::VisitModeString.size(); ++i)
|
||||
|
@ -134,13 +134,14 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
||||
{
|
||||
auto vi = info[index];
|
||||
logGlobal->debug("Granting reward %d. Message says: %s", index, vi.message.toString());
|
||||
// show message only if it is not empty
|
||||
if (!vi.message.toString().empty())
|
||||
// show message only if it is not empty or in infobox
|
||||
if (infoWindowType != EInfoWindowMode::MODAL || !vi.message.toString().empty())
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text = vi.message;
|
||||
vi.reward.loadComponents(iw.components, h);
|
||||
iw.type = infoWindowType;
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
// grant reward afterwards. Note that it may remove object
|
||||
@ -297,19 +298,7 @@ void CRewardableObject::grantRewardBeforeLevelup(const CRewardVisitInfo & info,
|
||||
void CRewardableObject::grantRewardAfterLevelup(const CRewardVisitInfo & info, const CGHeroInstance * hero) const
|
||||
{
|
||||
if(info.reward.manaDiff || info.reward.manaPercentage >= 0)
|
||||
{
|
||||
si32 manaScaled = hero->mana;
|
||||
if (info.reward.manaPercentage >= 0)
|
||||
manaScaled = hero->manaLimit() * info.reward.manaPercentage / 100;
|
||||
|
||||
si32 manaMissing = std::max(0, hero->manaLimit() - manaScaled);
|
||||
si32 manaGranted = std::min(manaMissing, info.reward.manaDiff);
|
||||
si32 manaOverflow = info.reward.manaDiff - manaGranted;
|
||||
si32 manaOverLimit = manaOverflow * info.reward.manaOverflowFactor / 100;
|
||||
si32 manaOutput = manaScaled + manaGranted + manaOverLimit;
|
||||
|
||||
cb->setManaPoints(hero->id, manaOutput);
|
||||
}
|
||||
cb->setManaPoints(hero->id, info.reward.calculateManaPoints(hero));
|
||||
|
||||
if(info.reward.movePoints || info.reward.movePercentage >= 0)
|
||||
{
|
||||
@ -442,39 +431,54 @@ void CRewardInfo::loadComponents(std::vector<Component> & comps,
|
||||
|
||||
if (heroExperience)
|
||||
{
|
||||
comps.emplace_back(Component::EXPERIENCE, 0, static_cast<si32>(h->calculateXp(heroExperience)), 0);
|
||||
comps.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(h->calculateXp(heroExperience)), 0);
|
||||
}
|
||||
if (heroLevel)
|
||||
comps.emplace_back(Component::EXPERIENCE, 1, heroLevel, 0);
|
||||
comps.emplace_back(Component::EComponentType::EXPERIENCE, 1, heroLevel, 0);
|
||||
|
||||
if (manaDiff || manaPercentage >= 0)
|
||||
comps.emplace_back(Component::PRIM_SKILL, 5, manaDiff, 0);
|
||||
comps.emplace_back(Component::EComponentType::PRIM_SKILL, 5, calculateManaPoints(h) - h->mana, 0);
|
||||
|
||||
for (size_t i=0; i<primary.size(); i++)
|
||||
{
|
||||
if (primary[i] != 0)
|
||||
comps.emplace_back(Component::PRIM_SKILL, static_cast<ui16>(i), primary[i], 0);
|
||||
comps.emplace_back(Component::EComponentType::PRIM_SKILL, static_cast<ui16>(i), primary[i], 0);
|
||||
}
|
||||
|
||||
for(const auto & entry : secondary)
|
||||
comps.emplace_back(Component::SEC_SKILL, entry.first, entry.second, 0);
|
||||
comps.emplace_back(Component::EComponentType::SEC_SKILL, entry.first, entry.second, 0);
|
||||
|
||||
for(const auto & entry : artifacts)
|
||||
comps.emplace_back(Component::ARTIFACT, entry, 1, 0);
|
||||
comps.emplace_back(Component::EComponentType::ARTIFACT, entry, 1, 0);
|
||||
|
||||
for(const auto & entry : spells)
|
||||
comps.emplace_back(Component::SPELL, entry, 1, 0);
|
||||
comps.emplace_back(Component::EComponentType::SPELL, entry, 1, 0);
|
||||
|
||||
for(const auto & entry : creatures)
|
||||
comps.emplace_back(Component::CREATURE, entry.type->idNumber, entry.count, 0);
|
||||
comps.emplace_back(Component::EComponentType::CREATURE, entry.type->idNumber, entry.count, 0);
|
||||
|
||||
for (size_t i=0; i<resources.size(); i++)
|
||||
{
|
||||
if (resources[i] !=0)
|
||||
comps.emplace_back(Component::RESOURCE, static_cast<ui16>(i), resources[i], 0);
|
||||
comps.emplace_back(Component::EComponentType::RESOURCE, static_cast<ui16>(i), resources[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
si32 CRewardInfo::calculateManaPoints(const CGHeroInstance * hero) const
|
||||
{
|
||||
si32 manaScaled = hero->mana;
|
||||
if (manaPercentage >= 0)
|
||||
manaScaled = hero->manaLimit() * manaPercentage / 100;
|
||||
|
||||
si32 manaMissing = std::max(0, hero->manaLimit() - manaScaled);
|
||||
si32 manaGranted = std::min(manaMissing, manaDiff);
|
||||
si32 manaOverflow = manaDiff - manaGranted;
|
||||
si32 manaOverLimit = manaOverflow * manaOverflowFactor / 100;
|
||||
si32 manaOutput = manaScaled + manaGranted + manaOverLimit;
|
||||
|
||||
return manaOutput;
|
||||
}
|
||||
|
||||
Component CRewardInfo::getDisplayedComponent(const CGHeroInstance * h) const
|
||||
{
|
||||
std::vector<Component> comps;
|
||||
|
@ -178,6 +178,8 @@ public:
|
||||
const CGHeroInstance * h) const;
|
||||
Component getDisplayedComponent(const CGHeroInstance * h) const;
|
||||
|
||||
si32 calculateManaPoints(const CGHeroInstance * h) const;
|
||||
|
||||
CRewardInfo() :
|
||||
heroExperience(0),
|
||||
heroLevel(0),
|
||||
@ -304,6 +306,9 @@ protected:
|
||||
/// if true - player can refuse visiting an object (e.g. Tomb)
|
||||
bool canRefuse;
|
||||
|
||||
/// if true - object info will shown in infobox (like resource pickup)
|
||||
EInfoWindowMode infoWindowType = EInfoWindowMode::AUTO;
|
||||
|
||||
/// return true if this object was "cleared" before and no longer has rewards applicable to selected hero
|
||||
/// unlike wasVisited, this method uses information not available to player owner, for example, if object was cleared by another player before
|
||||
bool wasVisitedBefore(const CGHeroInstance * contextHero) const;
|
||||
@ -349,6 +354,8 @@ public:
|
||||
h & selectMode;
|
||||
h & selectedReward;
|
||||
h & onceVisitableObjectCleared;
|
||||
if (version >= 817)
|
||||
h & infoWindowType;
|
||||
}
|
||||
|
||||
// for configuration/object setup
|
||||
|
@ -34,31 +34,6 @@ ui8 CGObelisk::obeliskCount = 0; //how many obelisks are on map
|
||||
std::map<TeamID, ui8> CGObelisk::visited; //map: team_id => how many obelisks has been visited
|
||||
|
||||
///helpers
|
||||
static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.window = type;
|
||||
ow.id1 = id1;
|
||||
ow.id2 = id2;
|
||||
IObjectInterface::cb->sendAndApply(&ow);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const PlayerColor & playerID, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
InfoWindow iw;
|
||||
if(soundID)
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID = 0)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
static std::string visitedTxt(const bool visited)
|
||||
{
|
||||
int id = visited ? 352 : 353;
|
||||
@ -385,7 +360,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
|
||||
}
|
||||
else //they fight
|
||||
{
|
||||
showInfoDialog(h,87,0);//Insulted by your refusal of their offer, the monsters attack!
|
||||
h->showInfoDialog(87, 0, EInfoWindowMode::MODAL);//Insulted by your refusal of their offer, the monsters attack!
|
||||
fight(h);
|
||||
}
|
||||
}
|
||||
@ -587,18 +562,19 @@ void CGCreature::giveReward(const CGHeroInstance * h) const
|
||||
for(int i = 0; i < resources.size(); i++)
|
||||
{
|
||||
if(resources[i] > 0)
|
||||
iw.components.emplace_back(Component::RESOURCE, i, resources[i], 0);
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE, i, resources[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(gainedArtifact != ArtifactID::NONE)
|
||||
{
|
||||
cb->giveHeroNewArtifact(h, VLC->arth->objects[gainedArtifact], ArtifactPosition::FIRST_AVAILABLE);
|
||||
iw.components.emplace_back(Component::ARTIFACT, gainedArtifact, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::ARTIFACT, gainedArtifact, 0, 0);
|
||||
}
|
||||
|
||||
if(!iw.components.empty())
|
||||
{
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 183); // % has found treasure
|
||||
iw.text.addReplacement(h->getNameTranslated());
|
||||
cb->showInfoDialog(&iw);
|
||||
@ -740,10 +716,11 @@ void CGMine::flagMine(const PlayerColor & player) const
|
||||
cb->setOwner(this, player); //not ours? flag it!
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.soundID = soundBase::FLAGMINE;
|
||||
iw.text.addTxt(MetaString::MINE_EVNTS,producedResource); //not use subID, abandoned mines uses default mine texts
|
||||
iw.player = player;
|
||||
iw.components.emplace_back(Component::RESOURCE, producedResource, producedQuantity, -1);
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE, producedResource, producedQuantity, -1);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
@ -767,7 +744,7 @@ void CGMine::battleFinished(const CGHeroInstance *hero, const BattleResult &resu
|
||||
{
|
||||
if(isAbandoned())
|
||||
{
|
||||
showInfoDialog(hero->tempOwner, 85, 0);
|
||||
hero->showInfoDialog(85);
|
||||
}
|
||||
flagMine(hero->tempOwner);
|
||||
}
|
||||
@ -881,27 +858,28 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(message.length())
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text << message;
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
collectRes(h->getOwner());
|
||||
}
|
||||
}
|
||||
|
||||
void CGResource::collectRes(const PlayerColor & player) const
|
||||
{
|
||||
cb->giveResource(player, static_cast<Res::ERes>(subID), amount);
|
||||
ShowInInfobox sii;
|
||||
InfoWindow sii;
|
||||
sii.player = player;
|
||||
sii.c = Component(Component::RESOURCE,subID,amount,0);
|
||||
sii.text.addTxt(MetaString::ADVOB_TXT,113);
|
||||
sii.text.addReplacement(MetaString::RES_NAMES, subID);
|
||||
cb->showCompInfo(&sii);
|
||||
if(!message.empty())
|
||||
{
|
||||
sii.type = EInfoWindowMode::AUTO;
|
||||
sii.text << message;
|
||||
}
|
||||
else
|
||||
{
|
||||
sii.type = EInfoWindowMode::INFO;
|
||||
sii.text.addTxt(MetaString::ADVOB_TXT,113);
|
||||
sii.text.addReplacement(MetaString::RES_NAMES, subID);
|
||||
}
|
||||
sii.components.emplace_back(Component::EComponentType::RESOURCE,subID,amount,0);
|
||||
sii.soundID = soundBase::pickup01 + CRandomGenerator::getDefault().nextInt(6);
|
||||
cb->showInfoDialog(&sii);
|
||||
cb->removeObject(this);
|
||||
}
|
||||
|
||||
@ -1077,7 +1055,7 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
|
||||
logGlobal->debug("All exits blocked for monolith %d at %s", id.getNum(), pos.toString());
|
||||
}
|
||||
else
|
||||
showInfoDialog(h, 70, 0);
|
||||
h->showInfoDialog(70);
|
||||
|
||||
cb->showTeleportDialog(&td);
|
||||
}
|
||||
@ -1133,7 +1111,7 @@ void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
|
||||
TeleportDialog td(h->tempOwner, channel);
|
||||
if(cb->isTeleportChannelImpassable(channel))
|
||||
{
|
||||
showInfoDialog(h,153,0);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged.
|
||||
h->showInfoDialog(153);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged.
|
||||
logGlobal->debug("Cannot find exit subterranean gate for %d at %s", id.getNum(), pos.toString());
|
||||
td.impassable = true;
|
||||
}
|
||||
@ -1236,9 +1214,10 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
|
||||
vstd::amax(countToTake, 1);
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 168);
|
||||
iw.components.emplace_back(CStackBasicDescriptor(h->getCreature(targetstack), countToTake));
|
||||
iw.components.emplace_back(CStackBasicDescriptor(h->getCreature(targetstack), -countToTake));
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->changeStackCount(StackLocation(h, targetstack), -countToTake);
|
||||
}
|
||||
@ -1318,12 +1297,13 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
|
||||
if(!stacksCount())
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
switch(ID)
|
||||
{
|
||||
case Obj::ARTIFACT:
|
||||
{
|
||||
iw.components.emplace_back(Component::ARTIFACT, subID, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::ARTIFACT, subID, 0, 0);
|
||||
if(message.length())
|
||||
iw.text << message;
|
||||
else
|
||||
@ -1333,7 +1313,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
|
||||
case Obj::SPELL_SCROLL:
|
||||
{
|
||||
int spellID = storedArtifact->getGivenSpellID();
|
||||
iw.components.emplace_back(Component::SPELL, spellID, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, spellID, 0, 0);
|
||||
if(message.length())
|
||||
iw.text << message;
|
||||
else
|
||||
@ -1446,6 +1426,7 @@ void CGWitchHut::initObj(CRandomGenerator & rand)
|
||||
void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->getOwner();
|
||||
if(!wasVisited(h->tempOwner))
|
||||
cb->setObjProperty(id, CGWitchHut::OBJPROP_VISITED, h->tempOwner.getNum());
|
||||
@ -1460,7 +1441,7 @@ void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
else //give sec skill
|
||||
{
|
||||
iw.components.emplace_back(Component::SEC_SKILL, ability, 1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, ability, 1, 0);
|
||||
txt_id = 171;
|
||||
cb->changeSecSkill(h, SecondarySkill(ability), 1, true);
|
||||
}
|
||||
@ -1520,6 +1501,7 @@ void CGWitchHut::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
switch (ID)
|
||||
{
|
||||
@ -1562,6 +1544,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->setObjProperty(id, CGShrine::OBJPROP_VISITED, h->tempOwner.getNum());
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->getOwner();
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,127 + ID - 88);
|
||||
iw.text.addTxt(MetaString::SPELL_NAME,spell);
|
||||
@ -1585,7 +1568,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
|
||||
spells.insert(spell);
|
||||
cb->changeSpells(h, true, spells);
|
||||
|
||||
iw.components.emplace_back(Component::SPELL, spell, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, spell, 0, 0);
|
||||
}
|
||||
|
||||
cb->showInfoDialog(&iw);
|
||||
@ -1679,6 +1662,7 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->getOwner();
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,115);
|
||||
|
||||
@ -1686,18 +1670,18 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
case PRIM_SKILL:
|
||||
cb->changePrimSkill(h,static_cast<PrimarySkill::PrimarySkill>(bid),+1);
|
||||
iw.components.emplace_back(Component::PRIM_SKILL, bid, +1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::PRIM_SKILL, bid, +1, 0);
|
||||
break;
|
||||
case SECONDARY_SKILL:
|
||||
cb->changeSecSkill(h,SecondarySkill(bid),+1);
|
||||
iw.components.emplace_back(Component::SEC_SKILL, bid, ssl + 1, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, bid, ssl + 1, 0);
|
||||
break;
|
||||
case SPELL:
|
||||
{
|
||||
std::set<SpellID> hlp;
|
||||
hlp.insert(SpellID(bid));
|
||||
cb->changeSpells(h,true,hlp);
|
||||
iw.components.emplace_back(Component::SPELL, bid, 0, 0);
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, bid, 0, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1851,7 +1835,7 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
if (ID == Obj::HUT_OF_MAGI)
|
||||
{
|
||||
showInfoDialog(h, 61);
|
||||
h->showInfoDialog(61);
|
||||
|
||||
if (!eyelist[subID].empty())
|
||||
{
|
||||
@ -1881,7 +1865,7 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
|
||||
}
|
||||
else if (ID == Obj::EYE_OF_MAGI)
|
||||
{
|
||||
showInfoDialog(h, 48);
|
||||
h->showInfoDialog(48);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1906,6 +1890,7 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
|
||||
iw.player = h->tempOwner;
|
||||
if(h->hasBonusFrom(Bonus::OBJECT,ID)) //has already visited Sirens
|
||||
{
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,133);
|
||||
}
|
||||
else
|
||||
@ -1971,13 +1956,14 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
|
||||
if(s != IBoatGenerator::GOOD)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = tempOwner;
|
||||
getProblemText(iw.text, h);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
else
|
||||
{
|
||||
openWindow(OpenWindow::SHIPYARD_WINDOW,id.getNum(),h->id.getNum());
|
||||
openWindow(EOpenWindowMode::SHIPYARD_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2017,12 +2003,12 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
else //if he cannot afford
|
||||
{
|
||||
showInfoDialog(h, 28);
|
||||
h->showInfoDialog(28);
|
||||
}
|
||||
}
|
||||
else //if he already visited carographer
|
||||
{
|
||||
showInfoDialog(h, 24);
|
||||
h->showInfoDialog(24);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2067,6 +2053,7 @@ void CGDenOfthieves::onHeroVisit (const CGHeroInstance * h) const
|
||||
void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
TeamState *ts = cb->gameState()->getPlayerTeam(h->tempOwner);
|
||||
assert(ts);
|
||||
@ -2080,7 +2067,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
|
||||
// increment general visited obelisks counter
|
||||
cb->setObjProperty(id, CGObelisk::OBJPROP_INC, team.getNum());
|
||||
|
||||
openWindow(OpenWindow::PUZZLE_MAP, h->tempOwner.getNum());
|
||||
openWindow(EOpenWindowMode::PUZZLE_MAP, h->tempOwner.getNum());
|
||||
|
||||
// mark that particular obelisk as visited for all players in the team
|
||||
for(const auto & color : ts->players)
|
||||
@ -2141,7 +2128,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
PlayerColor oldOwner = tempOwner;
|
||||
cb->setOwner(this,h->tempOwner); //not ours? flag it!
|
||||
showInfoDialog(h, 69);
|
||||
h->showInfoDialog(69);
|
||||
giveBonusTo(h->tempOwner);
|
||||
|
||||
if(oldOwner < PlayerColor::PLAYER_LIMIT) //remove bonus from old owner
|
||||
|
@ -243,7 +243,6 @@ void registerTypesClientPacks1(Serializer &s)
|
||||
s.template registerType<CPackForClient, NewTurn>();
|
||||
s.template registerType<CPackForClient, InfoWindow>();
|
||||
s.template registerType<CPackForClient, SetObjectProperty>();
|
||||
s.template registerType<CPackForClient, ShowInInfobox>();
|
||||
s.template registerType<CPackForClient, AdvmapSpellCast>();
|
||||
s.template registerType<CPackForClient, OpenWindow>();
|
||||
s.template registerType<CPackForClient, NewObject>();
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
const ui32 SERIALIZATION_VERSION = 816;
|
||||
const ui32 SERIALIZATION_VERSION = 817;
|
||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 813;
|
||||
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||
|
||||
|
@ -505,7 +505,7 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
|
||||
request.player = parameters.caster->getOwner();
|
||||
request.title.addTxt(MetaString::JK_TXT, 40);
|
||||
request.description.addTxt(MetaString::JK_TXT, 41);
|
||||
request.icon.id = Component::SPELL;
|
||||
request.icon.id = Component::EComponentType::SPELL;
|
||||
request.icon.subtype = owner->id.toEnum();
|
||||
|
||||
env->genericQuery(&request, request.player, queryCallback);
|
||||
|
@ -837,9 +837,9 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance * heroAttacker, con
|
||||
|
||||
for (auto art : arts) //TODO; separate function to display loot for various ojects?
|
||||
{
|
||||
iw.components.push_back(Component(
|
||||
Component::ARTIFACT, art->artType->getId(),
|
||||
art->artType->getId() == ArtifactID::SPELL_SCROLL? art->getGivenSpellID() : 0, 0));
|
||||
iw.components.emplace_back(
|
||||
Component::EComponentType::ARTIFACT, art->artType->getId(),
|
||||
art->artType->getId() == ArtifactID::SPELL_SCROLL? art->getGivenSpellID() : 0, 0);
|
||||
if (iw.components.size() >= 14)
|
||||
{
|
||||
sendAndApply(&iw);
|
||||
@ -881,7 +881,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance * heroAttacker, con
|
||||
iw.text.addReplacement(MetaString::SPELL_NAME, it->toEnum());
|
||||
if (i == cs.spells.size() - 2) //we just added pre-last name
|
||||
iw.text.addReplacement(MetaString::GENERAL_TXT, 141); // " and "
|
||||
iw.components.push_back(Component(Component::SPELL, *it, 0, 0));
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, *it, 0, 0);
|
||||
}
|
||||
sendAndApply(&iw);
|
||||
sendAndApply(&cs);
|
||||
@ -2657,10 +2657,6 @@ void CGameHandler::takeCreatures(ObjectInstanceID objid, const std::vector<CStac
|
||||
}
|
||||
}
|
||||
|
||||
void CGameHandler::showCompInfo(ShowInInfobox * comp)
|
||||
{
|
||||
sendToAllClients(comp);
|
||||
}
|
||||
void CGameHandler::heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)
|
||||
{
|
||||
HeroVisitCastle vc;
|
||||
@ -2822,7 +2818,7 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
|
||||
h2->getSecSkillLevel(SecondarySkill::SCHOLAR));
|
||||
InfoWindow iw;
|
||||
iw.player = h1->tempOwner;
|
||||
iw.components.push_back(Component(Component::SEC_SKILL, 18, ScholarSkillLevel, 0));
|
||||
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, 18, ScholarSkillLevel, 0);
|
||||
|
||||
iw.text.addTxt(MetaString::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
|
||||
iw.text.addReplacement(h1->getNameTranslated());
|
||||
@ -2833,7 +2829,7 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
|
||||
int size = static_cast<int>(cs2.spells.size());
|
||||
for (auto it : cs2.spells)
|
||||
{
|
||||
iw.components.push_back(Component(Component::SPELL, it, 1, 0));
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0);
|
||||
iw.text.addTxt(MetaString::SPELL_NAME, it.toEnum());
|
||||
switch (size--)
|
||||
{
|
||||
@ -2858,7 +2854,7 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
|
||||
int size = static_cast<int>(cs1.spells.size());
|
||||
for (auto it : cs1.spells)
|
||||
{
|
||||
iw.components.push_back(Component(Component::SPELL, it, 1, 0));
|
||||
iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0);
|
||||
iw.text.addTxt(MetaString::SPELL_NAME, it.toEnum());
|
||||
switch (size--)
|
||||
{
|
||||
@ -5582,7 +5578,7 @@ void CGameHandler::handleTimeEvents()
|
||||
for (int i=0; i<ev.resources.size(); i++)
|
||||
{
|
||||
if (ev.resources.at(i)) //if resource is changed, we add it to the dialog
|
||||
iw.components.push_back(Component(Component::RESOURCE,i,ev.resources.at(i),0));
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE,i,ev.resources.at(i),0);
|
||||
}
|
||||
|
||||
sendAndApply(&iw); //show dialog
|
||||
@ -5640,7 +5636,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
|
||||
|
||||
for (int i=0; i<ev.resources.size(); i++)
|
||||
if (ev.resources.at(i) && pinfo->resources.at(i) != n.res.at(player).at(i)) //if resource had changed, we add it to the dialog
|
||||
iw.components.push_back(Component(Component::RESOURCE,i,n.res.at(player).at(i)-was.at(i),0));
|
||||
iw.components.emplace_back(Component::EComponentType::RESOURCE,i,n.res.at(player).at(i)-was.at(i),0);
|
||||
|
||||
}
|
||||
|
||||
@ -5649,7 +5645,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
|
||||
if (!town->hasBuilt(i))
|
||||
{
|
||||
buildStructure(town->id, i, true);
|
||||
iw.components.push_back(Component(Component::BUILDING, town->subID, i, 0));
|
||||
iw.components.emplace_back(Component::EComponentType::BUILDING, town->subID, i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5665,8 +5661,8 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
|
||||
if (!town->creatures.at(i).second.empty() && ev.creatures.at(i) > 0)//there is dwelling
|
||||
{
|
||||
sac.creatures[i].first += ev.creatures.at(i);
|
||||
iw.components.push_back(Component(Component::CREATURE,
|
||||
town->creatures.at(i).second.back(), ev.creatures.at(i), 0));
|
||||
iw.components.emplace_back(Component::EComponentType::CREATURE,
|
||||
town->creatures.at(i).second.back(), ev.creatures.at(i), 0);
|
||||
}
|
||||
}
|
||||
sendAndApply(&iw); //show dialog
|
||||
@ -5725,7 +5721,7 @@ void CGameHandler::showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID h
|
||||
void CGameHandler::showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId)
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.window = OpenWindow::THIEVES_GUILD;
|
||||
ow.window = EOpenWindowMode::THIEVES_GUILD;
|
||||
ow.id1 = player.getNum();
|
||||
ow.id2 = requestingObjId.getNum();
|
||||
sendAndApply(&ow);
|
||||
@ -6028,7 +6024,7 @@ void CGameHandler::getVictoryLossMessage(PlayerColor player, const EVictoryLossC
|
||||
if (victoryLossCheckResult.messageToSelf.find("%s") != std::string::npos)
|
||||
out.text.addReplacement(MetaString::COLOR, player.getNum());
|
||||
|
||||
out.components.push_back(Component(Component::FLAG, player.getNum(), 0, 0));
|
||||
out.components.emplace_back(Component::EComponentType::FLAG, player.getNum(), 0, 0);
|
||||
}
|
||||
|
||||
bool CGameHandler::dig(const CGHeroInstance *h)
|
||||
@ -6050,6 +6046,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
|
||||
sendAndApply(&smp);
|
||||
|
||||
InfoWindow iw;
|
||||
iw.type = EInfoWindowMode::AUTO;
|
||||
iw.player = h->tempOwner;
|
||||
if (gs->map->grailPos == h->visitablePos())
|
||||
{
|
||||
@ -6060,6 +6057,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
|
||||
sendAndApply(&iw);
|
||||
|
||||
iw.soundID = soundBase::invalid;
|
||||
iw.components.emplace_back(Component::EComponentType::ARTIFACT, ArtifactID::GRAIL, 0, 0);
|
||||
iw.text.clear();
|
||||
iw.text.addTxt(MetaString::ART_DESCR, ArtifactID::GRAIL);
|
||||
sendAndApply(&iw);
|
||||
|
@ -184,7 +184,6 @@ public:
|
||||
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap);
|
||||
void synchronizeArtifactHandlerLists();
|
||||
|
||||
void showCompInfo(ShowInInfobox * comp) override;
|
||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override;
|
||||
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override;
|
||||
void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = nullptr) override; //use hero=nullptr for no hero
|
||||
|
@ -70,7 +70,6 @@ public:
|
||||
void removeArtifact(const ArtifactLocation &al) override {}
|
||||
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;}
|
||||
|
||||
void showCompInfo(ShowInInfobox * comp) override {}
|
||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {}
|
||||
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {}
|
||||
void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero) override {}
|
||||
|
Loading…
Reference in New Issue
Block a user