From 57665aaa9e0b64a010a6215c426ef9d4b231da30 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Wed, 19 Nov 2025 14:31:31 +0100 Subject: [PATCH] ItemDetailPage/Misc * fix "vendor in" mapper * add "fished in" mapper * move 'see-also' and 'same-model-as' tabs to the back of the tabs list --- endpoints/item/item.php | 137 ++++++++++++++++++++--------------- localization/locale_dede.php | 4 +- localization/locale_enus.php | 4 +- localization/locale_eses.php | 6 +- localization/locale_frfr.php | 4 +- localization/locale_ruru.php | 4 +- localization/locale_zhcn.php | 4 +- template/pages/item.tpl.php | 4 +- 8 files changed, 101 insertions(+), 66 deletions(-) diff --git a/endpoints/item/item.php b/endpoints/item/item.php index 34d94c1b..4a158b7b 100644 --- a/endpoints/item/item.php +++ b/endpoints/item/item.php @@ -474,6 +474,28 @@ class ItemBaseResponse extends TemplateResponse implements ICache } } + if ($idx == 15 && !$this->map) + { + $nodeIds = array_map(fn($x) => $x['id'], $tabData['data']); + $fishedIn = new GameObjectList(array(['id', $nodeIds])); + if (!$fishedIn->error) + { + // show mapper for fishing locations + if ($nodeSpawns = $fishedIn->getSpawns(SPAWNINFO_FULL, true, true, true, true)) + { + $this->map = array( + ['parent' => 'mapper-generic'], // Mapper + $nodeSpawns, // mapperData + null, // ShowOnMap + [Lang::item('fishedIn')], // foundIn + Lang::item('fishingLoc') // title + ); + foreach ($nodeSpawns as $areaId => $_) + $this->map[3][$areaId] = ZoneList::getName($areaId); + } + } + } + if ($template == 'npc' || $template == 'object') $this->addDataLoader('zones'); @@ -633,40 +655,6 @@ class ItemBaseResponse extends TemplateResponse implements ICache } } - // tab: see also - $conditions = array( - ['id', $this->typeId, '!'], - [ - 'OR', - ['name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)], - [ - 'AND', - ['class', $_class], - ['subClass', $_subClass], - ['slot', $_slot], - ['itemLevel', $_ilvl - 15, '>'], - ['itemLevel', $_ilvl + 15, '<'], - ['quality', $this->subject->getField('quality')], - ['requiredClass', $this->subject->getField('requiredClass') ?: -1] // todo: fix db data in setup and not on fetch - ] - ] - ); - - if ($_ = $this->subject->getField('itemset')) - $conditions[1][] = ['AND', ['slot', $_slot], ['itemset', $_]]; - - $saItems = new ItemList($conditions); - if (!$saItems->error) - { - $this->extendGlobalData($saItems->getJSGlobals(GLOBALINFO_SELF)); - - $this->lvTabs->addListviewTab(new Listview(array( - 'data' => $saItems->getListviewData(), - 'name' => '$LANG.tab_seealso', - 'id' => 'see-also' - ), ItemList::$brickFile)); - } - // tab: starts (quest) if ($qId = $this->subject->getField('startQuest')) { @@ -719,24 +707,6 @@ class ItemBaseResponse extends TemplateResponse implements ICache ), QuestList::$brickFile)); } - // tab: same model as - // todo (low): should also work for creatures summoned by item - if (($model = $this->subject->getField('model')) && $_slot) - { - $sameModel = new ItemList(array(['model', $model], ['id', $this->typeId, '!'], ['slot', $_slot])); - if (!$sameModel->error) - { - $this->extendGlobalData($sameModel->getJSGlobals(GLOBALINFO_SELF)); - - $this->lvTabs->addListviewTab(new Listview(array( - 'data' => $sameModel->getListviewData(ITEMINFO_MODEL), - 'name' => '$LANG.tab_samemodelas', - 'id' => 'same-model-as', - 'genericlinktype' => 'item' - ), 'genericmodel')); - } - } - // tab: sold by if (!empty($this->subject->getExtendedCost()[$this->typeId])) { @@ -748,13 +718,14 @@ class ItemBaseResponse extends TemplateResponse implements ICache if ($vendorSpawns = $soldBy->getSpawns(SPAWNINFO_FULL, true, true, true, true)) { $this->map = array( - ['parent' => 'mapper-generic'], // Mapper - $vendorSpawns, // mapperData - null, // ShowOnMap - [Lang::item('purchasedIn')] // foundIn + ['parent' => 'mapper-generic'], // Mapper + $vendorSpawns, // mapperData + null, // ShowOnMap + [Lang::item('purchasedIn')], // foundIn + Lang::item('vendorLoc') // title ); foreach ($vendorSpawns as $areaId => $_) - $this->map['extra'][$areaId] = ZoneList::getName($areaId); + $this->map[3][$areaId] = ZoneList::getName($areaId); } $sbData = $soldBy->getListviewData(); @@ -904,6 +875,58 @@ class ItemBaseResponse extends TemplateResponse implements ICache } } + // tab: see also + $conditions = array( + ['id', $this->typeId, '!'], + [ + 'OR', + ['name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)], + [ + 'AND', + ['class', $_class], + ['subClass', $_subClass], + ['slot', $_slot], + ['itemLevel', $_ilvl - 15, '>'], + ['itemLevel', $_ilvl + 15, '<'], + ['quality', $this->subject->getField('quality')], + ['requiredClass', $this->subject->getField('requiredClass') ?: -1] // todo: fix db data in setup and not on fetch + ] + ] + ); + + if ($_ = $this->subject->getField('itemset')) + $conditions[1][] = ['AND', ['slot', $_slot], ['itemset', $_]]; + + $saItems = new ItemList($conditions); + if (!$saItems->error) + { + $this->extendGlobalData($saItems->getJSGlobals(GLOBALINFO_SELF)); + + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $saItems->getListviewData(), + 'name' => '$LANG.tab_seealso', + 'id' => 'see-also' + ), ItemList::$brickFile)); + } + + // tab: same model as + // todo (low): should also work for creatures summoned by item + if (($model = $this->subject->getField('model')) && $_slot) + { + $sameModel = new ItemList(array(['model', $model], ['id', $this->typeId, '!'], ['slot', $_slot])); + if (!$sameModel->error) + { + $this->extendGlobalData($sameModel->getJSGlobals(GLOBALINFO_SELF)); + + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $sameModel->getListviewData(ITEMINFO_MODEL), + 'name' => '$LANG.tab_samemodelas', + 'id' => 'same-model-as', + 'genericlinktype' => 'item' + ), 'genericmodel')); + } + } + // tab: Shared cooldown $cdCats = []; $useSpells = []; diff --git a/localization/locale_dede.php b/localization/locale_dede.php index b7c75473..a094562b 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -2265,8 +2265,10 @@ $lang = array( 'uniqueEquipped'=> ["Einzigartig anlegbar", null, "Einzigartig angelegt: %s (%d)"], 'speed' => "Tempo", 'dps' => "(%.1f Schaden pro Sekunde)", - 'vendorIn' => "Händlerstandpunkte", + 'vendorLoc' => "Händlerstandpunkte", 'purchasedIn' => "Dieser Gegenstand kann gekauft werden in", + 'fishingLoc' => "Angelplätze", + 'fishedIn' => "Dieser Gegenstand kann geangelt werden in", 'duration' => array( // ITEM_DURATION_* '', "Dauer: %d Sek.", diff --git a/localization/locale_enus.php b/localization/locale_enus.php index ae57cd91..42d18fd6 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -2265,8 +2265,10 @@ $lang = array( 'uniqueEquipped'=> ["Unique-Equipped", null, "Unique-Equipped: %s (%d)"], // ITEM_UNIQUE_EQUIPPABLE, null, ITEM_LIMIT_CATEGORY_MULTIPLE 'speed' => "Speed", // SPEED 'dps' => "(%.1f damage per second)", // DPS_TEMPLATE - 'vendorIn' => "Vendor Locations", + 'vendorLoc' => "Vendor Locations", 'purchasedIn' => "This item can be purchased in", + 'fishingLoc' => "Fishing Locations", + 'fishedIn' => "This item can be fished in", 'duration' => array( // ITEM_DURATION_* '', "Duration: %d sec", diff --git a/localization/locale_eses.php b/localization/locale_eses.php index 67d5486d..d3951955 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -2265,8 +2265,10 @@ $lang = array( 'uniqueEquipped'=> ["Único-Equipado", null, "Único-Equipado: %s (%d)"], 'speed' => "Veloc.", 'dps' => "(%.1f daño por segundo)", - 'vendorIn' => "Ubicación de Vendedores", - 'purchasedIn' => "[This item can be purchased in]", + 'vendorLoc' => "Ubicación de Vendedores", + 'purchasedIn' => "Este objeto se puede comprar en", + 'fishingLoc' => "Lugares de pesca", + 'fishedIn' => "Este objeto se puede pescar en", 'duration' => array( '', "Duración: %d s", diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index 9c98f2ed..d0247e71 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -2265,8 +2265,10 @@ $lang = array( 'uniqueEquipped'=> ["Unique - Equipé", null, "Unique - Equipé: %s (%d)"], // ITEM_UNIQUE_EQUIPPABLE, null, ITEM_LIMIT_CATEGORY_MULTIPLE 'speed' => "Vitesse", 'dps' => "(%.1f dégâts par seconde)", - 'vendorIn' => "Lieux de vente", + 'vendorLoc' => "Lieux de vente", 'purchasedIn' => "Cet objet peut être acheté dans", + 'fishingLoc' => "Lieux de pêche", + 'fishedIn' => "Cet objet peut être pêché dans", 'duration' => array( '', "Durée : %d sec", diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index 383dd2ee..00622880 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -2265,8 +2265,10 @@ $lang = array( 'uniqueEquipped'=> ["Уникальный использующийся", null, "Уникальный использующийся предмет: %s (%d)"], 'speed' => "Скорость", 'dps' => "(%.1f ед. урона в секунду)", - 'vendorIn' => "Расположение торговца", + 'vendorLoc' => "Расположение торговца", 'purchasedIn' => "Этот предмет приобретается в", + 'fishingLoc' => "Места рыбной ловли", + 'fishedIn' => "Этот предмет вылавливается в", 'duration' => array( '', "Срок действия: %d |4секунда:секунды:секунд;", diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index fbc1908e..f3e5ac65 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -2265,8 +2265,10 @@ $lang = array( 'uniqueEquipped'=> ["装备唯一", null, "装备唯一:%s (%d)"], 'speed' => "速度", 'dps' => "(每秒伤害%.1f)", - 'vendorIn' => "[Vendor Locations]", + 'vendorLoc' => "[Vendor Locations]", 'purchasedIn' => "[This item can be purchased in]", + 'fishingLoc' => "钓鱼地点", + 'fishedIn' => "此物品位于", 'duration' => array( '', "持续时间:%d秒", diff --git a/template/pages/item.tpl.php b/template/pages/item.tpl.php index f519205a..e4314d4d 100644 --- a/template/pages/item.tpl.php +++ b/template/pages/item.tpl.php @@ -34,8 +34,8 @@ endif; $this->brick('markup', ['markup' => $this->article]); -if (isset($this->map)): - echo "

".Lang::item('vendorIn')."

\n"; +if ($this->map): + echo "

".$this->map[4]."

\n"; $this->brick('mapper'); endif;