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/StarContainerInterface.cpp | 303 +++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 source/frontend/StarContainerInterface.cpp (limited to 'source/frontend/StarContainerInterface.cpp') diff --git a/source/frontend/StarContainerInterface.cpp b/source/frontend/StarContainerInterface.cpp new file mode 100644 index 0000000..e94c25c --- /dev/null +++ b/source/frontend/StarContainerInterface.cpp @@ -0,0 +1,303 @@ +#include "StarContainerInterface.hpp" +#include "StarCasting.hpp" +#include "StarContainerEntity.hpp" +#include "StarWorldClient.hpp" +#include "StarRoot.hpp" +#include "StarItemTooltip.hpp" +#include "StarItemGridWidget.hpp" +#include "StarLabelWidget.hpp" +#include "StarImageWidget.hpp" +#include "StarPaneManager.hpp" +#include "StarFuelWidget.hpp" +#include "StarPlayer.hpp" +#include "StarItemDatabase.hpp" +#include "StarObject.hpp" +#include "StarPlayerInventory.hpp" +#include "StarConfigLuaBindings.hpp" +#include "StarPlayerLuaBindings.hpp" +#include "StarStatusControllerLuaBindings.hpp" +#include "StarWidgetLuaBindings.hpp" +#include "StarAugmentItem.hpp" + +namespace Star { + +ContainerPane::ContainerPane(WorldClientPtr worldClient, PlayerPtr player, ContainerInteractorPtr containerInteractor) { + m_worldClient = worldClient; + m_player = player; + m_containerInteractor = move(containerInteractor); + + auto container = m_containerInteractor->openContainer(); + auto guiConfig = container->containerGuiConfig(); + + if (auto scripts = guiConfig.opt("scripts").apply(jsonToStringList)) { + if (!m_script) { + m_script.emplace(); + m_script->setScripts(*scripts); + } + m_script->addCallbacks("widget", LuaBindings::makeWidgetCallbacks(this, &m_reader)); + m_script->addCallbacks("config", LuaBindings::makeConfigCallbacks( [guiConfig](String const& name, Json const& def) { + return guiConfig.query(name, def); + })); + m_script->addCallbacks("player", LuaBindings::makePlayerCallbacks(m_player.get())); + m_script->addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_player->statusController())); + + LuaCallbacks containerPaneCallbacks; + containerPaneCallbacks.registerCallback("containerEntityId", [this]() -> Maybe { + return m_containerInteractor->openContainerId(); + }); + containerPaneCallbacks.registerCallback("playerEntityId", [this]() { return m_player->entityId(); }); + containerPaneCallbacks.registerCallback("dismiss", [this]() { dismiss(); }); + m_script->addCallbacks("pane", containerPaneCallbacks); + + m_script->setUpdateDelta(guiConfig.getUInt("scriptDelta", 1)); + } + + auto rightClickCallback = [this](size_t index) { + if (m_expectingSwap != ExpectingSwap::None) + return; + + if (ItemPtr slotItem = m_containerInteractor->openContainer()->itemBag()->at(index)) { + auto swapItem = m_player->inventory()->swapSlotItem(); + if (!swapItem || swapItem->empty() || swapItem->couldStack(slotItem)) { + size_t count = swapItem ? swapItem->couldStack(slotItem) : slotItem->maxStack(); + if (context()->shiftHeld()) + count = max(1, min(count, slotItem->count() / 2)); + else + count = 1; + + m_containerInteractor->takeFromContainerSlot(index, count); + m_expectingSwap = ExpectingSwap::SwapSlotStack; + } else if (is(swapItem)) { + m_containerInteractor->applyAugmentInContainer(index, swapItem); + m_player->inventory()->setSwapSlotItem({}); + m_expectingSwap = ExpectingSwap::SwapSlot; + } + } + }; + + m_reader.registerCallback("close", [this](Widget*) { dismiss(); }); + m_reader.registerCallback("itemGrid", [=](Widget* paneObj) { + if (auto itemGrid = as(paneObj)) + swapSlot(itemGrid); + else + throw GuiException("Invalid object type, expected ItemGridWidget."); + }); + m_reader.registerCallback("itemGrid.right", [=](Widget* paneObj) { + if (auto itemGrid = as(paneObj)) + rightClickCallback(itemGrid->selectedIndex()); + else + throw GuiException("Invalid object type, expected ItemGridWidget."); + }); + + m_reader.registerCallback("itemGrid2", [=](Widget* paneObj) { + if (auto itemGrid = as(paneObj)) + swapSlot(itemGrid); + else + throw GuiException("Invalid object type, expected ItemGridWidget."); + }); + m_reader.registerCallback("itemGrid2.right", [=](Widget* paneObj) { + if (auto itemGrid = as(paneObj)) + rightClickCallback(itemGrid->selectedIndex()); + else + throw GuiException("Invalid object type, expected ItemGridWidget."); + }); + + m_reader.registerCallback("outputItemGrid", [=](Widget* paneObj) { + if (auto itemGrid = as(paneObj)) + swapSlot(itemGrid); + else + throw GuiException("Invalid object type, expected ItemGridWidget."); + }); + m_reader.registerCallback("outputItemGrid.right", [=](Widget* paneObj) { + if (auto itemGrid = as(paneObj)) + rightClickCallback(itemGrid->selectedIndex()); + else + throw GuiException("Invalid object type, expected ItemGridWidget."); + }); + + m_reader.registerCallback("toggleCrafting", [=](Widget*) { toggleCrafting(); }); + + m_reader.registerCallback("clear", [=](Widget*) { clear(); }); + m_reader.registerCallback("burn", [=](Widget*) { burn(); }); + + for (auto const& callbackName : jsonToStringList(guiConfig.get("scriptWidgetCallbacks", JsonArray{}))) { + m_reader.registerCallback(callbackName, [this, callbackName](Widget* widget) { + m_script->invoke(callbackName, widget->name(), widget->data()); + }); + } + + m_reader.construct(guiConfig.get("gui"), this); + + if (auto countWidget = fetchChild("count")) + countWidget->setText(countWidget->text().replace("", strf("%s", container->containerSize()))); + + m_itemBag = make_shared(container->containerSize()); + auto items = container->containerItems(); + + fetchChild("itemGrid")->setItemBag(m_itemBag); + if (containsChild("itemGrid2")) + fetchChild("itemGrid2")->setItemBag(m_itemBag); + if (containsChild("outputItemGrid")) + fetchChild("outputItemGrid")->setItemBag(m_itemBag); + + if (container->iconItem()) { + auto itemDatabase = Root::singleton().itemDatabase(); + auto iconItem = itemDatabase->item(container->iconItem()); + auto icon = make_shared(iconItem, "/interface/inventory/portrait.png"); + icon->showDurability(false); + icon->showRarity(false); + icon->setBackingImageAffinity(true, true); + setTitle(icon, container->containerDescription(), container->containerSubTitle()); + } + + if (containsChild("objectImage")) + if (auto containerObject = as(m_containerInteractor->openContainer())) + fetchChild("objectImage")->setDrawables(containerObject->cursorHintDrawables()); + + m_expectingSwap = ExpectingSwap::None; +} + +void ContainerPane::displayed() { + Pane::displayed(); + + m_expectingSwap = ExpectingSwap::None; + + if (m_script) { + if (m_worldClient && m_worldClient->inWorld()) + m_script->init(m_worldClient.get()); + + m_script->invoke("displayed"); + } +} + +void ContainerPane::dismissed() { + Pane::dismissed(); + + if (m_script) { + m_script->invoke("dismissed"); + m_script->uninit(); + } +} + +bool ContainerPane::giveContainerResult(ContainerResult result) { + if (m_expectingSwap == ExpectingSwap::None) + return false; + + for (auto item : result) { + auto inv = m_player->inventory(); + m_player->triggerPickupEvents(item); + + if (m_expectingSwap == ExpectingSwap::SwapSlot) { + m_player->clearSwap(); + inv->setSwapSlotItem(item); + } else if (m_expectingSwap == ExpectingSwap::SwapSlotStack) { + auto swapItem = inv->swapSlotItem(); + if (swapItem && swapItem->stackWith(item)) { + continue; + } else { + inv->clearSwap(); + inv->setSwapSlotItem(item); + } + } else { + m_containerInteractor->addToContainer(inv->addItems(item)); + } + } + + m_expectingSwap = ExpectingSwap::None; + return true; +} + +PanePtr ContainerPane::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 {}; +} + +void ContainerPane::swapSlot(ItemGridWidget* grid) { + auto inv = m_player->inventory(); + if (context()->shiftHeld()) { + auto containerItem = grid->selectedItem(); + if (containerItem && inv->itemsCanFit(containerItem) >= containerItem->count()) { + m_containerInteractor->swapInContainer(grid->selectedIndex(), {}); + m_expectingSwap = ExpectingSwap::Inventory; + } + } else { + m_containerInteractor->swapInContainer(grid->selectedIndex(), inv->swapSlotItem()); + inv->setSwapSlotItem({}); + m_expectingSwap = ExpectingSwap::SwapSlot; + } +} + +void ContainerPane::startCrafting() { + m_containerInteractor->startCraftingInContainer(); +} + +void ContainerPane::stopCrafting() { + m_containerInteractor->stopCraftingInContainer(); +} + +void ContainerPane::toggleCrafting() { + if (m_containerInteractor->openContainer()->isCrafting()) + stopCrafting(); + else + startCrafting(); +} + +void ContainerPane::clear() { + m_containerInteractor->clearContainer(); +} + +void ContainerPane::burn() { + m_containerInteractor->burnContainer(); +} + +void ContainerPane::update() { + Pane::update(); + + if (m_script) + m_script->update(m_script->updateDt()); + + m_itemBag->clearItems(); + + if (!m_containerInteractor->containerOpen()) { + dismiss(); + + } else { + auto container = m_containerInteractor->openContainer(); + + for (size_t i = 0; i < m_itemBag->size(); ++i) + m_itemBag->putItems(i, container->containerItems()[i]); + + if (container->isInteractive()) { + if (auto itemGrid = fetchChild("itemGrid")) { + itemGrid->setProgress(container->craftingProgress()); + itemGrid->updateAllItemSlots(); + } + if (auto itemGrid = fetchChild("itemGrid2")) { + itemGrid->setProgress(container->craftingProgress()); + itemGrid->updateAllItemSlots(); + } + + if (auto fuelGauge = fetchChild("fuelGauge")) { + fuelGauge->setCurrentFuelLevel(m_worldClient->getProperty("ship.fuel", 0).toUInt()); + fuelGauge->setMaxFuelLevel(m_worldClient->getProperty("ship.maxFuel", 0).toUInt()); + float totalFuelAmount = 0; + for (auto& item : container->containerItems()) { + if (item) + totalFuelAmount += item->instanceValue("fuelAmount", 0).toUInt() * item->count(); + } + fuelGauge->setPotentialFuelAmount(totalFuelAmount); + fuelGauge->setRequestedFuelAmount(0); + } + } + } +} + +} -- cgit v1.2.3