diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/frontend/StarQuestInterface.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/frontend/StarQuestInterface.cpp')
-rw-r--r-- | source/frontend/StarQuestInterface.cpp | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/source/frontend/StarQuestInterface.cpp b/source/frontend/StarQuestInterface.cpp new file mode 100644 index 0000000..cb1f3e5 --- /dev/null +++ b/source/frontend/StarQuestInterface.cpp @@ -0,0 +1,447 @@ +#include "StarQuestInterface.hpp" +#include "StarQuestManager.hpp" +#include "StarCinematic.hpp" +#include "StarGuiReader.hpp" +#include "StarRoot.hpp" +#include "StarUniverseClient.hpp" +#include "StarPaneManager.hpp" +#include "StarListWidget.hpp" +#include "StarItemGridWidget.hpp" +#include "StarButtonWidget.hpp" +#include "StarLabelWidget.hpp" +#include "StarLabelWidget.hpp" +#include "StarImageWidget.hpp" +#include "StarAssets.hpp" +#include "StarItemDatabase.hpp" +#include "StarRandom.hpp" +#include "StarJsonExtra.hpp" +#include "StarPlayer.hpp" +#include "StarVerticalLayout.hpp" +#include "StarItemTooltip.hpp" + +namespace Star { + +QuestLogInterface::QuestLogInterface(QuestManagerPtr manager, PlayerPtr player, CinematicPtr cinematic, UniverseClientPtr client) { + m_manager = manager; + m_player = player; + m_cinematic = cinematic; + m_client = client; + + auto assets = Root::singleton().assets(); + auto config = assets->json("/interface/windowconfig/questlog.config"); + + m_trackLabel = config.getString("trackLabel"); + m_untrackLabel = config.getString("untrackLabel"); + + GuiReader reader; + + reader.registerCallback("close", [=](Widget*) { dismiss(); }); + reader.registerCallback("btnToggleTracking", + [=](Widget*) { + toggleTracking(); + }); + reader.registerCallback("btnAbandon", + [=](Widget*) { + abandon(); + }); + reader.registerCallback("filter", + [=](Widget*) { + fetchData(); + }); + + reader.construct(config.get("paneLayout"), this); + + auto mainQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.mainQuestList"); + auto sideQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.sideQuestList"); + mainQuestList->setCallback([sideQuestList](Widget* widget) { + auto listWidget = as<ListWidget>(widget); + if (listWidget->selectedItem() != NPos) + sideQuestList->clearSelected(); + }); + sideQuestList->setCallback([mainQuestList](Widget* widget) { + auto listWidget = as<ListWidget>(widget); + if (listWidget->selectedItem() != NPos) + mainQuestList->clearSelected(); + }); + mainQuestList->disableScissoring(); + sideQuestList->disableScissoring(); + + m_rewardItems = make_shared<ItemBag>(5); + fetchChild<ItemGridWidget>("rewardItems")->setItemBag(m_rewardItems); + + m_refreshRate = 30; + m_refreshTimer = 0; +} + +void QuestLogInterface::pollDialog(PaneManager* paneManager) { + if (paneManager->topPane({PaneLayer::ModalWindow})) + return; + + if (auto failableQuest = m_manager->getFirstFailableQuest()) { + auto qfi = make_shared<QuestFailedInterface>(failableQuest.value(), m_player); + (*failableQuest)->setDialogShown(); + paneManager->displayPane(PaneLayer::ModalWindow, qfi); + } else if (auto completableQuest = m_manager->getFirstCompletableQuest()) { + auto qci = make_shared<QuestCompleteInterface>(completableQuest.value(), m_player, m_cinematic); + (*completableQuest)->setDialogShown(); + paneManager->displayPane(PaneLayer::ModalWindow, qci); + } else if (auto newQuest = m_manager->getFirstNewQuest()) { + auto nqd = make_shared<NewQuestInterface>(m_manager, newQuest.value(), m_player); + paneManager->displayPane(PaneLayer::ModalWindow, nqd); + } +} + +void QuestLogInterface::displayed() { + Pane::displayed(); + tick(); + fetchData(); +} + +void QuestLogInterface::tick() { + Pane::tick(); + auto selected = getSelected(); + if (selected && m_manager->hasQuest(selected->data().toString())) { + auto quest = m_manager->getQuest(selected->data().toString()); + + m_manager->markAsRead(quest->questId()); + + if (m_manager->isActive(quest->questId())) { + fetchChild<ButtonWidget>("btnToggleTracking")->enable(); + fetchChild<ButtonWidget>("btnToggleTracking")->setText(m_manager->isCurrent(quest->questId()) ? m_untrackLabel : m_trackLabel); + if (quest->canBeAbandoned()) + fetchChild<ButtonWidget>("btnAbandon")->enable(); + else + fetchChild<ButtonWidget>("btnAbandon")->disable(); + } else { + fetchChild<ButtonWidget>("btnToggleTracking")->disable(); + fetchChild<ButtonWidget>("btnToggleTracking")->setText(m_trackLabel); + fetchChild<ButtonWidget>("btnAbandon")->disable(); + } + fetchChild<LabelWidget>("lblQuestTitle")->setText(quest->title()); + fetchChild<LabelWidget>("lblQuestBody")->setText(quest->text()); + + auto portraitName = "Objective"; + auto imagePortrait = quest->portrait(portraitName); + if (imagePortrait) { + auto portraitTitleLabel = fetchChild<LabelWidget>("lblPortraitTitle"); + String portraitTitle = quest->portraitTitle(portraitName).value(""); + Maybe<unsigned> charLimit = portraitTitleLabel->getTextCharLimit(); + portraitTitleLabel->setText(portraitTitle); + + Drawable::scaleAll(*imagePortrait, Vec2F(-1, 1)); + fetchChild<ImageWidget>("imgPortrait")->setDrawables(*imagePortrait); + fetchChild<ImageWidget>("imgPolaroid")->setVisibility(true); + fetchChild<ImageWidget>("imgPolaroidBack")->setVisibility(true); + + } else { + fetchChild<LabelWidget>("lblPortraitTitle")->setText(""); + fetchChild<ImageWidget>("imgPortrait")->setDrawables({}); + fetchChild<ImageWidget>("imgPolaroid")->setVisibility(false); + fetchChild<ImageWidget>("imgPolaroidBack")->setVisibility(false); + } + + m_rewardItems->clearItems(); + if (quest->rewards().size() > 0) { + fetchChild<LabelWidget>("lblRewards")->setVisibility(true); + fetchChild<ItemGridWidget>("rewardItems")->setVisibility(true); + for (auto const& reward : quest->rewards()) + m_rewardItems->addItems(reward->clone()); + } else { + fetchChild<LabelWidget>("lblRewards")->setVisibility(false); + fetchChild<ItemGridWidget>("rewardItems")->setVisibility(false); + } + } else { + fetchChild<ButtonWidget>("btnToggleTracking")->disable(); + fetchChild<ButtonWidget>("btnToggleTracking")->setText(m_trackLabel); + fetchChild<ButtonWidget>("btnAbandon")->disable(); + fetchChild<LabelWidget>("lblQuestTitle")->setText(""); + fetchChild<LabelWidget>("lblQuestBody")->setText(""); + fetchChild<LabelWidget>("lblPortraitTitle")->setText(""); + fetchChild<ImageWidget>("imgPortrait")->setDrawables({}); + fetchChild<LabelWidget>("lblRewards")->setVisibility(false); + fetchChild<ItemGridWidget>("rewardItems")->setVisibility(false); + fetchChild<ImageWidget>("imgPolaroid")->setVisibility(false); + fetchChild<ImageWidget>("imgPolaroidBack")->setVisibility(false); + m_rewardItems->clearItems(); + } + + m_refreshTimer--; + if (m_refreshTimer < 0) { + fetchData(); + m_refreshTimer = m_refreshRate; + } +} + +PanePtr QuestLogInterface::createTooltip(Vec2I const& screenPosition) { + ItemPtr item; + if (auto child = getChildAt(screenPosition)) { + if (auto itemSlot = as<ItemSlotWidget>(child)) + item = itemSlot->item(); + if (auto itemGrid = as<ItemGridWidget>(child)) + item = itemGrid->itemAt(screenPosition); + } + if (item) + return ItemTooltipBuilder::buildItemTooltip(item, m_player); + return {}; +} + +WidgetPtr QuestLogInterface::getSelected() { + auto mainQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.mainQuestList"); + if (auto selected = mainQuestList->selectedWidget()) + return selected; + + auto sideQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.sideQuestList"); + if (auto selected = sideQuestList->selectedWidget()) + return selected; + + return {}; +} + +void QuestLogInterface::setSelected(WidgetPtr selected) { + auto mainQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.mainQuestList"); + auto mainQuestListPos = mainQuestList->itemPosition(selected); + if (mainQuestListPos != NPos) { + mainQuestList->setSelected(mainQuestListPos); + return; + } + + auto sideQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.sideQuestList"); + auto sideQuestListPos = sideQuestList->itemPosition(selected); + if (sideQuestListPos != NPos) { + sideQuestList->setSelected(sideQuestListPos); + return; + } +} + +void QuestLogInterface::toggleTracking() { + if (auto selected = getSelected()) { + String questId = selected->data().toString(); + if (!m_manager->isCurrent(questId)) + m_manager->setAsTracked(questId); + else + m_manager->setAsTracked({}); + } +} + +void QuestLogInterface::abandon() { + if (auto selected = getSelected()) { + m_manager->getQuest(selected->data().toString())->abandon(); + } +} + +void QuestLogInterface::fetchData() { + auto filter = fetchChild<ButtonGroupWidget>("filter")->checkedButton()->data().toString(); + if (filter.equalsIgnoreCase("inProgress")) + showQuests(m_manager->listActiveQuests()); + else if (filter.equalsIgnoreCase("completed")) + showQuests(m_manager->listCompletedQuests()); + else + throw StarException(strf("Unknown quest filter '%s'", filter)); +} + +void QuestLogInterface::showQuests(List<QuestPtr> quests) { + auto mainQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.mainQuestList"); + auto sideQuestList = fetchChild<ListWidget>("scrollArea.verticalLayout.sideQuestList"); + + auto mainQuestHeader = fetchChild<Widget>("scrollArea.verticalLayout.mainQuestHeader"); + auto sideQuestHeader = fetchChild<Widget>("scrollArea.verticalLayout.sideQuestHeader"); + + String selectedQuest; + if (auto selected = getSelected()) + selectedQuest = selected->data().toString(); + else if (m_manager->currentQuest()) + selectedQuest = (*m_manager->currentQuest())->questId(); + + mainQuestList->clear(); + mainQuestHeader->hide(); + sideQuestList->clear(); + sideQuestHeader->hide(); + for (auto const& quest : quests) { + WidgetPtr entry; + if (quest->mainQuest()) { + entry = mainQuestList->addItem(); + mainQuestHeader->show(); + } else { + entry = sideQuestList->addItem(); + sideQuestHeader->show(); + } + + entry->setData(quest->questId()); + entry->fetchChild<LabelWidget>("lblQuestEntry")->setText(quest->title()); + entry->fetchChild<ImageWidget>("imgNew")->setVisibility(quest->unread()); + entry->fetchChild<ImageWidget>("imgTracked")->setVisibility(m_manager->isCurrent(quest->questId())); + + bool currentWorld = false; + if (auto questWorld = quest->worldId()) { + currentWorld = m_client->playerWorld() == *questWorld; + } + entry->fetchChild<ImageWidget>("imgCurrent")->setVisibility(currentWorld); + + entry->fetchChild<ImageWidget>("imgPortrait")->setDrawables(quest->portrait("QuestStarted").value({})); + entry->show(); + if (quest->questId() == selectedQuest) + setSelected(entry); + } + + auto verticalLayout = fetchChild<VerticalLayout>("scrollArea.verticalLayout"); + verticalLayout->update(); +} + +QuestPane::QuestPane(QuestPtr const& quest, PlayerPtr player) : Pane(), m_quest(quest), m_player(move(player)) {} + +void QuestPane::commonSetup(Json config, String bodyText, String const& portraitName) { + GuiReader reader; + + reader.registerCallback("close", [=](Widget*) { close(); }); + reader.registerCallback("btnDecline", [=](Widget*) { close(); }); + reader.registerCallback("btnAccept", [=](Widget*) { accept(); }); + reader.construct(config.get("paneLayout"), this); + + if (auto titleLabel = fetchChild<LabelWidget>("lblQuestTitle")) + titleLabel->setText(m_quest->title()); + if (auto bodyLabel = fetchChild<LabelWidget>("lblQuestBody")) + bodyLabel->setText(bodyText); + + if (auto portraitImage = fetchChild<ImageWidget>("portraitImage")) { + Maybe<List<Drawable>> portrait = m_quest->portrait(portraitName); + portraitImage->setDrawables(portrait.value({})); + } + + if (auto portraitTitleLabel = fetchChild<LabelWidget>("portraitTitle")) { + Maybe<String> portraitTitle = m_quest->portraitTitle(portraitName); + String text = m_quest->portraitTitle(portraitName).value(""); + Maybe<unsigned> charLimit = portraitTitleLabel->getTextCharLimit(); + portraitTitleLabel->setText(text); + } + + if (auto rewardItemsWidget = fetchChild<ItemGridWidget>("rewardItems")) { + auto rewardItems = make_shared<ItemBag>(5); + for (auto const& reward : m_quest->rewards()) + rewardItems->addItems(reward->clone()); + rewardItemsWidget->setItemBag(rewardItems); + } + + auto sound = Random::randValueFrom(config.get("onShowSound").toArray(), "").toString(); + if (!sound.empty()) + context()->playAudio(sound); +} + +void QuestPane::close() { + dismiss(); +} + +void QuestPane::accept() { + close(); +} + +PanePtr QuestPane::createTooltip(Vec2I const& screenPosition) { + ItemPtr item; + if (auto child = getChildAt(screenPosition)) { + if (auto itemSlot = as<ItemSlotWidget>(child)) + item = itemSlot->item(); + if (auto itemGrid = as<ItemGridWidget>(child)) + item = itemGrid->itemAt(screenPosition); + } + if (item) + return ItemTooltipBuilder::buildItemTooltip(item, m_player); + return {}; +} + +NewQuestInterface::NewQuestInterface(QuestManagerPtr const& manager, QuestPtr const& quest, PlayerPtr player) + : QuestPane(quest, move(player)), m_manager(manager), m_declined(false) { + auto assets = Root::singleton().assets(); + + List<Drawable> objectivePortrait = m_quest->portrait("Objective").value({}); + bool shortDialog = objectivePortrait.size() == 0; + + String configFile; + if (shortDialog) + configFile = m_quest->getTemplate()->newQuestGuiConfig.value(assets->json("/quests/quests.config:defaultGuiConfigs.newQuest").toString()); + else + configFile = m_quest->getTemplate()->newQuestGuiConfig.value(assets->json("/quests/quests.config:defaultGuiConfigs.newQuestPortrait").toString()); + + Json config = assets->json(configFile); + + commonSetup(config, m_quest->text(), "QuestStarted"); + + m_declined = m_quest->canBeAbandoned(); + if (!m_declined) { + if (auto declineButton = fetchChild<ButtonWidget>("btnDecline")) + declineButton->disable(); + } + + if (!shortDialog) { + if (auto objectivePortraitImage = fetchChild<ImageWidget>("objectivePortraitImage")) { + Drawable::scaleAll(objectivePortrait, Vec2F(-1, 1)); + objectivePortraitImage->setDrawables(objectivePortrait); + + String objectivePortraitTitle = m_quest->portraitTitle("Objective").value(""); + auto portraitLabel = fetchChild<LabelWidget>("objectivePortraitTitle"); + portraitLabel->setText(objectivePortraitTitle); + portraitLabel->setVisibility(objectivePortrait.size() > 0); + + fetchChild<ImageWidget>("imgPolaroid")->setVisibility(objectivePortrait.size() > 0); + fetchChild<ImageWidget>("imgPolaroidBack")->setVisibility(objectivePortrait.size() > 0); + } + } + + if (auto rewardItemsWidget = fetchChild<ItemGridWidget>("rewardItems")) + rewardItemsWidget->setVisibility(m_quest->rewards().size() > 0); + if (auto rewardsLabel = fetchChild<LabelWidget>("lblRewards")) + rewardsLabel->setVisibility(m_quest->rewards().size() > 0); +} + +void NewQuestInterface::close() { + m_declined = true; + dismiss(); +} + +void NewQuestInterface::accept() { + m_declined = false; + dismiss(); +} + +void NewQuestInterface::dismissed() { + QuestPane::dismissed(); + if (m_declined && m_quest->canBeAbandoned()) { + m_manager->getQuest(m_quest->questId())->declineOffer(); + } else { + m_manager->getQuest(m_quest->questId())->start(); + } +} + +QuestCompleteInterface::QuestCompleteInterface(QuestPtr const& quest, PlayerPtr player, CinematicPtr cinematic) + : QuestPane(quest, player) { + auto assets = Root::singleton().assets(); + String configFile = m_quest->getTemplate()->questCompleteGuiConfig.value(assets->json("/quests/quests.config:defaultGuiConfigs.questComplete").toString()); + Json config = assets->json(configFile); + + m_player = player; + m_cinematic = cinematic; + + commonSetup(config, m_quest->completionText(), "QuestComplete"); + + if (auto moneyLabel = fetchChild<LabelWidget>("lblMoneyAmount")) + moneyLabel->setText(strf("%s", m_quest->money())); + disableScissoring(); +} + +void QuestCompleteInterface::close() { + auto assets = Root::singleton().assets(); + if (m_quest->completionCinema() && m_cinematic) { + String cinema = m_quest->completionCinema()->replaceTags( + StringMap<String>{{"species", m_player->species()}, {"gender", GenderNames.getRight(m_player->gender())}}); + m_cinematic->load(assets->fetchJson(cinema)); + } + dismiss(); +} + +QuestFailedInterface::QuestFailedInterface(QuestPtr const& quest, PlayerPtr player) : QuestPane(quest, move(player)) { + auto assets = Root::singleton().assets(); + String configFile = m_quest->getTemplate()->questFailedGuiConfig.value(assets->json("/quests/quests.config:defaultGuiConfigs.questFailed").toString()); + Json config = assets->json(configFile); + commonSetup(config, m_quest->failureText(), "QuestFailed"); + disableScissoring(); +} + +} |