From 6352e8e3196f78388b6c771073f9e03eaa612673 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:33:09 +1000 Subject: everything everywhere all at once --- source/frontend/StarQuestInterface.cpp | 447 +++++++++++++++++++++++++++++++++ 1 file changed, 447 insertions(+) create mode 100644 source/frontend/StarQuestInterface.cpp (limited to 'source/frontend/StarQuestInterface.cpp') 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("scrollArea.verticalLayout.mainQuestList"); + auto sideQuestList = fetchChild("scrollArea.verticalLayout.sideQuestList"); + mainQuestList->setCallback([sideQuestList](Widget* widget) { + auto listWidget = as(widget); + if (listWidget->selectedItem() != NPos) + sideQuestList->clearSelected(); + }); + sideQuestList->setCallback([mainQuestList](Widget* widget) { + auto listWidget = as(widget); + if (listWidget->selectedItem() != NPos) + mainQuestList->clearSelected(); + }); + mainQuestList->disableScissoring(); + sideQuestList->disableScissoring(); + + m_rewardItems = make_shared(5); + fetchChild("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(failableQuest.value(), m_player); + (*failableQuest)->setDialogShown(); + paneManager->displayPane(PaneLayer::ModalWindow, qfi); + } else if (auto completableQuest = m_manager->getFirstCompletableQuest()) { + auto qci = make_shared(completableQuest.value(), m_player, m_cinematic); + (*completableQuest)->setDialogShown(); + paneManager->displayPane(PaneLayer::ModalWindow, qci); + } else if (auto newQuest = m_manager->getFirstNewQuest()) { + auto nqd = make_shared(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("btnToggleTracking")->enable(); + fetchChild("btnToggleTracking")->setText(m_manager->isCurrent(quest->questId()) ? m_untrackLabel : m_trackLabel); + if (quest->canBeAbandoned()) + fetchChild("btnAbandon")->enable(); + else + fetchChild("btnAbandon")->disable(); + } else { + fetchChild("btnToggleTracking")->disable(); + fetchChild("btnToggleTracking")->setText(m_trackLabel); + fetchChild("btnAbandon")->disable(); + } + fetchChild("lblQuestTitle")->setText(quest->title()); + fetchChild("lblQuestBody")->setText(quest->text()); + + auto portraitName = "Objective"; + auto imagePortrait = quest->portrait(portraitName); + if (imagePortrait) { + auto portraitTitleLabel = fetchChild("lblPortraitTitle"); + String portraitTitle = quest->portraitTitle(portraitName).value(""); + Maybe charLimit = portraitTitleLabel->getTextCharLimit(); + portraitTitleLabel->setText(portraitTitle); + + Drawable::scaleAll(*imagePortrait, Vec2F(-1, 1)); + fetchChild("imgPortrait")->setDrawables(*imagePortrait); + fetchChild("imgPolaroid")->setVisibility(true); + fetchChild("imgPolaroidBack")->setVisibility(true); + + } else { + fetchChild("lblPortraitTitle")->setText(""); + fetchChild("imgPortrait")->setDrawables({}); + fetchChild("imgPolaroid")->setVisibility(false); + fetchChild("imgPolaroidBack")->setVisibility(false); + } + + m_rewardItems->clearItems(); + if (quest->rewards().size() > 0) { + fetchChild("lblRewards")->setVisibility(true); + fetchChild("rewardItems")->setVisibility(true); + for (auto const& reward : quest->rewards()) + m_rewardItems->addItems(reward->clone()); + } else { + fetchChild("lblRewards")->setVisibility(false); + fetchChild("rewardItems")->setVisibility(false); + } + } else { + fetchChild("btnToggleTracking")->disable(); + fetchChild("btnToggleTracking")->setText(m_trackLabel); + fetchChild("btnAbandon")->disable(); + fetchChild("lblQuestTitle")->setText(""); + fetchChild("lblQuestBody")->setText(""); + fetchChild("lblPortraitTitle")->setText(""); + fetchChild("imgPortrait")->setDrawables({}); + fetchChild("lblRewards")->setVisibility(false); + fetchChild("rewardItems")->setVisibility(false); + fetchChild("imgPolaroid")->setVisibility(false); + fetchChild("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(child)) + item = itemSlot->item(); + if (auto itemGrid = as(child)) + item = itemGrid->itemAt(screenPosition); + } + if (item) + return ItemTooltipBuilder::buildItemTooltip(item, m_player); + return {}; +} + +WidgetPtr QuestLogInterface::getSelected() { + auto mainQuestList = fetchChild("scrollArea.verticalLayout.mainQuestList"); + if (auto selected = mainQuestList->selectedWidget()) + return selected; + + auto sideQuestList = fetchChild("scrollArea.verticalLayout.sideQuestList"); + if (auto selected = sideQuestList->selectedWidget()) + return selected; + + return {}; +} + +void QuestLogInterface::setSelected(WidgetPtr selected) { + auto mainQuestList = fetchChild("scrollArea.verticalLayout.mainQuestList"); + auto mainQuestListPos = mainQuestList->itemPosition(selected); + if (mainQuestListPos != NPos) { + mainQuestList->setSelected(mainQuestListPos); + return; + } + + auto sideQuestList = fetchChild("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("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 quests) { + auto mainQuestList = fetchChild("scrollArea.verticalLayout.mainQuestList"); + auto sideQuestList = fetchChild("scrollArea.verticalLayout.sideQuestList"); + + auto mainQuestHeader = fetchChild("scrollArea.verticalLayout.mainQuestHeader"); + auto sideQuestHeader = fetchChild("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("lblQuestEntry")->setText(quest->title()); + entry->fetchChild("imgNew")->setVisibility(quest->unread()); + entry->fetchChild("imgTracked")->setVisibility(m_manager->isCurrent(quest->questId())); + + bool currentWorld = false; + if (auto questWorld = quest->worldId()) { + currentWorld = m_client->playerWorld() == *questWorld; + } + entry->fetchChild("imgCurrent")->setVisibility(currentWorld); + + entry->fetchChild("imgPortrait")->setDrawables(quest->portrait("QuestStarted").value({})); + entry->show(); + if (quest->questId() == selectedQuest) + setSelected(entry); + } + + auto verticalLayout = fetchChild("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("lblQuestTitle")) + titleLabel->setText(m_quest->title()); + if (auto bodyLabel = fetchChild("lblQuestBody")) + bodyLabel->setText(bodyText); + + if (auto portraitImage = fetchChild("portraitImage")) { + Maybe> portrait = m_quest->portrait(portraitName); + portraitImage->setDrawables(portrait.value({})); + } + + if (auto portraitTitleLabel = fetchChild("portraitTitle")) { + Maybe portraitTitle = m_quest->portraitTitle(portraitName); + String text = m_quest->portraitTitle(portraitName).value(""); + Maybe charLimit = portraitTitleLabel->getTextCharLimit(); + portraitTitleLabel->setText(text); + } + + if (auto rewardItemsWidget = fetchChild("rewardItems")) { + auto rewardItems = make_shared(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(child)) + item = itemSlot->item(); + if (auto itemGrid = as(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 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("btnDecline")) + declineButton->disable(); + } + + if (!shortDialog) { + if (auto objectivePortraitImage = fetchChild("objectivePortraitImage")) { + Drawable::scaleAll(objectivePortrait, Vec2F(-1, 1)); + objectivePortraitImage->setDrawables(objectivePortrait); + + String objectivePortraitTitle = m_quest->portraitTitle("Objective").value(""); + auto portraitLabel = fetchChild("objectivePortraitTitle"); + portraitLabel->setText(objectivePortraitTitle); + portraitLabel->setVisibility(objectivePortrait.size() > 0); + + fetchChild("imgPolaroid")->setVisibility(objectivePortrait.size() > 0); + fetchChild("imgPolaroidBack")->setVisibility(objectivePortrait.size() > 0); + } + } + + if (auto rewardItemsWidget = fetchChild("rewardItems")) + rewardItemsWidget->setVisibility(m_quest->rewards().size() > 0); + if (auto rewardsLabel = fetchChild("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("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{{"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(); +} + +} -- cgit v1.2.3