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
This commit is contained in:
Sarjuuk
2025-11-19 14:31:31 +01:00
parent 4cb544182d
commit 57665aaa9e
8 changed files with 101 additions and 66 deletions

View File

@@ -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 = [];

View File

@@ -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.",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -2265,8 +2265,10 @@ $lang = array(
'uniqueEquipped'=> ["Уникальный использующийся", null, "Уникальный использующийся предмет: %s (%d)"],
'speed' => "Скорость",
'dps' => "(%.1f ед. урона в секунду)",
'vendorIn' => "Расположение торговца",
'vendorLoc' => "Расположение торговца",
'purchasedIn' => "Этот предмет приобретается в",
'fishingLoc' => "Места рыбной ловли",
'fishedIn' => "Этот предмет вылавливается в",
'duration' => array(
'',
"Срок действия: %d |4секунда:секунды:секунд;",

View File

@@ -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秒",

View File

@@ -34,8 +34,8 @@ endif;
$this->brick('markup', ['markup' => $this->article]);
if (isset($this->map)):
echo " <h3>".Lang::item('vendorIn')."</h3>\n";
if ($this->map):
echo " <h3>".$this->map[4]."</h3>\n";
$this->brick('mapper');
endif;