#include "StarItemTooltip.hpp" #include "StarGuiReader.hpp" #include "StarPane.hpp" #include "StarListWidget.hpp" #include "StarLabelWidget.hpp" #include "StarRoot.hpp" #include "StarStoredFunctions.hpp" #include "StarObjectItem.hpp" #include "StarImageWidget.hpp" #include "StarItemSlotWidget.hpp" #include "StarPreviewableItem.hpp" #include "StarFireableItem.hpp" #include "StarStatusEffectItem.hpp" #include "StarObject.hpp" #include "StarLogging.hpp" #include "StarAssets.hpp" #include "StarObjectDatabase.hpp" #include "StarStatusEffectDatabase.hpp" #include "StarJsonExtra.hpp" namespace Star { PanePtr ItemTooltipBuilder::buildItemTooltip(ItemPtr const& item, PlayerPtr const& viewer) { if (!item) { return {}; } else { PanePtr tooltip = make_shared(); tooltip->removeAllChildren(); String title; String subTitle; String tooltipKind = item->tooltipKind(); if (tooltipKind.empty()) tooltipKind = "base"; if (!tooltipKind.endsWith(".tooltip")) tooltipKind = "/interface/tooltips/" + tooltipKind + ".tooltip"; buildItemDescriptionInner(tooltip, item, tooltipKind, title, subTitle, viewer); auto titleIcon = make_shared(item, "/interface/inventory/portrait.png"); titleIcon->setBackingImageAffinity(true, true); titleIcon->showRarity(false); tooltip->setTitle(titleIcon, title, subTitle); return tooltip; } } void ItemTooltipBuilder::buildItemDescription(WidgetPtr const& container, ItemPtr const& item) { String tooltipKind = item->tooltipKind(); if (tooltipKind.empty()) tooltipKind = "base"; if (!tooltipKind.endsWith(".itemdescription")) tooltipKind = "/interface/itemdescriptions/" + tooltipKind + ".itemdescription"; String title; String subTitle; buildItemDescriptionInner(container, item, tooltipKind, title, subTitle); } String categoryDisplayName(String const& category) { Json categories = Root::singleton().assets()->json("/items/categories.config:labels"); return categories.getString(category, category); } void ItemTooltipBuilder::buildItemDescriptionInner( WidgetPtr const& container, ItemPtr const& item, String const& tooltipKind, String& title, String& subTitle, PlayerPtr const& viewer) { GuiReader reader; auto& root = Root::singleton(); title = item->friendlyName(); subTitle = categoryDisplayName(item->category()); String description = item->description(); reader.construct(root.assets()->json(tooltipKind), container.get()); if (container->containsChild("icon")) container->fetchChild("icon")->setItem(item); container->setLabel("nameLabel", item->name()); container->setLabel("countLabel", toString(item->count())); container->setLabel("rarityLabel", RarityNames.getRight(item->rarity()).titleCase()); if (item->twoHanded()) container->setLabel("handednessLabel", "2-Handed"); else container->setLabel("handednessLabel", "1-Handed"); container->setLabel("countLabel", toString(item->instanceValue("fuelAmount", 0).toUInt() * item->count())); container->setLabel("priceLabel", toString((int)item->price())); if (auto objectItem = as(item)) { try { auto object = Root::singleton().objectDatabase()->createObject(objectItem->objectName(), objectItem->objectParameters()); if (container->containsChild("objectImage")) { auto drawables = object->cursorHintDrawables(); container->fetchChild("objectImage")->setDrawables(drawables); } if (objectItem->tooltipKind() == "container") container->setLabel("slotCountLabel", strf("Holds {} Items", objectItem->instanceValue("slotCount"))); title = object->shortDescription(); subTitle = categoryDisplayName(object->category()); description = object->description(); } catch (StarException const& e) { Logger::error("Failed to instantiate object for object item tooltip. {}", outputException(e, false)); } } else { if (container->containsChild("objectImage")) { if (auto previewable = as(item)) { container->fetchChild("objectImage")->setDrawables(previewable->preview(viewer)); } else { auto drawables = item->iconDrawables(); container->fetchChild("objectImage")->setDrawables(drawables); } } } auto tooltipFields = item->instanceValue("tooltipFields", JsonObject()); for (auto const& pair : tooltipFields.iterateObject()) { if (pair.first.equalsIgnoreCase("subtitle")) subTitle = pair.second.toString(); if (pair.first.endsWith("Label")) container->setLabel(pair.first, pair.second.type() == Json::Type::String ? pair.second.toString() : toString(pair.second)); if (pair.first.endsWith("Image") && container->containsChild(pair.first)) { if (pair.second.isType(Json::Type::String)) container->fetchChild(pair.first)->setImage(pair.second.toString()); else container->fetchChild(pair.first)->setDrawables(pair.second.toArray().transformed(construct())); } } if (auto fireable = as(item)) { container->setLabel("cooldownTimeLabel", strf("{:.2f}", fireable->cooldownTime())); container->setLabel("windupTimeLabel", strf("{:.2f}", fireable->windupTime())); container->setLabel("speedLabel", strf("{:.2f}", 1.0f / (fireable->cooldownTime() + fireable->windupTime()))); } if (container->containsChild("largeImage")) { container->fetchChild("largeImage")->setImage(item->largeImage()); } container->setLabel("descriptionLabel", description); container->setLabel("friendlyNameLabel", title); if (container->containsChild("statusList")) { auto statusList = container->fetchChild("statusList"); if (auto statusEffects = as(item)) { for (auto effect : statusEffects->statusEffects()) describePersistentEffect(statusList, effect); } } if (item->instanceValue("acceptsAugmentType", false)) { if (auto augmentLabel = container->fetchChild("augmentNameLabel")) { if (auto currentAugment = item->instanceValue("currentAugment")) { container->setLabel("augmentNameLabel", currentAugment.getString("displayName", "???")); if (auto augmentIcon = container->fetchChild("augmentIconImage")) augmentIcon->setImage(currentAugment.getString("displayIcon", "")); augmentLabel->setColor(Color::White); } else { container->setLabel("augmentNameLabel", "NO AUGMENT INSERTED"); if (auto augmentIcon = container->fetchChild("augmentIconImage")) augmentIcon->setImage(""); augmentLabel->setColor(Color::Gray); } } } container->setLabel("title", title); container->setLabel("subTitle", subTitle); if (container->containsChild("titleIcon")) { auto titleIcon = container->fetchChild("titleIcon"); titleIcon->setItem(item); } } void ItemTooltipBuilder::describePersistentEffect( ListWidgetPtr const& container, PersistentStatusEffect const& effect) { if (auto uniqueStatusEffect = effect.ptr()) { auto statusEffectDatabase = Root::singleton().statusEffectDatabase(); auto effectConfig = statusEffectDatabase->uniqueEffectConfig(*uniqueStatusEffect); if (effectConfig.icon) { auto listItem = container->addItem(); listItem->setLabel("statusLabel", effectConfig.label); listItem->fetchChild("statusImage")->setImage(*effectConfig.icon); } } else if (auto modifierEffect = effect.ptr()) { auto statsConfig = Root::singleton().assets()->json("/interface/stats/stats.config"); if (auto baseMultiplier = modifierEffect->ptr()) { if (statsConfig.contains(baseMultiplier->statName)) { auto listItem = container->addItem(); listItem->fetchChild("statusImage") ->setImage(statsConfig.get(baseMultiplier->statName).getString("icon")); listItem->setLabel("statusLabel", strf("{:.1f}%", (baseMultiplier->baseMultiplier - 1) * 100)); } } else if (auto valueModifier = modifierEffect->ptr()) { if (statsConfig.contains(valueModifier->statName)) { auto listItem = container->addItem(); listItem->fetchChild("statusImage") ->setImage(statsConfig.get(valueModifier->statName).getString("icon")); listItem->setLabel("statusLabel", strf("{}{}", valueModifier->value < 0 ? "-" : "", valueModifier->value)); } } else if (auto effectiveMultiplier = modifierEffect->ptr()) { if (statsConfig.contains(effectiveMultiplier->statName)) { auto listItem = container->addItem(); listItem->fetchChild("statusImage") ->setImage(statsConfig.get(effectiveMultiplier->statName).getString("icon")); listItem->setLabel("statusLabel", strf("{:.1f}%", (effectiveMultiplier->effectiveMultiplier - 1) * 100)); } } } } }