diff --git a/pages/item.php b/endpoints/item/item.php
similarity index 63%
rename from pages/item.php
rename to endpoints/item/item.php
index ad21cc58..5d81b9b2 100644
--- a/pages/item.php
+++ b/endpoints/item/item.php
@@ -6,142 +6,80 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-// menuId 0: Item g_initPath()
-// tabId 0: Database g_initHeader()
-class ItemPage extends genericPage
+class ItemBaseResponse extends TemplateResponse implements ICache
{
- use TrDetailPage;
+ use TrDetailPage, TrCache;
- protected $pageText = [];
- protected $tooltip = null;
- protected $unavailable = false;
- protected $subItems = [];
+ protected int $cacheType = CACHE_TYPE_PAGE;
- protected $type = Type::ITEM;
- protected $typeId = 0;
- protected $tpl = 'item';
- protected $path = [0, 0];
- protected $tabId = 0;
- protected $mode = CACHE_TYPE_PAGE;
- protected $enhancedTT = [];
- protected $scripts = array(
+ protected string $template = 'item';
+ protected string $pageName = 'item';
+ protected ?int $activeTab = parent::TAB_DATABASE;
+ protected array $breadcrumb = [0, 0];
+
+ protected array $scripts = array(
[SC_JS_FILE, 'js/swfobject.js'],
[SC_JS_FILE, 'js/profile.js'],
[SC_JS_FILE, 'js/filters.js']
);
- protected $_get = array(
- 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\Locale::tryFromDomain'],
- 'rand' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\GenericPage::checkInt'],
- 'ench' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\GenericPage::checkInt'],
- 'gems' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\GenericPage::checkIntArray'],
- 'sock' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\GenericPage::checkEmptySet']
- );
+ public int $type = Type::ITEM;
+ public int $typeId = 0;
+ public bool $unavailable = false;
+ public ?Book $book = null;
+ public ?array $subItems = null;
+ public array $tooltip = [];
- private $powerTpl = '$WowheadPower.registerItem(%s, %d, %s);';
+ private ItemList $subject;
- public function __construct($pageCall, $param)
+ public function __construct(string $id)
{
- parent::__construct($pageCall, $param);
+ parent::__construct($id);
- $conditions = [['i.id', intVal($param)]];
+ $this->typeId = intVal($id);
+ $this->contribute = Type::getClassAttrib($this->type, 'contribute') ?? CONTRIBUTE_NONE;
+ }
- $this->typeId = intVal($param);
-
- if ($this->mode == CACHE_TYPE_TOOLTIP)
- {
- // temp locale
- if ($this->_get['domain'])
- Lang::load($this->_get['domain']);
-
- if ($this->_get['rand'])
- $this->enhancedTT['r'] = $this->_get['rand'];
- if ($this->_get['ench'])
- $this->enhancedTT['e'] = $this->_get['ench'];
- if ($this->_get['gems'])
- $this->enhancedTT['g'] = $this->_get['gems'];
- if ($this->_get['sock'])
- $this->enhancedTT['s'] = '';
- }
- else if ($this->mode == CACHE_TYPE_XML)
- {
- // temp locale
- if ($this->_get['domain'])
- Lang::load($this->_get['domain']);
-
- // allow lookup by name for xml
- if (!is_numeric($param))
- $conditions = [['name_loc'.Lang::getLocale()->value, urldecode($param)]];
- }
-
- $this->subject = new ItemList($conditions);
+ protected function generate() : void
+ {
+ $this->subject = new ItemList(array(['i.id', $this->typeId]));
if ($this->subject->error)
- $this->notFound(Lang::game('item'), Lang::item('notFound'));
+ $this->generateNotFound(Lang::game('item'), Lang::item('notFound'));
- if (!is_numeric($param))
- $this->typeId = $this->subject->id;
+ $jsg = $this->subject->getJSGlobals(GLOBALINFO_EXTRA | GLOBALINFO_SELF, $extra);
+ $this->extendGlobalData($jsg, $extra);
- $this->name = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_HTML);
+ $this->h1 = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_HTML);
- if ($this->mode == CACHE_TYPE_PAGE)
- {
- $jsg = $this->subject->getJSGlobals(GLOBALINFO_EXTRA | GLOBALINFO_SELF, $extra);
- $this->extendGlobalData($jsg, $extra);
- }
- }
-
- protected function generatePath()
- {
- $_class = $this->subject->getField('class');
- $_subClass = $this->subject->getField('subClass');
-
- if (in_array($_class, [ITEM_CLASS_REAGENT, ITEM_CLASS_GENERIC, ITEM_CLASS_PERMANENT]))
- {
- $this->path[] = ITEM_CLASS_MISC; // misc.
-
- if ($_class == ITEM_CLASS_REAGENT) // reagent
- $this->path[] = 1;
- else // other
- $this->path[] = 4;
- }
- else
- {
- $this->path[] = $_class;
-
- if (!in_array($_class, [ITEM_CLASS_MONEY, ITEM_CLASS_QUEST, ITEM_CLASS_KEY]))
- $this->path[] = $_subClass;
-
- if ($_class == ITEM_CLASS_ARMOR && in_array($_subClass, [1, 2, 3, 4]))
- {
- if ($_ = $this->subject->getField('slot'));
- $this->path[] = $_;
- }
- else if (($_class == ITEM_CLASS_CONSUMABLE && $_subClass == 2) || $_class == ITEM_CLASS_GLYPH)
- $this->path[] = $this->subject->getField('subSubClass');
- }
- }
-
- protected function generateTitle()
- {
- array_unshift($this->title, Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW), Util::ucFirst(Lang::game('item')));
- }
-
- protected function generateContent()
- {
- $this->addScript([SC_JS_FILE, '?data=weight-presets.zones']);
+ $this->gPageInfo += array(
+ 'type' => $this->type,
+ 'typeId' => $this->typeId,
+ 'name' => $this->h1
+ );
$_flags = $this->subject->getField('flags');
$_slot = $this->subject->getField('slot');
$_class = $this->subject->getField('class');
$_subClass = $this->subject->getField('subClass');
$_bagFamily = $this->subject->getField('bagFamily');
- $_model = $this->subject->getField('displayId');
+ $_displayId = $this->subject->getField('displayId');
$_ilvl = $this->subject->getField('itemLevel');
- $_visSlots = array(
- INVTYPE_HEAD, INVTYPE_SHOULDERS, INVTYPE_BODY, INVTYPE_CHEST, INVTYPE_WAIST, INVTYPE_LEGS, INVTYPE_FEET, INVTYPE_WRISTS,
- INVTYPE_HANDS, INVTYPE_WEAPON, INVTYPE_SHIELD, INVTYPE_RANGED, INVTYPE_CLOAK, INVTYPE_2HWEAPON, INVTYPE_TABARD, INVTYPE_ROBE,
- INVTYPE_WEAPONMAINHAND, INVTYPE_WEAPONOFFHAND, INVTYPE_HOLDABLE, INVTYPE_THROWN, INVTYPE_RANGEDRIGHT
- );
+
+
+ /*************/
+ /* Menu Path */
+ /*************/
+
+ if ($path = $this->followBreadcrumbPath())
+ array_push($this->breadcrumb, ...$path);
+
+
+ /**************/
+ /* Page Title */
+ /**************/
+
+ array_unshift($this->title, Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW), Util::ucFirst(Lang::game('item')));
+
/***********/
/* Infobox */
@@ -159,8 +97,12 @@ class ItemPage extends genericPage
// side
if ($si = $this->subject->json[$this->typeId]['side'])
- if ($si != 3)
- $infobox[] = Lang::main('side').Lang::main('colon').'[span class=icon-'.($si == 1 ? 'alliance' : 'horde').']'.Lang::game('si', $si).'[/span]';
+ $infobox[] = Lang::main('side') . match ($si)
+ {
+ SIDE_ALLIANCE => '[span class=icon-alliance]'.Lang::game('si', SIDE_ALLIANCE).'[/span]',
+ SIDE_HORDE => '[span class=icon-horde]'.Lang::game('si', SIDE_HORDE).'[/span]',
+ SIDE_BOTH => Lang::game('si', SIDE_BOTH)
+ };
// icon
if ($_ = $this->subject->getField('iconId'))
@@ -188,20 +130,20 @@ class ItemPage extends genericPage
}
if ($hasUse)
- $infobox[] = isset($tt) ? $tt : '[tooltip=tooltip_notconsumedonuse]'.Lang::item('nonConsumable').'[/tooltip]';
+ $infobox[] = $tt ?? '[tooltip=tooltip_notconsumedonuse]'.Lang::item('nonConsumable').'[/tooltip]';
}
// related holiday
if ($eId = $this->subject->getField('eventId'))
{
$this->extendGlobalIds(Type::WORLDEVENT, $eId);
- $infobox[] = Lang::game('eventShort').Lang::main('colon').'[event='.$eId.']';
+ $infobox[] = Lang::game('eventShort', ['[event='.$eId.']']);
}
// tool
if ($tId = $this->subject->getField('totemCategory'))
- if ($tName = DB::Aowow()->selectRow('SELECT * FROM ?_totemcategory WHERE id = ?d', $tId))
- $infobox[] = Lang::item('tool').Lang::main('colon').'[url=?items&filter=cr=91;crs='.$tId.';crv=0]'.Util::localizedString($tName, 'name').'[/url]';
+ if ($tName = DB::Aowow()->selectRow('SELECT * FROM ?_totemcategory WHERE `id` = ?d', $tId))
+ $infobox[] = Lang::item('tool').'[url=?items&filter=cr=91;crs='.$tId.';crv=0]'.Util::localizedString($tName, 'name').'[/url]';
// extendedCost
if (!empty($this->subject->getExtendedCost([], $_reqRating)[$this->subject->id]))
@@ -265,17 +207,17 @@ class ItemPage extends genericPage
else
$cost = '[money';
- $stringify = function(&$v) use ($divisor) { return $v = $v[0] . ',' . ($v[1] / $divisor); };
+ $stringify = fn(&$x) => $x = $x[0] . ',' . ($x[1] / $divisor);
if ($tokens)
{
- array_walk($tokens, $stringify, $divisor);
+ array_walk($tokens, $stringify);
$cost .= ' items='.implode(',', $tokens);
}
if ($currency)
{
- array_walk($currency, $stringify, $divisor);
+ array_walk($currency, $stringify);
$cost .= ' currency='.implode(',', $currency);
}
@@ -304,7 +246,7 @@ class ItemPage extends genericPage
// repair cost
if ($_ = $this->subject->getField('repairPrice'))
- $infobox[] = Lang::item('repairCost').Lang::main('colon').'[money='.$_.']';
+ $infobox[] = Lang::item('repairCost').'[money='.$_.']';
// avg auction buyout
if (in_array($this->subject->getField('bonding'), [0, 2, 3]))
@@ -314,7 +256,7 @@ class ItemPage extends genericPage
// avg money contained
if ($_flags & ITEM_FLAG_OPENABLE)
if ($_ = intVal(($this->subject->getField('minMoneyLoot') + $this->subject->getField('maxMoneyLoot')) / 2))
- $infobox[] = Lang::item('worth').Lang::main('colon').'[tooltip=tooltip_avgmoneycontained][money='.$_.'][/tooltip]';
+ $infobox[] = Lang::item('worth').'[tooltip=tooltip_avgmoneycontained][money='.$_.'][/tooltip]';
// if it goes into a slot it may be disenchanted
if ($_slot && $_class != ITEM_CLASS_CONTAINER)
@@ -375,28 +317,31 @@ class ItemPage extends genericPage
if ($_bagFamily & 0x0100)
$infobox[] = Lang::item('atKeyring');
+ if ($infobox)
+ $this->infobox = new InfoboxMarkup($infobox, ['allow' => Markup::CLASS_STAFF, 'dbpage' => true], 'infobox-contents0');
+
+
/****************/
/* Main Content */
/****************/
- $_cu = in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) || $this->subject->getField('gemEnchantmentId');
+ if ($canBeWeighted = in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR, ITEM_CLASS_GEM]))
+ $this->addDataLoader('weight-presets');
// pageText
- if ($this->pageText = Game::getBook($this->subject->getField('pageTextId')))
+ if ($this->book = Game::getBook($this->subject->getField('pageTextId')))
$this->addScript(
[SC_JS_FILE, 'js/Book.js'],
[SC_CSS_FILE, 'css/Book.css']
);
- $this->headIcons = [$this->subject->getField('iconString', true, true), $this->subject->getField('stackable')];
- $this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
- $this->tooltip = $this->subject->renderTooltip(true);
+ $this->tooltip = [$this->subject->getField('iconString'), $this->subject->getField('stackable'), false];
$this->redButtons = array(
BUTTON_WOWHEAD => true,
- BUTTON_VIEW3D => in_array($_slot, $_visSlots) && $_model ? ['displayId' => $this->subject->getField('displayId'), 'slot' => $_slot, 'type' => Type::ITEM, 'typeId' => $this->typeId] : false,
- BUTTON_COMPARE => $_cu,
+ BUTTON_VIEW3D => $this->subject->isDisplayable() ? ['displayId' => $_displayId, 'slot' => $_slot, 'type' => Type::ITEM, 'typeId' => $this->typeId] : false,
+ BUTTON_COMPARE => $canBeWeighted,
BUTTON_EQUIP => in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]),
- BUTTON_UPGRADE => ($_cu ? ['class' => $_class, 'slot' => $_slot] : false),
+ BUTTON_UPGRADE => $canBeWeighted ? ['class' => $_class, 'slot' => $_slot] : false,
BUTTON_LINKS => array(
'linkColor' => 'ff'.Game::$rarityColorStings[$this->subject->getField('quality')],
'linkId' => 'item:'.$this->typeId.':0:0:0:0:0:0:0:0',
@@ -413,7 +358,7 @@ class ItemPage extends genericPage
$this->subject->initSubItems();
if (!empty($this->subject->subItems[$this->typeId]))
{
- uaSort($this->subject->subItems[$this->typeId], function($a, $b) { return strcmp($a['name'], $b['name']); });
+ uaSort($this->subject->subItems[$this->typeId], fn($a, $b) => $a['name'] <=> $b['name']);
$this->subItems = array(
'data' => array_values($this->subject->subItems[$this->typeId]),
'randIds' => array_keys($this->subject->subItems[$this->typeId]),
@@ -440,29 +385,31 @@ class ItemPage extends genericPage
}
// factionchange-equivalent
- if ($pendant = DB::World()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_items WHERE alliance_id = ?d OR horde_id = ?d', $this->typeId, $this->typeId, $this->typeId))
+ if ($pendant = DB::World()->selectCell('SELECT IF(`horde_id` = ?d, `alliance_id`, -`horde_id`) FROM player_factionchange_items WHERE `alliance_id` = ?d OR `horde_id` = ?d', $this->typeId, $this->typeId, $this->typeId))
{
$altItem = new ItemList(array(['id', abs($pendant)]));
if (!$altItem->error)
{
- $this->transfer = sprintf(
- Lang::item('_transfer'),
+ $this->transfer = Lang::item('_transfer', [
$altItem->id,
$altItem->getField('quality'),
- $altItem->getField('iconString', true, true),
+ $altItem->getField('iconString'),
$altItem->getField('name', true),
$pendant > 0 ? 'alliance' : 'horde',
- $pendant > 0 ? Lang::game('si', 1) : Lang::game('si', 2)
- );
+ $pendant > 0 ? Lang::game('si', SIDE_ALLIANCE) : Lang::game('si', SIDE_HORDE)
+ ]);
}
}
+
/**************/
/* Extra Tabs */
/**************/
+ $this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsRelated', true);
+
// tab: createdBy (perfect item specific)
- if ($perfItem = DB::World()->select('SELECT *, spellId AS ARRAY_KEY FROM skill_perfect_item_template WHERE perfectItemType = ?d', $this->typeId))
+ if ($perfItem = DB::World()->select('SELECT *, `spellId` AS ARRAY_KEY FROM skill_perfect_item_template WHERE `perfectItemType` = ?d', $this->typeId))
{
$perfSpells = new SpellList(array(['id', array_column($perfItem, 'spellId')]));
if (!$perfSpells->error)
@@ -477,12 +424,12 @@ class ItemPage extends genericPage
$this->extendGlobalIDs(Type::SPELL, $perfItem[$sId]['requiredSpecialization']);
}
- $this->lvTabs[] = [SpellList::$brickFile, array(
- 'data' => array_values($lvData),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $lvData,
'name' => '$LANG.tab_createdby',
'id' => 'created-by', // should by exclusive with created-by from spell_loot
'extraCols' => ['$Listview.extraCols.percent', '$Listview.extraCols.condition']
- )];
+ ), SpellList::$brickFile));
}
}
@@ -493,7 +440,7 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($lootTabs->jsGlobals);
- foreach ($lootTabs->iterate() as $idx => [$file, $tabData])
+ foreach ($lootTabs->iterate() as $idx => [$template, $tabData])
{
if (!$tabData['data'])
continue;
@@ -518,7 +465,10 @@ class ItemPage extends genericPage
}
}
- $this->lvTabs[] = [$file, $tabData];
+ if ($template == 'npc' || $template == 'object')
+ $this->addDataLoader('zones');
+
+ $this->lvTabs->addListviewTab(new Listview($tabData, $template));
}
}
@@ -539,7 +489,7 @@ class ItemPage extends genericPage
$extraCols = array_merge($extraCols, $lootTab->extraCols);
$tabData = array(
- 'data' => array_values($lootTab->getResult()),
+ 'data' => $lootTab->getResult(),
'name' => $tabName,
'id' => $tabId,
);
@@ -550,7 +500,7 @@ class ItemPage extends genericPage
if ($hiddenCols)
$tabData['hiddenCols'] = array_unique($hiddenCols);
- $this->lvTabs[] = [ItemList::$brickFile, $tabData];
+ $this->lvTabs->addListviewTab(new Listview($tabData, ItemList::$brickFile));
}
}
@@ -566,12 +516,12 @@ class ItemPage extends genericPage
if (!$contains->hasSetFields('slot'))
$hCols[] = 'slot';
- $this->lvTabs[] = [ItemList::$brickFile, array(
- 'data' => array_values($contains->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $contains->getListviewData(),
'name' => '$LANG.tab_cancontain',
'id' => 'can-contain',
'hiddenCols' => $hCols
- )];
+ ), ItemList::$brickFile));
}
}
@@ -583,12 +533,12 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($contains->getJSGlobals(GLOBALINFO_SELF));
- $this->lvTabs[] = [ItemList::$brickFile, array(
- 'data' => array_values($contains->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $contains->getListviewData(),
'name' => '$LANG.tab_canbeplacedin',
'id' => 'can-be-placed-in',
'hiddenCols' => ['side']
- )];
+ ), ItemList::$brickFile));
}
}
@@ -604,7 +554,7 @@ class ItemPage extends genericPage
$this->extendGlobalData($criteriaOf->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
$tabData = array(
- 'data' => array_values($criteriaOf->getListviewData()),
+ 'data' => $criteriaOf->getListviewData(),
'name' => '$LANG.tab_criteriaof',
'id' => 'criteria-of',
'visibleCols' => ['category']
@@ -613,7 +563,7 @@ class ItemPage extends genericPage
if (!$criteriaOf->hasSetFields('reward_loc0'))
$tabData['hiddenCols'] = ['rewards'];
- $this->lvTabs[] = [AchievementList::$brickFile, $tabData];
+ $this->lvTabs->addListviewTab(new Listview($tabData, AchievementList::$brickFile));
}
// tab: reagent for
@@ -628,19 +578,19 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($reagent->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
- $this->lvTabs[] = [SpellList::$brickFile, array(
- 'data' => array_values($reagent->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $reagent->getListviewData(),
'name' => '$LANG.tab_reagentfor',
'id' => 'reagent-for',
'visibleCols' => ['reagents']
- )];
+ ), SpellList::$brickFile));
}
- // tab: unlocks (object or item)
+ // tab: unlocks (object or item) - LOCK_TYPE_ITEM: 1
$lockIds = DB::Aowow()->selectCol(
- 'SELECT id FROM ?_lock WHERE (type1 = 1 AND properties1 = ?d) OR
- (type2 = 1 AND properties2 = ?d) OR (type3 = 1 AND properties3 = ?d) OR
- (type4 = 1 AND properties4 = ?d) OR (type5 = 1 AND properties5 = ?d)',
+ 'SELECT `id` FROM ?_lock WHERE (`type1` = 1 AND `properties1` = ?d) OR
+ (`type2` = 1 AND `properties2` = ?d) OR (`type3` = 1 AND `properties3` = ?d) OR
+ (`type4` = 1 AND `properties4` = ?d) OR (`type5` = 1 AND `properties5` = ?d)',
$this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId
);
@@ -650,11 +600,12 @@ class ItemPage extends genericPage
$lockedObj = new GameObjectList(array(['lockId', $lockIds]));
if (!$lockedObj->error)
{
- $this->lvTabs[] = [GameObjectList::$brickFile, array(
- 'data' => array_values($lockedObj->getListviewData()),
+ $this->addDataLoader('zones');
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $lockedObj->getListviewData(),
'name' => '$LANG.tab_unlocks',
- 'id' => 'unlocks-object'
- )];
+ 'id' => 'unlocks-object',
+ ), GameObjectList::$brickFile));
}
// items (generally unused. It's the spell on the item, that unlocks stuff)
@@ -663,11 +614,11 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($lockedItm->getJSGlobals(GLOBALINFO_SELF));
- $this->lvTabs[] = [ItemList::$brickFile, array(
- 'data' => array_values($lockedItm->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $lockedItm->getListviewData(),
'name' => '$LANG.tab_unlocks',
'id' => 'unlocks-item'
- )];
+ ), ItemList::$brickFile));
}
}
@@ -698,11 +649,11 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($saItems->getJSGlobals(GLOBALINFO_SELF));
- $this->lvTabs[] = [ItemList::$brickFile, array(
- 'data' => array_values($saItems->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $saItems->getListviewData(),
'name' => '$LANG.tab_seealso',
'id' => 'see-also'
- )];
+ ), ItemList::$brickFile));
}
// tab: starts (quest)
@@ -713,11 +664,11 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($starts->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
- $this->lvTabs[] = [QuestList::$brickFile, array(
- 'data' => array_values($starts->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $starts->getListviewData(),
'name' => '$LANG.tab_starts',
'id' => 'starts-quest'
- )];
+ ), QuestList::$brickFile));
}
}
@@ -732,11 +683,11 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($objective->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
- $this->lvTabs[] = [QuestList::$brickFile, array(
- 'data' => array_values($objective->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $objective->getListviewData(),
'name' => '$LANG.tab_objectiveof',
'id' => 'objective-of-quest'
- )];
+ ), QuestList::$brickFile));
}
// tab: provided for (quest)
@@ -750,11 +701,11 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($provided->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
- $this->lvTabs[] = [QuestList::$brickFile, array(
- 'data' => array_values($provided->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $provided->getListviewData(),
'name' => '$LANG.tab_providedfor',
'id' => 'provided-for-quest'
- )];
+ ), QuestList::$brickFile));
}
// tab: same model as
@@ -766,12 +717,12 @@ class ItemPage extends genericPage
{
$this->extendGlobalData($sameModel->getJSGlobals(GLOBALINFO_SELF));
- $this->lvTabs[] = ['genericmodel', array(
- 'data' => array_values($sameModel->getListviewData(ITEMINFO_MODEL)),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $sameModel->getListviewData(ITEMINFO_MODEL),
'name' => '$LANG.tab_samemodelas',
'id' => 'same-model-as',
'genericlinktype' => 'item'
- )];
+ ), 'genericmodel'));
}
}
@@ -785,7 +736,12 @@ class ItemPage extends genericPage
// show mapper for vendors
if ($vendorSpawns = $soldBy->getSpawns(SPAWNINFO_FULL, true, true, true, true))
{
- $this->map = ['data' => ['parent' => 'mapper-generic'], 'mapperData' => &$vendorSpawns, 'foundIn' => Lang::item('purchasedIn')];
+ $this->map = array(
+ ['parent' => 'mapper-generic'], // Mapper
+ $vendorSpawns, // mapperData
+ null, // ShowOnMap
+ [Lang::item('purchasedIn')] // foundIn
+ );
foreach ($vendorSpawns as $areaId => $_)
$this->map['extra'][$areaId] = ZoneList::getName($areaId);
}
@@ -839,13 +795,14 @@ class ItemPage extends genericPage
if ($cnd->toListviewColumn($sbData, $extraCols, 'id', $this->typeId))
$this->extendGlobalData($cnd->getJsGlobals());
- $this->lvTabs[] = [CreatureList::$brickFile, array(
- 'data' => array_values($sbData),
+ $this->addDataLoader('zones');
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $sbData,
'name' => '$LANG.tab_soldby',
'id' => 'sold-by-npc',
'extraCols' => $extraCols,
'hiddenCols' => ['level', 'type']
- )];
+ ), CreatureList::$brickFile));
}
}
@@ -865,7 +822,7 @@ class ItemPage extends genericPage
else
$w = '`reqItemId1` = '.$this->typeId.' OR `reqItemId2` = '.$this->typeId.' OR `reqItemId3` = '.$this->typeId.' OR `reqItemId4` = '.$this->typeId.' OR `reqItemId5` = '.$this->typeId;
- if (!$n && ItemListFilter::isCurrencyFor($this->typeId))
+ if (!$n && !is_null(ItemListFilter::getCriteriaIndex(158, $this->typeId)))
$n = '?items&filter=cr=158;crs='.$this->typeId.';crv=0';
$xCosts = DB::Aowow()->selectCol('SELECT `id` FROM ?_itemextendedcost WHERE '.$w);
@@ -879,7 +836,7 @@ class ItemPage extends genericPage
$filter = $iCur->error ? [Type::ITEM => $this->typeId] : [Type::CURRENCY => $iCur->id];
$tabData = array(
- 'data' => array_values($boughtBy->getListviewData(ITEMINFO_VENDOR, $filter)),
+ 'data' => $boughtBy->getListviewData(ITEMINFO_VENDOR, $filter),
'name' => '$LANG.tab_currencyfor',
'id' => 'currency-for',
'extraCols' => ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost']
@@ -888,7 +845,7 @@ class ItemPage extends genericPage
if ($n)
$tabData['note'] = sprintf(Util::$filterResultString, $n);
- $this->lvTabs[] = [ItemList::$brickFile, $tabData];
+ $this->lvTabs->addListviewTab(new Listview($tabData, ItemList::$brickFile));
$this->extendGlobalData($boughtBy->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
}
@@ -927,12 +884,12 @@ class ItemPage extends genericPage
if ($taughtSpells->hasSetFields('reagent1', 'reagent2', 'reagent3', 'reagent4', 'reagent5', 'reagent6', 'reagent7', 'reagent8'))
$visCols[] = 'reagents';
- $this->lvTabs[] = [SpellList::$brickFile, array(
- 'data' => array_values($taughtSpells->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $taughtSpells->getListviewData(),
'name' => '$LANG.tab_teaches',
'id' => 'teaches',
'visibleCols' => $visCols
- )];
+ ), SpellList::$brickFile));
}
}
@@ -950,7 +907,7 @@ class ItemPage extends genericPage
$useSpells[] = $this->subject->getField('spellId'.$i);
}
if ($useSpells)
- if ($_ = DB::Aowow()->selectCol('SELECT category FROM ?_spell WHERE id IN (?a) AND recoveryCategory > 0', $useSpells))
+ if ($_ = DB::Aowow()->selectCol('SELECT `category` FROM ?_spell WHERE `id` IN (?a) AND `recoveryCategory` > 0', $useSpells))
$cdCats += $_;
if ($cdCats)
@@ -967,18 +924,18 @@ class ItemPage extends genericPage
]
);
- if ($spellsByCat = DB::Aowow()->selectCol('SELECT id FROM ?_spell WHERE category IN (?a)', $cdCats))
+ if ($spellsByCat = DB::Aowow()->selectCol('SELECT `id` FROM ?_spell WHERE `category` IN (?a)', $cdCats))
for ($i = 1; $i < 6; $i++)
$conditions[1][] = ['spellId'.$i, $spellsByCat];
$cdItems = new ItemList($conditions);
if (!$cdItems->error)
{
- $this->lvTabs[] = [ItemList::$brickFile, array(
- 'data' => array_values($cdItems->getListviewData()),
+ $this->lvTabs->addListviewTab(new Listview(array(
+ 'data' => $cdItems->getListviewData(),
'name' => '$LANG.tab_sharedcooldown',
'id' => 'shared-cooldown'
- )];
+ ), ItemList::$brickFile));
$this->extendGlobalData($cdItems->getJSGlobals(GLOBALINFO_SELF));
}
@@ -992,7 +949,7 @@ class ItemPage extends genericPage
if ($this->subject->getField('soundOverrideSubclass') > 0)
$scm = (1 << $this->subject->getField('soundOverrideSubclass'));
- $soundIds = DB::Aowow()->selectCol('SELECT soundId FROM ?_items_sounds WHERE subClassMask & ?d', $scm);
+ $soundIds = DB::Aowow()->selectCol('SELECT `soundId` FROM ?_items_sounds WHERE `subClassMask` & ?d', $scm);
}
$fields = ['pickUpSoundId', 'dropDownSoundId', 'sheatheSoundId', 'unsheatheSoundId'];
@@ -1002,7 +959,7 @@ class ItemPage extends genericPage
if ($x = $this->subject->getField('spellVisualId'))
{
- if ($spellSounds = DB::Aowow()->selectRow('SELECT * FROM ?_spell_sounds WHERE id = ?d', $x))
+ if ($spellSounds = DB::Aowow()->selectRow('SELECT * FROM ?_spell_sounds WHERE `id` = ?d', $x))
{
array_shift($spellSounds); // bye 'id'-field
foreach ($spellSounds as $ss)
@@ -1017,7 +974,7 @@ class ItemPage extends genericPage
if (!$sounds->error)
{
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
- $this->lvTabs[] = [SoundList::$brickFile, ['data' => array_values($sounds->getListviewData())]];
+ $this->lvTabs->addListviewTab(new Listview(['data' => $sounds->getListviewData()], SoundList::$brickFile));
}
}
@@ -1027,7 +984,7 @@ class ItemPage extends genericPage
if ($tab = $cnd->toListviewTab('condition-for', '$LANG.tab_condition_for'))
{
$this->extendGlobalData($cnd->getJsGlobals());
- $this->lvTabs[] = $tab;
+ $this->lvTabs->addDataTab(...$tab);
}
@@ -1035,174 +992,39 @@ class ItemPage extends genericPage
// use var $createdBy to find source of this spell
// id: 'taught-by-X',
// name: LANG.tab_taughtby
+
+ parent::generate();
}
- protected function generateTooltip()
+ private function followBreadcrumbPath() : array
{
- $power = new \StdClass();
- if (!$this->subject->error)
- {
- $power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true, false, $this->enhancedTT), Lang::FMT_RAW);
- $power->quality = $this->subject->getField('quality');
- $power->icon = rawurlencode($this->subject->getField('iconString', true, true));
- $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(false, 0, $this->enhancedTT);
- }
+ $c = $this->subject->getField('class');
+ $sc = $this->subject->getField('subClass');
+ $ssc = $this->subject->getField('subSubClass');
+ $slot = $this->subject->getField('slot');
- $itemString = $this->typeId;
- if ($this->enhancedTT)
- {
- foreach ($this->enhancedTT as $k => $val)
- $itemString .= $k.(is_array($val) ? implode(',', $val) : $val);
- $itemString = "'".$itemString."'";
- }
+ if ($c == ITEM_CLASS_REAGENT)
+ return [ITEM_CLASS_MISC, 1]; // misc > reagents
- return sprintf($this->powerTpl, $itemString,Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
- }
+ if ($c == ITEM_CLASS_GENERIC || $c == ITEM_CLASS_PERMANENT)
+ return [ITEM_CLASS_MISC, 4]; // misc > other
- protected function generateXML()
- {
- $root = new SimpleXML('');
+ // depths: 1
+ $path = [$c];
- if ($this->subject->error)
- $root->addChild('error', 'Item not found!');
- else
- {
- // item root
- $xml = $root->addChild('item');
- $xml->addAttribute('id', $this->typeId);
+ if (in_array($c, [ITEM_CLASS_MONEY, ITEM_CLASS_QUEST, ITEM_CLASS_KEY]))
+ return $path;
- // name
- $xml->addChild('name')->addCData($this->subject->getField('name', true));
- // itemlevel
- $xml->addChild('level', $this->subject->getField('itemLevel'));
- // quality
- $xml->addChild('quality', Lang::item('quality', $this->subject->getField('quality')))->addAttribute('id', $this->subject->getField('quality'));
- // class
- $x = Lang::item('cat', $this->subject->getField('class'));
- $xml->addChild('class')->addCData(is_array($x) ? $x[0] : $x)->addAttribute('id', $this->subject->getField('class'));
- // subclass
- $x = $this->subject->getField('class') == 2 ? Lang::spell('weaponSubClass') : Lang::item('cat', $this->subject->getField('class'), 1);
- $xml->addChild('subclass')->addCData(is_array($x) ? (is_array($x[$this->subject->getField('subClass')]) ? $x[$this->subject->getField('subClass')][0] : $x[$this->subject->getField('subClass')]) : Lang::item('cat', $this->subject->getField('class')))->addAttribute('id', $this->subject->getField('subClass'));
- // icon + displayId
- $xml->addChild('icon', $this->subject->getField('iconString', true, true))->addAttribute('displayId', $this->subject->getField('displayId'));
- // inventorySlot
- $xml->addChild('inventorySlot', Lang::item('inventoryType', $this->subject->getField('slot')))->addAttribute('id', $this->subject->getField('slot'));
- // tooltip
- $xml->addChild('htmlTooltip')->addCData($this->subject->renderTooltip());
+ // depths: 2
+ $path[] = $sc;
- $this->subject->extendJsonStats();
+ // maybe depths: 3
+ if ($this->subject->isBodyArmor() && $slot)
+ $path[] = $slot;
+ else if (($c == ITEM_CLASS_CONSUMABLE && $sc == ITEM_SUBCLASS_ELIXIR) || $c == ITEM_CLASS_GLYPH)
+ $path[] = $ssc;
- // json
- $fields = ['classs', 'displayid', 'dps', 'id', 'level', 'name', 'reqlevel', 'slot', 'slotbak', 'speed', 'subclass'];
- $json = [];
- foreach ($fields as $f)
- {
- if (isset($this->subject->json[$this->typeId][$f]))
- {
- $_ = $this->subject->json[$this->typeId][$f];
- if ($f == 'name')
- $_ = (7 - $this->subject->getField('quality')).$_;
-
- $json[$f] = $_;
- }
- }
-
- // itemsource
- if ($this->subject->getSources($s, $sm))
- {
- $json['source'] = $s;
- if ($sm)
- $json['sourcemore'] = $sm;
- }
-
- $xml->addChild('json')->addCData(substr(json_encode($json), 1, -1));
-
- // jsonEquip missing: avgbuyout
- $json = [];
- if ($_ = $this->subject->getField('sellPrice')) // sellprice
- $json['sellprice'] = $_;
-
- if ($_ = $this->subject->getField('requiredLevel')) // reqlevel
- $json['reqlevel'] = $_;
-
- if ($_ = $this->subject->getField('requiredSkill')) // reqskill
- $json['reqskill'] = $_;
-
- if ($_ = $this->subject->getField('requiredSkillRank')) // reqskillrank
- $json['reqskillrank'] = $_;
-
- if ($_ = $this->subject->getField('cooldown')) // cooldown
- $json['cooldown'] = $_ / 1000;
-
- Util::arraySumByKey($json, $this->subject->jsonStats[$this->typeId] ?? []);
-
- foreach ($this->subject->json[$this->typeId] as $name => $qty)
- if ($idx = Stat::getIndexFrom(Stat::IDX_JSON_STR, $name))
- if (Stat::getFilterCriteriumId($idx))
- $json[$name] = $qty;
-
- $xml->addChild('jsonEquip')->addCData(substr(json_encode($json), 1, -1));
-
- // jsonUse
- if ($onUse = $this->subject->getOnUseStats())
- {
- $j = '';
- foreach ($onUse->toJson() as $key => $amt)
- $j .= ',"'.$key.'":'.$amt;
-
- $xml->addChild('jsonUse')->addCData(substr($j, 1));
- }
-
- // reagents
- $cnd = array(
- 'OR',
- ['AND', ['effect1CreateItemId', $this->typeId], ['OR', ['effect1Id', SpellList::EFFECTS_ITEM_CREATE], ['effect1AuraId', SpellList::AURAS_ITEM_CREATE]]],
- ['AND', ['effect2CreateItemId', $this->typeId], ['OR', ['effect2Id', SpellList::EFFECTS_ITEM_CREATE], ['effect2AuraId', SpellList::AURAS_ITEM_CREATE]]],
- ['AND', ['effect3CreateItemId', $this->typeId], ['OR', ['effect3Id', SpellList::EFFECTS_ITEM_CREATE], ['effect3AuraId', SpellList::AURAS_ITEM_CREATE]]],
- );
-
- $spellSource = new SpellList($cnd);
- if (!$spellSource->error)
- {
- $cbNode = $xml->addChild('createdBy');
-
- foreach ($spellSource->iterate() as $sId => $__)
- {
- foreach ($spellSource->canCreateItem() as $idx)
- {
- if ($spellSource->getField('effect'.$idx.'CreateItemId') != $this->typeId)
- continue;
-
- $splNode = $cbNode->addChild('spell');
- $splNode->addAttribute('id', $sId);
- $splNode->addAttribute('name', $spellSource->getField('name', true));
- $splNode->addAttribute('icon', $this->subject->getField('iconString', true, true));
- $splNode->addAttribute('minCount', $spellSource->getField('effect'.$idx.'BasePoints') + 1);
- $splNode->addAttribute('maxCount', $spellSource->getField('effect'.$idx.'BasePoints') + $spellSource->getField('effect'.$idx.'DieSides'));
-
- foreach ($spellSource->getReagentsForCurrent() as $rId => $qty)
- {
- if ($reagent = $spellSource->relItems->getEntry($rId))
- {
- $rgtNode = $splNode->addChild('reagent');
- $rgtNode->addAttribute('id', $rId);
- $rgtNode->addAttribute('name', Util::localizedString($reagent, 'name'));
- $rgtNode->addAttribute('quality', $reagent['quality']);
- $rgtNode->addAttribute('icon', $reagent['iconString']);
- $rgtNode->addAttribute('count', $qty[1]);
- }
- }
-
- break;
- }
- }
- }
-
- // link
- $xml->addChild('link', Cfg::get('HOST_URL').'?item='.$this->subject->id);
- }
-
- return $root->asXML();
+ return $path;
}
}
diff --git a/endpoints/item/item_power.php b/endpoints/item/item_power.php
new file mode 100644
index 00000000..25617b47
--- /dev/null
+++ b/endpoints/item/item_power.php
@@ -0,0 +1,70 @@
+ ['filter' => FILTER_CALLBACK, 'options' => [Locale::class, 'tryFromDomain']],
+ 'rand' => ['filter' => FILTER_VALIDATE_INT ],
+ 'ench' => ['filter' => FILTER_VALIDATE_INT ],
+ 'gems' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkIntArray'] ],
+ 'sock' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkEmptySet'] ]
+ );
+
+ public function __construct($param)
+ {
+ parent::__construct($param);
+
+ // temp locale
+ if ($this->_get['domain'])
+ Lang::load($this->_get['domain']);
+
+ $this->typeId = intVal($param);
+
+ if ($this->_get['rand'])
+ $this->enhancedTT['r'] = $this->_get['rand'];
+ if ($this->_get['ench'])
+ $this->enhancedTT['e'] = $this->_get['ench'];
+ if ($this->_get['gems'])
+ $this->enhancedTT['g'] = $this->_get['gems'];
+ if ($this->_get['sock'])
+ $this->enhancedTT['s'] = '';
+ }
+
+ protected function generate() : void
+ {
+ $item = new ItemList(array(['i.id', $this->typeId]));
+ if ($item->error)
+ $this->cacheType = CACHE_TYPE_NONE;
+ else
+ {
+ $itemString = $this->typeId;
+ foreach ($this->enhancedTT as $k => $val)
+ $itemString .= $k.(is_array($val) ? implode(',', $val) : $val);
+
+ $opts = array(
+ 'name' => Lang::unescapeUISequences($item->getField('name', true, false, $this->enhancedTT), Lang::FMT_RAW),
+ 'tooltip' => $item->renderTooltip(enhance: $this->enhancedTT),
+ 'icon' => $item->getField('iconString'),
+ 'quality' => $item->getField('quality')
+ );
+ }
+
+ $this->result = new Tooltip(self::POWER_TEMPLATE, $itemString ?? $this->typeId, $opts ?? []);
+ }
+}
+
+?>
diff --git a/endpoints/item/item_xml.php b/endpoints/item/item_xml.php
new file mode 100644
index 00000000..5599be5c
--- /dev/null
+++ b/endpoints/item/item_xml.php
@@ -0,0 +1,231 @@
+ ['filter' => FILTER_CALLBACK, 'options' => [Locale::class, 'tryFromDomain']]
+ );
+
+ private ItemList $subject;
+ private string $search = '';
+
+ public function __construct(string $param)
+ {
+ parent::__construct($param);
+
+ // temp locale
+ if ($this->_get['domain'])
+ Lang::load($this->_get['domain']);
+
+ // allow lookup by name
+ if (is_numeric($param))
+ $this->typeId = intVal($param);
+ else
+ $this->search = urldecode($param);
+ }
+
+ protected function generate() : void
+ {
+ if ($this->search)
+ $conditions = [['name_loc'.Lang::getLocale()->value, $this->search]];
+ else
+ $conditions = [['i.id', $this->typeId]];
+
+ $this->subject = new ItemList($conditions);
+ if ($this->subject->error)
+ {
+ $this->cacheType = CACHE_TYPE_NONE;
+ header('HTTP/1.0 404 Not Found', true, 404);
+
+ $root = new SimpleXML('');
+ $root->addChild('error', 'Item not found!');
+ $this->result = $root->asXML();
+
+ return;
+ }
+ else
+ $this->typeId = $this->subject->id;
+
+ $root = new SimpleXML('');
+
+ // item root
+ $xml = $root->addChild('item');
+ $xml->addAttribute('id', $this->typeId);
+
+ // name
+ $xml->addChild('name')->addCData($this->subject->getField('name', true));
+ // itemlevel
+ $xml->addChild('level', $this->subject->getField('itemLevel'));
+ // quality
+ $xml->addChild('quality', Lang::item('quality', $this->subject->getField('quality')))->addAttribute('id', $this->subject->getField('quality'));
+ // class
+ $x = Lang::item('cat', $this->subject->getField('class'));
+ $xml->addChild('class')->addCData(is_array($x) ? $x[0] : $x)->addAttribute('id', $this->subject->getField('class'));
+ // subclass
+ $xml->addChild('subclass')->addCData($this->getSubclass())->addAttribute('id', $this->subject->getField('subClass'));
+ // icon + displayId
+ $xml->addChild('icon', $this->subject->getField('iconString'))->addAttribute('displayId', $this->subject->getField('displayId'));
+ // inventorySlot
+ $xml->addChild('inventorySlot', Lang::item('inventoryType', $this->subject->getField('slot')))->addAttribute('id', $this->subject->getField('slot'));
+ // tooltip
+ $xml->addChild('htmlTooltip')->addCData($this->subject->renderTooltip());
+
+ $this->subject->extendJsonStats();
+
+ // json
+ $fields = ['classs', 'displayid', 'dps', 'id', 'level', 'name', 'reqlevel', 'slot', 'slotbak', 'speed', 'subclass'];
+ $json = [];
+ foreach ($fields as $f)
+ {
+ if (isset($this->subject->json[$this->typeId][$f]))
+ {
+ $_ = $this->subject->json[$this->typeId][$f];
+ if ($f == 'name')
+ $_ = (7 - $this->subject->getField('quality')).$_;
+
+ $json[$f] = $_;
+ }
+ }
+
+ // itemsource
+ if ($this->subject->getSources($s, $sm))
+ {
+ $json['source'] = $s;
+ if ($sm)
+ $json['sourcemore'] = $sm;
+ }
+
+ $xml->addChild('json')->addCData(substr(json_encode($json), 1, -1));
+
+ // jsonEquip missing: avgbuyout
+ $json = [];
+ if ($_ = $this->subject->getField('sellPrice')) // sellprice
+ $json['sellprice'] = $_;
+
+ if ($_ = $this->subject->getField('requiredLevel')) // reqlevel
+ $json['reqlevel'] = $_;
+
+ if ($_ = $this->subject->getField('requiredSkill')) // reqskill
+ $json['reqskill'] = $_;
+
+ if ($_ = $this->subject->getField('requiredSkillRank')) // reqskillrank
+ $json['reqskillrank'] = $_;
+
+ if ($_ = $this->subject->getField('cooldown')) // cooldown
+ $json['cooldown'] = $_ / 1000;
+
+ Util::arraySumByKey($json, $this->subject->jsonStats[$this->typeId] ?? []);
+
+ foreach ($this->subject->json[$this->typeId] as $name => $qty)
+ if ($idx = Stat::getIndexFrom(Stat::IDX_JSON_STR, $name))
+ if (Stat::getFilterCriteriumId($idx))
+ $json[$name] = $qty;
+
+ $xml->addChild('jsonEquip')->addCData(substr(json_encode($json), 1, -1));
+
+ // jsonUse
+ if ($onUse = $this->subject->getOnUseStats())
+ {
+ $j = '';
+ foreach ($onUse->toJson(includeEmpty: false) as $key => $amt)
+ $j .= ',"'.$key.'":'.$amt;
+
+ $xml->addChild('jsonUse')->addCData(substr($j, 1));
+ }
+
+ // reagents
+ $cnd = array(
+ 'OR',
+ ['AND', ['effect1CreateItemId', $this->typeId], ['OR', ['effect1Id', SpellList::EFFECTS_ITEM_CREATE], ['effect1AuraId', SpellList::AURAS_ITEM_CREATE]]],
+ ['AND', ['effect2CreateItemId', $this->typeId], ['OR', ['effect2Id', SpellList::EFFECTS_ITEM_CREATE], ['effect2AuraId', SpellList::AURAS_ITEM_CREATE]]],
+ ['AND', ['effect3CreateItemId', $this->typeId], ['OR', ['effect3Id', SpellList::EFFECTS_ITEM_CREATE], ['effect3AuraId', SpellList::AURAS_ITEM_CREATE]]],
+ );
+
+ $spellSource = new SpellList($cnd);
+ if (!$spellSource->error)
+ {
+ $cbNode = $xml->addChild('createdBy');
+
+ foreach ($spellSource->iterate() as $sId => $__)
+ {
+ foreach ($spellSource->canCreateItem() as $idx)
+ {
+ if ($spellSource->getField('effect'.$idx.'CreateItemId') != $this->typeId)
+ continue;
+
+ $splNode = $cbNode->addChild('spell');
+ $splNode->addAttribute('id', $sId);
+ $splNode->addAttribute('name', $spellSource->getField('name', true));
+ $splNode->addAttribute('icon', $this->subject->getField('iconString'));
+ $splNode->addAttribute('minCount', $spellSource->getField('effect'.$idx.'BasePoints') + 1);
+ $splNode->addAttribute('maxCount', $spellSource->getField('effect'.$idx.'BasePoints') + $spellSource->getField('effect'.$idx.'DieSides'));
+
+ foreach ($spellSource->getReagentsForCurrent() as $rId => $qty)
+ {
+ if ($reagent = $spellSource->relItems->getEntry($rId))
+ {
+ $rgtNode = $splNode->addChild('reagent');
+ $rgtNode->addAttribute('id', $rId);
+ $rgtNode->addAttribute('name', Util::localizedString($reagent, 'name'));
+ $rgtNode->addAttribute('quality', $reagent['quality']);
+ $rgtNode->addAttribute('icon', $reagent['iconString']);
+ $rgtNode->addAttribute('count', $qty[1]);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ // link
+ $xml->addChild('link', Cfg::get('HOST_URL').'?item='.$this->subject->id);
+
+ $this->result = $root->asXML();
+ }
+
+ private function getSubclass() : string
+ {
+ $c = $this->subject->getField('class');
+ $sc = $this->subject->getField('subClass');
+
+ if ($c == ITEM_CLASS_WEAPON)
+ $langRef = Lang::spell('weaponSubClass');
+ else
+ $langRef = Lang::item('cat', $c, 1);
+
+ if (!is_array($langRef))
+ return Lang::item('cat', $c);
+
+ if (is_array($langRef[$sc]))
+ return $langRef[$sc][0];
+
+ return $langRef[$sc];
+ }
+
+ public function getCacheKeyComponents() : array
+ {
+ return array(
+ $this->type, // DBType
+ $this->typeId, // DBTypeId
+ -1, // category
+ -1, // staff mask (content does not diff)
+ '' // misc (unused)
+ );
+ }
+}
+
+?>
diff --git a/pages/items.php b/endpoints/items/items.php
similarity index 70%
rename from pages/items.php
rename to endpoints/items/items.php
index f334b52b..97d4a9d1 100644
--- a/pages/items.php
+++ b/endpoints/items/items.php
@@ -6,28 +6,24 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-// menuId 0: Item g_initPath()
-// tabId 0: Database g_initHeader()
-class ItemsPage extends GenericPage
+class ItemsBaseResponse extends TemplateResponse implements ICache
{
- use TrListPage;
+ use TrListPage, TrCache;
- protected $forceTabs = false;
- protected $gemScores = [];
+ protected int $type = Type::ITEM;
+ protected int $cacheType = CACHE_TYPE_PAGE;
- protected $typeList = []; // rightPanel - content by context
- protected $slotList = []; // rightPanel - INV_TYPE_Xs
+ protected string $template = 'items';
+ protected string $pageName = 'items';
+ protected ?int $activeTab = parent::TAB_DATABASE;
+ protected array $breadcrumb = [0, 0];
- protected $type = Type::ITEM;
- protected $tpl = 'items';
- protected $path = [0, 0];
- protected $tabId = 0;
- protected $mode = CACHE_TYPE_PAGE;
- protected $scripts = [[SC_JS_FILE, 'js/filters.js'], [SC_JS_FILE, 'js/swfobject.js']];
-
- protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]];
-
- protected $validCats = array( // if > 0 class => subclass
+ protected array $dataLoader = ['weight-presets'];
+ protected array $scripts = [[SC_JS_FILE, 'js/filters.js'], [SC_JS_FILE, 'js/swfobject.js']];
+ protected array $expectedGET = array(
+ 'filter' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => Filter::PATTERN_PARAM]]
+ );
+ protected array $validCats = array( // if > 0 class => subclass
2 => [15, 13, 0, 4, 7, 6, 10, 1, 5, 8, 2, 18, 3, 16, 19, 20, 14],
4 => array(
0 => true,
@@ -84,51 +80,52 @@ class ItemsPage extends GenericPage
13 => true
);
- private $filterOpts = [];
- private $sharedLV = array( // common listview components across all tabs
+ public array $gemScores = [];
+ public array $typeList = []; // rightPanel - content by context
+ public array $slotList = []; // rightPanel - INV_TYPE_Xs
+
+ private array $filterOpts = [];
+ private array $sharedLV = array( // common listview components across all tabs
'hiddenCols' => [],
'visibleCols' => [],
'extraCols' => []
);
- public function __construct($pageCall, $pageParam)
+ public function __construct(string $pageParam)
{
$this->getCategoryFromUrl($pageParam);
- parent::__construct($pageCall, $pageParam);
+ parent::__construct($pageParam);
- $this->filterObj = new ItemListFilter($this->_get['filter'] ?? '', ['parentCats' => $this->category]);
-
- $this->name = Util::ucFirst(Lang::game('items'));
$this->subCat = $pageParam !== '' ? '='.$pageParam : '';
+ $this->filter = new ItemListFilter($this->_get['filter'] ?? '', ['parentCats' => $this->category]);
+ $this->filterError = $this->filter->error;
}
- protected function generateContent()
+ protected function generate() : void
{
- $this->addScript([SC_JS_FILE, '?data=weight-presets']);
+ $this->h1 = Util::ucFirst(Lang::game('items'));
$conditions = [];
-
if (!User::isInGroup(U_GROUP_EMPLOYEE))
$conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
+ $this->filter->evalCriteria();
+ $this->filter->evalWeights();
+
+ if ($_ = $this->filter->getConditions())
+ $conditions[] = $_;
+
+ $this->filterError = $this->filter->error; // maybe the evalX() caused something
+
/*******************/
/* evaluate filter */
/*******************/
- $this->filterObj->evalCriteria();
- $this->filterObj->evalWeights();
+ $fiForm = $this->filter->values;
- if ($_ = $this->filterObj->getConditions())
- $conditions[] = $_;
-
- // recreate form selection (must be evaluated first via getConditions())
- $fiForm = $this->filterObj->values;
-
- $xCols = $this->filterObj->fiExtraCols;
-
- $this->createExtraMenus();
+ $xCols = $this->filter->fiExtraCols;
$infoMask = ITEMINFO_JSON;
if (array_intersect([63, 64, 125], $xCols)) // 63:buyPrice; 64:sellPrice; 125:reqarenartng
@@ -137,8 +134,42 @@ class ItemsPage extends GenericPage
if ($xCols)
$this->sharedLV['extraCols'] = '$fi_getExtraCols(fi_extraCols, '.($fiForm['gm'] ?? 0).', '.(array_intersect([63], $xCols) ? 1 : 0).')';
- if ($this->filterObj->error)
- $this->sharedLV['_errors'] = '$1';
+ $this->createExtraMenus(); // right side panels in search form
+
+
+ /*************/
+ /* Menu Path */
+ /*************/
+
+ foreach ($this->category as $c)
+ $this->breadcrumb[] = $c;
+
+ // if slot-dropdown is available && Armor && $path points to Armor-Class
+ if (count($this->breadcrumb) == 4 && $this->category[0] == 4 && count($fiForm['sl']) == 1)
+ $this->breadcrumb[] = $fiForm['sl'][0];
+ else if (isset($this->category[0]) && $this->category[0] == 0 && count($fiForm['ty']) == 1)
+ $this->breadcrumb[] = $fiForm['ty'][0];
+
+
+ /**************/
+ /* Page Title */
+ /**************/
+
+ array_unshift($this->title, $this->h1);
+
+ if ($this->category)
+ {
+ if (isset($this->category[2]) && is_array(Lang::item('cat', $this->category[0], 1, $this->category[1])))
+ $tPart = Lang::item('cat', $this->category[0], 1, $this->category[1], 1, $this->category[2]);
+ else if (isset($this->category[1]) && is_array(Lang::item('cat', $this->category[0])))
+ $tPart = Lang::item('cat', $this->category[0], 1, $this->category[1]);
+ else if ($this->category[0] == 0 && count($fiForm['ty']) == 1)
+ $tPart = Lang::item('cat', 0, 1, $fiForm['ty'][0]);
+ else
+ $tPart = Lang::item('cat', $this->category[0]);
+
+ array_unshift($this->title, is_array($tPart) ? $tPart[0] : $tPart);
+ }
/******************/
@@ -157,7 +188,7 @@ class ItemsPage extends GenericPage
/* handle auto-gemming */
/***********************/
- $this->gemScores = $this->createGemScores($fiForm['gm'] ?? 0);
+ $this->createGemScores($fiForm['gm'] ?? 0);
/*************************/
@@ -165,9 +196,9 @@ class ItemsPage extends GenericPage
/*************************/
$upgItemData = [];
- if ($this->filterObj->upgrades && $this->filterObj->fiSetWeights)
+ if ($this->filter->upgrades && $this->filter->fiSetWeights)
{
- $upgItems = new ItemList(array(['id', array_keys($this->filterObj->upgrades)]), ['extraOpts' => $this->filterObj->extraOpts]);
+ $upgItems = new ItemList(array(['id', array_keys($this->filter->upgrades)]), ['extraOpts' => $this->filter->extraOpts]);
if (!$upgItems->error)
{
$upgItemData = $upgItems->getListviewData($infoMask);
@@ -175,11 +206,11 @@ class ItemsPage extends GenericPage
}
}
- if ($upgItemData) // check if upItems cover multiple slots
+ if ($upgItemData) // check if upgItems cover multiple slots
{
$singleSlot = true;
- $ref = reset($this->filterObj->upgrades);
- foreach ($this->filterObj->upgrades as $slot)
+ $ref = reset($this->filter->upgrades);
+ foreach ($this->filter->upgrades as $slot)
{
if ($slot == $ref)
continue;
@@ -189,10 +220,10 @@ class ItemsPage extends GenericPage
}
if ($singleSlot && empty($fiForm['gb'])) // enforce group by slot
- $fiForm['gb'] = 1;
+ $fiForm['gb'] = ItemListFilter::GROUP_BY_SLOT;
else if (!$singleSlot) // multiples can only be grouped by slot
{
- $fiForm['gb'] = 1;
+ $fiForm['gb'] = ItemListFilter::GROUP_BY_SLOT;
$maxResults = 25;
$this->sharedLV['customFilter'] = '$fi_filterUpgradeListview';
}
@@ -221,15 +252,17 @@ class ItemsPage extends GenericPage
);
$groups = [];
$nameSource = [];
- $grouping = $fiForm['gb'] ?? 0;
+ $grouping = $fiForm['gb'] ?? ItemListFilter::GROUP_BY_NONE;
$extraOpts = [];
$maxResults = Cfg::get('SQL_LIMIT_DEFAULT');
+ $forceTabs = false;
+ $tabs = [];
switch ($grouping)
{
// slot: (try to limit the lookups by class grouping and intersecting with preselected slots)
// if intersect yields an empty array no lookups will occur
- case 1:
+ case ItemListFilter::GROUP_BY_SLOT:
if (isset($this->category[0]) && $this->category[0] == ITEM_CLASS_ARMOR)
$groups = $availableSlots[ITEM_CLASS_ARMOR];
else if (isset($this->category[0]) && $this->category[0] == ITEM_CLASS_WEAPON)
@@ -240,20 +273,20 @@ class ItemsPage extends GenericPage
if ($fiForm['sl']) // skip lookups for unselected slots
$groups = array_intersect($groups, $fiForm['sl']);
- if (!empty($this->filterObj->upgrades)) // skip lookups for slots we dont have items to upgrade for
- $groups = array_intersect($groups, $this->filterObj->upgrades);
+ if ($this->filter->upgrades) // skip lookups for slots we dont have items to upgrade for
+ $groups = array_intersect($groups, $this->filter->upgrades);
if ($groups)
{
$nameSource = Lang::item('inventoryType');
- $this->forceTabs = true;
+ $forceTabs = true;
}
break;
- case 2: // itemlevel: first, try to find 10 level steps within range (if given) as tabs
+ case ItemListFilter::GROUP_BY_LEVEL: // itemlevel: first, try to find 10 level steps within range (if given) as tabs
// ohkayy, maybe i need to rethink $this
- $this->filterOpts = $this->filterObj->extraOpts;
- $this->filterOpts['is']['o'] = [null]; // remove 'order by' from itemStats
+ $this->filterOpts = $this->filter->extraOpts;
+ $this->filterOpts['is']['o'] = [null]; // remove 'order by' from ?_item_stats
$extraOpts = array_merge($this->filterOpts, ['i' => ['g' => ['itemlevel'], 'o' => ['itemlevel DESC']]]);
$levelRef = new ItemList(array_merge($conditions, [10]), ['extraOpts' => $extraOpts]);
@@ -270,25 +303,25 @@ class ItemsPage extends GenericPage
$groups[] = $l; // push last value as negativ to signal misc group after $this level
$extraOpts = ['i' => ['o' => ['itemlevel DESC']]];
$nameSource[$l] = Lang::item('tabOther');
- $this->forceTabs = true;
+ $forceTabs = true;
}
break;
- case 3: // source
+ case ItemListFilter::GROUP_BY_SOURCE: // source
$groups = [1, 2, 3, 4, 5, 10, 11, 12, 0];
$nameSource = Lang::game('sources');
- $this->forceTabs = true;
+ $forceTabs = true;
break;
// none
default:
- $grouping = 0;
+ $grouping = ItemListFilter::GROUP_BY_NONE;
$groups[0] = null;
}
// write back 'gb' to filter
if ($grouping)
- $this->filterObj->values['gb'] = $grouping;
+ $this->filter->values['gb'] = $grouping;
/*****************************/
@@ -297,22 +330,15 @@ class ItemsPage extends GenericPage
foreach ($groups as $group)
{
- switch ($grouping)
+ $finalCnd = match ($grouping)
{
- case 1:
- $finalCnd = array_merge($conditions, [['slot', $group], $maxResults]);
- break;
- case 2:
- $finalCnd = array_merge($conditions, [['itemlevel', abs($group), $group > 0 ? null : '<'], $maxResults]);
- break;
- case 3:
- $finalCnd = array_merge($conditions, [$group ? ['src.src'.$group, null, '!'] : ['src.typeId', null], $maxResults]);
- break;
- default:
- $finalCnd = $conditions;
- }
+ ItemListFilter::GROUP_BY_SLOT => array_merge($conditions, [['slot', $group], $maxResults]),
+ ItemListFilter::GROUP_BY_LEVEL => array_merge($conditions, [['itemlevel', abs($group), $group > 0 ? null : '<'], $maxResults]),
+ ItemListFilter::GROUP_BY_SOURCE => array_merge($conditions, [$group ? ['src.src'.$group, null, '!'] : ['src.typeId', null], $maxResults]),
+ default => $conditions
+ };
- $items = new ItemList($finalCnd, ['extraOpts' => array_merge($extraOpts, $this->filterObj->extraOpts), 'calcTotal' => true]);
+ $items = new ItemList($finalCnd, ['extraOpts' => array_merge($extraOpts, $this->filter->extraOpts), 'calcTotal' => true]);
if ($items->error)
continue;
@@ -326,11 +352,10 @@ class ItemsPage extends GenericPage
$upg = [];
if ($upgItemData)
{
- if ($grouping == 1) // slot: match upgradeItem to slot
+ // slot: match upgradeItem to slot
+ if ($grouping == ItemListFilter::GROUP_BY_SLOT)
{
- $upg = array_keys(array_filter($this->filterObj->upgrades, function ($v) use ($group) {
- return $v == $group;
- }));
+ $upg = array_keys(array_filter($this->filter->upgrades, fn($x) => $x == $group));
foreach ($upg as $uId)
$tabData['data'][$uId] = $upgItemData[$uId];
@@ -340,7 +365,7 @@ class ItemsPage extends GenericPage
}
else if ($grouping)
{
- $upg = array_keys($this->filterObj->upgrades);
+ $upg = array_keys($this->filter->upgrades);
$tabData['_upgradeIds'] = $upg;
foreach ($upgItemData as $uId => $data) // using numeric keys => cant use array_merge
$tabData['data'][$uId] = $data;
@@ -349,24 +374,18 @@ class ItemsPage extends GenericPage
if ($grouping)
{
- switch ($grouping)
+ $tabData['id'] = match ($grouping)
{
- case 1:
- $tabData['id'] = 'slot-'.$group;
- break;
- case 2:
- $tabData['id'] = $group > 0 ? 'level-'.$group : 'other';
- break;
- case 3:
- $tabData['id'] = $group ? 'source-'.$group : 'unknown';
- break;
- }
+ ItemListFilter::GROUP_BY_SLOT => 'slot-'.$group,
+ ItemListFilter::GROUP_BY_LEVEL => $group > 0 ? 'level-'.$group : 'other',
+ ItemListFilter::GROUP_BY_SOURCE => $group ? 'source-'.$group : 'unknown'
+ };
$tabData['name'] = $nameSource[$group];
$tabData['tabs'] = '$tabsGroups';
}
- if ($this->filterObj->fiSetWeights)
+ if ($this->filter->fiSetWeights)
if ($items->hasSetFields('tplArmor'))
$tabData['visibleCols'][] = 'armor';
@@ -375,18 +394,18 @@ class ItemsPage extends GenericPage
{
$tabData['_truncated'] = 1;
- $cls = isset($this->category[0]) ? '='.$this->category[0] : '';
+ $catg = isset($this->category[0]) ? '='.$this->category[0] : '';
$override = ['gb' => ''];
if ($upg)
- $override['upg'] = implode(':', $upg);
+ $override['upg'] = $upg;
switch ($grouping)
{
- case 1:
+ case ItemListFilter::GROUP_BY_SLOT:
$override['sl'] = $group;
- $tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmoreslot, \''.$cls.'\', \''.$this->filterObj->buildGETParam($override).'\')';
+ $tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmoreslot, \''.$catg.'\', \''.$this->filter->buildGETParam($override).'\')';
break;
- case 2:
+ case ItemListFilter::GROUP_BY_LEVEL:
if ($group > 0)
{
$override['minle'] = $group;
@@ -395,11 +414,11 @@ class ItemsPage extends GenericPage
else
$override['maxle'] = abs($group) - 1;
- $tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmorelevel, \''.$cls.'\', \''.$this->filterObj->buildGETParam($override).'\')';
+ $tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmorelevel, \''.$catg.'\', \''.$this->filter->buildGETParam($override).'\')';
break;
- case 3:
+ case ItemListFilter::GROUP_BY_SOURCE:
if ($_ = [null, 3, 4, 5, 6, 7, 9, 10, 11][$group])
- $tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmoresource, \''.$cls.'\', \''.$this->filterObj->buildGETParam($override, ['cr' => 128, 'crs' => $_, 'crv' => 0]).'\')';
+ $tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmoresource, \''.$catg.'\', \''.$this->filter->buildGETParam($override, ['cr' => 128, 'crs' => $_, 'crv' => 0]).'\')';
break;
}
@@ -410,105 +429,43 @@ class ItemsPage extends GenericPage
$tabData['_truncated'] = 1;
}
- foreach ($tabData as $k => $p)
- if (!$p && $k != 'data')
- unset($tabData[$k]);
+ // inherited from >sharedLV, may be empty
+ if (!$tabData['hiddenCols'])
+ unset($tabData['hiddenCols']);
+ if (!$tabData['visibleCols'])
+ unset($tabData['visibleCols']);
+ if (!$tabData['extraCols'])
+ unset($tabData['extraCols']);
if ($grouping)
$tabData['hideCount'] = 1;
- $tabData['data'] = array_values($tabData['data']);
-
- $this->lvTabs[] = [ItemList::$brickFile, $tabData];
+ $tabs[] = $tabData;
}
+ $this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsGroups', $forceTabs && $tabs);
+
// whoops, we have no data? create emergency content
- if (empty($this->lvTabs))
- {
- $this->forceTabs = false;
- $this->lvTabs[] = [ItemList::$brickFile, ['data' => []]];
- }
- }
+ if (!count($tabs))
+ $tabs[] = ['data' => []];
- protected function postCache()
- {
- // sort for dropdown-menus
- Lang::sort('game', 'ra');
- Lang::sort('game', 'cl');
- }
+ foreach ($tabs as $t)
+ $this->lvTabs->addListviewTab(new Listview($t, ItemList::$brickFile));
- protected function generateTitle()
- {
- array_unshift($this->title, $this->name);
+ $this->redButtons[BUTTON_WOWHEAD] = true;
+ if ($fiQuery = $this->filter->buildGETParam())
+ $this->wowheadLink .= '&filter='.$fiQuery;
- if (!$this->category)
- return;
+ parent::generate();
- if (isset($this->category[2]) && is_array(Lang::item('cat', $this->category[0], 1, $this->category[1])))
- $tPart = Lang::item('cat', $this->category[0], 1, $this->category[1], 1, $this->category[2]);
- else if (isset($this->category[1]) && is_array(Lang::item('cat', $this->category[0])))
- $tPart = Lang::item('cat', $this->category[0], 1, $this->category[1]);
- else if ($this->category[0] == 0 && count($this->filterObj->values['ty']) == 1)
- $tPart = Lang::item('cat', 0, 1, $this->filterObj->values['ty'][0]);
- else
- $tPart = Lang::item('cat', $this->category[0]);
-
- array_unshift($this->title, is_array($tPart) ? $tPart[0] : $tPart);
- }
-
- protected function generatePath()
- {
- foreach ($this->category as $c)
- $this->path[] = $c;
-
- // if slot-dropdown is available && Armor && $path points to Armor-Class
- $form = $this->filterObj->values;
- if (count($this->path) == 4 && $this->category[0] == 4 && count($form['sl']) == 1)
- $this->path[] = $form['sl'][0];
- else if (isset($this->category[0]) && $this->category[0] == 0 && count($form['ty']) == 1)
- $this->path[] = $form['ty'][0];
+ $this->setOnCacheLoaded([self::class, 'onBeforeDisplay']);
}
// fetch best possible gems for chosen weights
- private function createGemScores(int $gemQuality) : array
+ private function createGemScores(int $gemQuality) : void
{
- $gemScores = [];
-
- if (!$this->filterObj->fiSetWeights)
- return [];
-
- if (!$gemQuality)
- return [];
-
- $this->sharedLV['computeDataFunc'] = '$fi_scoreSockets';
-
- $q = intVal($this->filterObj->values['gm']);
- $mask = 0xE;
- $cnd = [10, ['class', ITEM_CLASS_GEM], ['gemColorMask', &$mask, '&'], ['quality', &$q]];
- if (!$this->filterObj->values['jc'])
- $cnd[] = ['itemLimitCategory', 0]; // Jeweler's Gems
-
- If ($this->filterObj->wtCnd)
- $cnd[] = $this->filterObj->wtCnd;
-
- $anyColor = new ItemList($cnd, ['extraOpts' => $this->filterObj->extraOpts]);
- if (!$anyColor->error)
- {
- $this->extendGlobalData($anyColor->getJSGlobals());
- $gemScores[0] = array_values($anyColor->getListviewData(ITEMINFO_GEM));
- }
-
- for ($i = 0; $i < 4; $i++)
- {
- $mask = 1 << $i;
- $q = !$i ? ITEM_QUALITY_RARE : intVal($gemQuality); // meta gems are always included.. ($q is backReferenced)
- $byColor = new ItemList($cnd, ['extraOpts' => $this->filterObj->extraOpts]);
- if (!$byColor->error)
- {
- $this->extendGlobalData($byColor->getJSGlobals());
- $gemScores[$mask] = array_values($byColor->getListviewData(ITEMINFO_GEM));
- }
- }
+ if (!$this->filter->fiSetWeights)
+ return;
$this->sharedLV['onBeforeCreate'] = '$fi_initWeightedListview';
$this->sharedLV['onAfterCreate'] = '$fi_addUpgradeIndicator';
@@ -516,7 +473,38 @@ class ItemsPage extends GenericPage
array_push($this->sharedLV['hiddenCols'], 'type', 'source');
- return $gemScores;
+ if (!$gemQuality)
+ return;
+
+ $this->sharedLV['computeDataFunc'] = '$fi_scoreSockets';
+
+ $q = intVal($gemQuality);
+ $mask = 0xE;
+ $cnd = [10, ['class', ITEM_CLASS_GEM], ['gemColorMask', &$mask, '&'], ['quality', &$q]];
+ if (!isset($fiForm['jc']))
+ $cnd[] = ['itemLimitCategory', 0]; // Jeweler's Gems
+
+ if ($this->filter->wtCnd)
+ $cnd[] = $this->filter->wtCnd;
+
+ $anyColor = new ItemList($cnd, ['extraOpts' => $this->filter->extraOpts]);
+ if (!$anyColor->error)
+ {
+ $this->extendGlobalData($anyColor->getJSGlobals());
+ $this->gemScores[0] = array_values($anyColor->getListviewData(ITEMINFO_GEM));
+ }
+
+ for ($i = 0; $i < 4; $i++)
+ {
+ $mask = 1 << $i;
+ $q = !$i ? ITEM_QUALITY_RARE : intVal($gemQuality); // meta gems are always included.. ($q is backReferenced)
+ $byColor = new ItemList($cnd, ['extraOpts' => $this->filter->extraOpts]);
+ if (!$byColor->error)
+ {
+ $this->extendGlobalData($byColor->getJSGlobals());
+ $this->gemScores[$mask] = array_values($byColor->getListviewData(ITEMINFO_GEM));
+ }
+ }
}
// display available submenus 'type' and 'slot', if applicable
@@ -571,7 +559,6 @@ class ItemsPage extends GenericPage
$slotData = Lang::item('inventoryType');
$slotMask = 0x7EA;
}
-
asort($slotData);
break;
case 16:
@@ -596,12 +583,19 @@ class ItemsPage extends GenericPage
foreach ($typeData as $k => $str)
if ($str && (!$typeMask || ($typeMask & (1 << $k))))
- $this->typeList[$k] = $str;
+ $this->typeList[$k] = is_array($str) ? $str[0] : $str;
foreach ($slotData as $k => $str) // "Off Hand" => "Shield"
if ($str && (!$slotMask || ($slotMask & (1 << $k))))
$this->slotList[$k] = $k == INVTYPE_SHIELD ? Lang::item('armorSubClass', 6) : $str;
}
+
+ protected static function onBeforeDisplay() : void
+ {
+ // sort for dropdown-menus
+ Lang::sort('game', 'ra');
+ Lang::sort('game', 'cl');
+ }
}
?>
diff --git a/includes/dbtypes/enchantment.class.php b/includes/dbtypes/enchantment.class.php
index 4fbcbb64..fbe71b3a 100644
--- a/includes/dbtypes/enchantment.class.php
+++ b/includes/dbtypes/enchantment.class.php
@@ -114,7 +114,7 @@ class EnchantmentList extends DBTypeList
if (!$data[$this->id]['spells'])
unset($data[$this->id]['spells']);
- Util::arraySumByKey($data[$this->id], $this->jsonStats[$this->id]->toJson());
+ Util::arraySumByKey($data[$this->id], $this->jsonStats[$this->id]->toJson(includeEmpty: false));
}
return $data;
@@ -122,7 +122,7 @@ class EnchantmentList extends DBTypeList
public function getStatGainForCurrent() : array
{
- return $this->jsonStats[$this->id]->toJson();
+ return $this->jsonStats[$this->id]->toJson(includeEmpty: false);
}
public function getRelSpell(int $id) : ?array
diff --git a/includes/dbtypes/item.class.php b/includes/dbtypes/item.class.php
index 36333893..d8e11659 100644
--- a/includes/dbtypes/item.class.php
+++ b/includes/dbtypes/item.class.php
@@ -49,7 +49,7 @@ class ItemList extends DBTypeList
// from json to json .. the gentle fuckups of legacy code integration
$this->initJsonStats();
- $this->jsonStats[$this->id] = (new StatsContainer())->fromJson($_curTpl, true)->toJson(Stat::FLAG_ITEM /* | Stat::FLAG_SERVERSIDE */);
+ $this->jsonStats[$this->id] = (new StatsContainer())->fromJson($_curTpl, true)->toJson(Stat::FLAG_ITEM /* | Stat::FLAG_SERVERSIDE */, false);
if ($miscData)
{
@@ -723,32 +723,7 @@ class ItemList extends DBTypeList
// activation conditions for meta gems
if (!empty($gemEnch['conditionId']))
- {
- if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE `id` = ?d', $gemEnch['conditionId']))
- {
- for ($i = 1; $i < 6; $i++)
- {
- if (!$gemCnd['color'.$i])
- continue;
-
- $vspfArgs = [];
- switch ($gemCnd['comparator'.$i])
- {
- case 2: // requires less than ( || ) gems
- case 5: // requires at least than ( || ) gems
- $vspfArgs = [$gemCnd['value'.$i], Lang::item('gemColors', $gemCnd['color'.$i] - 1)];
- break;
- case 3: // requires more than ( || ) gems
- $vspfArgs = [Lang::item('gemColors', $gemCnd['color'.$i] - 1), Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1)];
- break;
- default:
- continue 2;
- }
-
- $x .= ''.Lang::achievement('reqNumCrt').' '.Lang::item('gemConditions', $gemCnd['comparator'.$i], $vspfArgs).'
';
- }
- }
- }
+ $x .= Game::getEnchantmentCondition($gemEnch['conditionId'], $interactive);
}
// Random Enchantment - if random enchantment is set, prepend stats from it
@@ -1461,6 +1436,25 @@ class ItemList extends DBTypeList
return in_array($this->curTpl['subClassBak'], [ITEM_SUBCLASS_BOW, ITEM_SUBCLASS_GUN, ITEM_SUBCLASS_THROWN, ITEM_SUBCLASS_CROSSBOW, ITEM_SUBCLASS_WAND]);
}
+ public function isBodyArmor() : bool
+ {
+ if ($this->curTpl['class'] != ITEM_CLASS_ARMOR)
+ return false;
+
+ return in_array($this->curTpl['subClassBak'], [ITEM_SUBCLASS_CLOTH_ARMOR, ITEM_SUBCLASS_LEATHER_ARMOR, ITEM_SUBCLASS_MAIL_ARMOR, ITEM_SUBCLASS_PLATE_ARMOR]);
+ }
+
+ public function isDisplayable() : bool
+ {
+ if (!$this->curTpl['displayId'])
+ return false;
+
+ return in_array($this->curTpl['slot'], array(
+ INVTYPE_HEAD, INVTYPE_SHOULDERS, INVTYPE_BODY, INVTYPE_CHEST, INVTYPE_WAIST, INVTYPE_LEGS, INVTYPE_FEET, INVTYPE_WRISTS,
+ INVTYPE_HANDS, INVTYPE_WEAPON, INVTYPE_SHIELD, INVTYPE_RANGED, INVTYPE_CLOAK, INVTYPE_2HWEAPON, INVTYPE_TABARD, INVTYPE_ROBE,
+ INVTYPE_WEAPONMAINHAND, INVTYPE_WEAPONOFFHAND, INVTYPE_HOLDABLE, INVTYPE_THROWN, INVTYPE_RANGEDRIGHT));
+ }
+
private function formatRating(int $statId, int $itemMod, int $qty, bool $interactive = false, bool &$scaling = false) : string
{
// clamp level range
@@ -1773,6 +1767,11 @@ class ItemList extends DBTypeList
class ItemListFilter extends Filter
{
+ public const /* int */ GROUP_BY_NONE = 0;
+ public const /* int */ GROUP_BY_SLOT = 1;
+ public const /* int */ GROUP_BY_LEVEL = 2;
+ public const /* int */ GROUP_BY_SOURCE = 3;
+
private array $ubFilter = []; // usable-by - limit weapon/armor selection per CharClass - itemClass => available itemsubclasses
private string $extCostQuery = 'SELECT `item` FROM npc_vendor WHERE `extendedCost` IN (?a) UNION
SELECT `item` FROM game_event_npc_vendor WHERE `extendedCost` IN (?a)';
@@ -2372,7 +2371,7 @@ class ItemListFilter extends Filter
return null;
$costs = DB::Aowow()->selectCol(
- 'SELECT `id` FROM ?_itemextendedcost WHERE `reqItemId1` IN (?a) OR `reqItemId2` IN (?a) OR `reqItemId3` IN (?a) OR `reqItemId4` IN (?a) OR `reqItemId5` IN (?a)',
+ 'SELECT `id` FROM ?_itemextendedcost WHERE `reqItemId1` IN (?a) OR `reqItemId2` IN (?a) OR `reqItemId3` IN (?a) OR `reqItemId4` IN (?a) OR `reqItemId5` IN (?a)',
$_, $_, $_, $_, $_
);
if ($items = DB::World()->selectCol($this->extCostQuery, $costs, $costs))
diff --git a/includes/dbtypes/spell.class.php b/includes/dbtypes/spell.class.php
index aaff8865..aef037c7 100644
--- a/includes/dbtypes/spell.class.php
+++ b/includes/dbtypes/spell.class.php
@@ -210,7 +210,7 @@ class SpellList extends DBTypeList
$data = []; // flat gains
foreach ($this->getStatGain() as $id => $spellData)
{
- $data[$id] = $spellData->toJson(STAT::FLAG_ITEM | STAT::FLAG_PROFILER);
+ $data[$id] = $spellData->toJson(STAT::FLAG_ITEM | STAT::FLAG_PROFILER, false);
// apply weapon restrictions
$this->getEntry($id);
diff --git a/includes/game/chrstatistics.php b/includes/game/chrstatistics.php
index 77dbe581..c1819501 100644
--- a/includes/game/chrstatistics.php
+++ b/includes/game/chrstatistics.php
@@ -487,11 +487,11 @@ class StatsContainer implements \Countable
/* Output */
/**********/
- public function toJson(int $outFlags = Stat::FLAG_NONE) : array
+ public function toJson(int $outFlags = Stat::FLAG_NONE, bool $includeEmpty = true) : array
{
$out = [];
foreach ($this->store as $stat => $amt)
- if (!$outFlags || (Stat::getFlags($stat) & $outFlags))
+ if ((!$outFlags || (Stat::getFlags($stat) & $outFlags)) && ($amt || $includeEmpty))
$out[Stat::getJsonString($stat)] = $amt;
return $out;
diff --git a/localization/locale_dede.php b/localization/locale_dede.php
index df489fdd..4244baf7 100644
--- a/localization/locale_dede.php
+++ b/localization/locale_dede.php
@@ -37,7 +37,7 @@ $lang = array(
'quickFacts' => "Kurzübersicht",
'screenshots' => "Screenshots",
'videos' => "Videos",
- 'side' => "Seite",
+ 'side' => "Seite: ",
'related' => "Weiterführende Informationen",
'contribute' => "Beitragen",
// 'replyingTo' => "Antwort zu einem Kommentar von",
@@ -73,7 +73,7 @@ $lang = array(
'refineSearch' => 'Tipp: Präzisiere deine Suche mit Durchsuchen einer Unterkategorie.',
'clear' => "leeren",
'exactMatch' => "Exakt passend",
- '_reqLevel' => "Mindeststufe",
+ '_reqLevel' => "Mindeststufe: ",
// infobox
'unavailable' => "Nicht für Spieler verfügbar",
@@ -106,12 +106,12 @@ $lang = array(
'langOnly' => "Diese Seite ist nur in %s verfügbar.",
// calculators
- 'preset' => "Vorlage",
+ 'preset' => "Vorlage: ",
'addWeight' => "Weitere Gewichtung hinzufügen",
'createWS' => "Gewichtungsverteilung erstellen",
'jcGemsOnly' => "JS-exklusive Edelsteine einschließen",
'cappedHint' => 'Tipp: Entfernt Gewichtungen für gedeckte Werte wie Trefferwertung.',
- 'groupBy' => "Ordnen nach",
+ 'groupBy' => "Ordnen nach: ",
'gb' => array(
["Nichts", "none"], ["Platz", "slot"], ["Stufe", "level"], ["Quelle", "source"]
),
@@ -345,7 +345,7 @@ $lang = array(
'reqLevel' => "Benötigt Stufe %s",
'reqSkillLevel' => "Benötigte Fertigkeitsstufe",
'school' => "Magieart",
- 'type' => "Art",
+ 'type' => "Art: ",
'valueDelim' => " - ", // " bis "
'pvp' => "PvP",
@@ -2059,7 +2059,7 @@ $lang = array(
'refundable' => "Rückzahlbar",
'noNeedRoll' => "Kann nicht für Bedarf werfen",
'atKeyring' => "Passt in den Schlüsselbund",
- 'worth' => "Wert",
+ 'worth' => "Wert: ",
'consumable' => "Verbrauchbar",
'nonConsumable' => "Nicht verbrauchbar",
'accountWide' => "Accountweit",
@@ -2068,17 +2068,17 @@ $lang = array(
'prospectable' => "Sondierbar",
'disenchantable'=> "Kann entzaubert werden",
'cantDisenchant'=> "Kann nicht entzaubert werden",
- 'repairCost' => "Reparaturkosten",
- 'tool' => "Werkzeug",
+ 'repairCost' => "Reparaturkosten: ",
+ 'tool' => "Werkzeug: ",
'cost' => "Preis",
'content' => "Inhalt",
'_transfer' => 'Dieser Gegenstand wird mit %s vertauscht, wenn Ihr zur %s wechselt.',
'_unavailable' => "Dieser Gegenstand ist nicht für Spieler verfügbar.",
'_rndEnchants' => "Zufällige Verzauberungen",
'_chance' => "(Chance von %s%%)",
- 'slot' => "Platz",
- '_quality' => "Qualität",
- 'usableBy' => "Benutzbar von",
+ 'slot' => "Platz: ",
+ '_quality' => "Qualität: ",
+ 'usableBy' => "Benutzbar von: ",
'buyout' => "Sofortkaufpreis",
'each' => "Stück",
'tabOther' => "Anderes",
@@ -2110,7 +2110,7 @@ $lang = array(
'range' => ['%1$d - %2$d Schaden', '%1$d - %2$d %3$sschaden', '+ %1$d - %2$d Schaden', '+ %1$d - %2$d %3$sschaden' ],
'ammo' => ["Verursacht %g zusätzlichen Schaden pro Sekunde.", "Verursacht %g zusätzlichen %sschaden pro Sekunde", "+ %g Schaden pro Sekunde", "+ %g %sschaden pro Sekunde"]
),
- 'gems' => "Edelsteine",
+ 'gems' => "Edelsteine: ",
'socketBonus' => "Sockelbonus: %s",
'socket' => array(
"Metasockel", "Roter Sockel", "Gelber Sockel", "Blauer Sockel", -1 => "Prismatischer Sockel"
diff --git a/localization/locale_enus.php b/localization/locale_enus.php
index 0dbf5cfb..ad214f03 100644
--- a/localization/locale_enus.php
+++ b/localization/locale_enus.php
@@ -37,7 +37,7 @@ $lang = array(
'quickFacts' => "Quick Facts",
'screenshots' => "Screenshots",
'videos' => "Videos",
- 'side' => "Side",
+ 'side' => "Side: ",
'related' => "Related",
'contribute' => "Contribute",
// 'replyingTo' => "The answer to a comment from",
@@ -73,7 +73,7 @@ $lang = array(
'refineSearch' => 'Tip: Refine your search by browsing a subcategory.',
'clear' => "clear",
'exactMatch' => "Exact match",
- '_reqLevel' => "Required level",
+ '_reqLevel' => "Required level: ",
// infobox
'unavailable' => "Not available to players", // alternative wording found: "No longer available to players" ... aw screw it <_<
@@ -106,12 +106,12 @@ $lang = array(
'langOnly' => "This page is only available in %s.",
// calculators
- 'preset' => "Preset",
+ 'preset' => "Preset: ",
'addWeight' => "Add another weight",
'createWS' => "Create a weight scale",
'jcGemsOnly' => "Include JC-only gems",
'cappedHint' => 'Tip: Remove weights for capped statistics such as Hit rating.',
- 'groupBy' => "Group By",
+ 'groupBy' => "Group By: ",
'gb' => array(
["None", "none"], ["Slot", "slot"], ["Level", "level"], ["Source", "source"]
),
@@ -345,7 +345,7 @@ $lang = array(
'reqLevel' => "Requires Level %s",
'reqSkillLevel' => "Required skill level",
'school' => "School",
- 'type' => "Type",
+ 'type' => "Type: ",
'valueDelim' => " to ",
'pvp' => "PvP", // PVP
@@ -2059,7 +2059,7 @@ $lang = array(
'refundable' => "Refundable",
'noNeedRoll' => "Cannot roll Need",
'atKeyring' => "Can be placed in the keyring",
- 'worth' => "Worth",
+ 'worth' => "Worth: ",
'consumable' => "Consumable",
'nonConsumable' => "Non-consumable",
'accountWide' => "Account-wide",
@@ -2068,17 +2068,17 @@ $lang = array(
'prospectable' => "Prospectable", // ITEM_PROSPECTABLE
'disenchantable'=> "Disenchantable", // ITEM_DISENCHANT_ANY_SKILL
'cantDisenchant'=> "Cannot be disenchanted", // ITEM_DISENCHANT_NOT_DISENCHANTABLE
- 'repairCost' => "Repair cost", // REPAIR_COST
- 'tool' => "Tool",
+ 'repairCost' => "Repair cost: ", // REPAIR_COST
+ 'tool' => "Tool: ",
'cost' => "Cost", // COSTS_LABEL
'content' => "Content",
'_transfer' => 'This item will be converted to %s if you transfer to %s.',
'_unavailable' => "This item is not available to players.",
'_rndEnchants' => "Random Enchantments",
'_chance' => "(%s%% chance)",
- 'slot' => "Slot",
- '_quality' => "Quality", // QUALITY
- 'usableBy' => "Usable by",
+ 'slot' => "Slot: ",
+ '_quality' => "Quality: ", // QUALITY
+ 'usableBy' => "Usable by: ",
'buyout' => "Buyout price", // BUYOUT_PRICE
'each' => "each",
'tabOther' => "Other",
@@ -2110,7 +2110,7 @@ $lang = array(
'range' => ["%d - %d Damage", "%d - %d %s Damage", "+ %d - %d Damage", "+%d - %d %s Damage" ],
'ammo' => ["Adds %g damage per second", "Adds %g %s damage per second", "+ %g damage per second", "+ %g %s damage per second" ]
),
- 'gems' => "Gems",
+ 'gems' => "Gems: ",
'socketBonus' => "Socket Bonus: %s", // ITEM_SOCKET_BONUS
'socket' => array( // EMPTY_SOCKET_*
"Meta Socket", "Red Socket", "Yellow Socket", "Blue Socket", -1 => "Prismatic Socket"
diff --git a/localization/locale_eses.php b/localization/locale_eses.php
index 80540f31..660fc84c 100644
--- a/localization/locale_eses.php
+++ b/localization/locale_eses.php
@@ -37,7 +37,7 @@ $lang = array(
'quickFacts' => "Notas rápidas",
'screenshots' => "Capturas de pantalla",
'videos' => "Videos",
- 'side' => "Lado",
+ 'side' => "Lado: ",
'related' => "Información relacionada",
'contribute' => "Contribuir",
// 'replyingTo' => "The answer to a comment from",
@@ -73,7 +73,7 @@ $lang = array(
'refineSearch' => 'Sugerencia: Refina tu búsqueda llendo a una subcategoría.',
'clear' => "borrar",
'exactMatch' => "Coincidencia exacta",
- '_reqLevel' => "Nivel requerido",
+ '_reqLevel' => "Nivel requerido: ",
// infobox
'unavailable' => "No está disponible a los jugadores",
@@ -106,12 +106,12 @@ $lang = array(
'langOnly' => "Esta página sólo está disponible en %s.",
// calculators
- 'preset' => "Predet.",
+ 'preset' => "Predet.: ",
'addWeight' => "Añadir otro factor",
'createWS' => "Crear escala de valores",
'jcGemsOnly' => "Incluir solo gemas de joyería",
'cappedHint' => 'Consejo: Elimina escalas para atributos al máximo como el Índice de Golpe.',
- 'groupBy' => "Agrupar por",
+ 'groupBy' => "Agrupar por: ",
'gb' => array(
["Ninguno", "none"], ["Casilla", "slot"], ["Nivel", "level"], ["Fuente", "source"]
),
@@ -345,7 +345,7 @@ $lang = array(
'reqLevel' => "Necesitas ser de nivel %s",
'reqSkillLevel' => "Requiere nivel de habilidad",
'school' => "Escuela",
- 'type' => "Tipo",
+ 'type' => "Tipo: ",
'valueDelim' => " - ",
'pvp' => "JcJ",
@@ -2059,7 +2059,7 @@ $lang = array(
'refundable' => "Se puede devolver",
'noNeedRoll' => "No se puede hacer una tirada por Necesidad",
'atKeyring' => "Se puede poner en el llavero",
- 'worth' => "Valor",
+ 'worth' => "Valor: ",
'consumable' => "Consumible",
'nonConsumable' => "No consumible",
'accountWide' => "Ligado a la cuenta",
@@ -2068,17 +2068,17 @@ $lang = array(
'prospectable' => "Prospectable",
'disenchantable'=> "Desencantable",
'cantDisenchant'=> "No se puede desencantar",
- 'repairCost' => "Coste de reparación",
- 'tool' => "Herramienta",
+ 'repairCost' => "Coste de reparación: ",
+ 'tool' => "Herramienta: ",
'cost' => "Coste",
'content' => "Contenido",
'_transfer' => 'Este objeto será convertido a %s si lo transfieres a la %s.',
'_unavailable' => "Este objeto no está disponible para los jugadores.",
'_rndEnchants' => "Encantamientos aleatorios",
'_chance' => "(probabilidad %s%%)",
- 'slot' => "Casilla",
- '_quality' => "Calidad",
- 'usableBy' => "Usable por",
+ 'slot' => "Casilla: ",
+ '_quality' => "Calidad: ",
+ 'usableBy' => "Usable por: ",
'buyout' => "Precio de venta en subasta",
'each' => "cada uno",
'tabOther' => "Otros",
@@ -2110,7 +2110,7 @@ $lang = array(
"range" => ["%d - %d Daño", "%d - %d daño de %s", "+ %d: %d daño", "+%d - %d daño de %s" ],
'ammo' => ["Añade %g daño por segundo", "Añade %g %s daño por segundo", "+ %g daño por segundo", "+ %g %s daño por segundo"]
),
- 'gems' => "Gemas",
+ 'gems' => "Gemas: ",
'socketBonus' => "Bono de ranura: %s",
'socket' => array(
"Ranura meta", "Ranura roja", "Ranura amarilla", "Ranura azul", -1 => "Ranura prismática"
diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php
index 96eb30a4..6cc43e08 100644
--- a/localization/locale_frfr.php
+++ b/localization/locale_frfr.php
@@ -37,7 +37,7 @@ $lang = array(
'quickFacts' => "En bref",
'screenshots' => "Captures d'écran",
'videos' => "Vidéos",
- 'side' => "Coté",
+ 'side' => "Coté : ",
'related' => "Informations connexes",
'contribute' => "Contribuer",
// 'replyingTo' => "En réponse au commentaire de",
@@ -73,7 +73,7 @@ $lang = array(
'refineSearch' => "Astuce : Affinez votre recherche en utilisant une sous-catégorie.",
'clear' => "effacer",
'exactMatch' => "Concordance exacte",
- '_reqLevel' => "Niveau requis",
+ '_reqLevel' => "Niveau requis : ",
// infobox
'unavailable' => "Non disponible aux joueurs",
@@ -106,12 +106,12 @@ $lang = array(
'langOnly' => "Cette page n'est disponible qu'en %s pour le moment.",
// calculators
- 'preset' => "Prédéterminée",
+ 'preset' => "Prédéterminée : ",
'addWeight' => "Ajouter un autre facteur",
'createWS' => "Créer une échelle de valeurs",
'jcGemsOnly' => "Inclure les gemmes de joaillier",
'cappedHint' => 'Conseil: Enlever un facteur pour les statistiques au maximum tel que le score de touche.',
- 'groupBy' => "Groupé par",
+ 'groupBy' => "Groupé par : ",
'gb' => array(
["Aucun", "none"], ["Emplacement", "slot"], ["Niveau", "level"], ["Source", "source"]
),
@@ -345,7 +345,7 @@ $lang = array(
'reqLevel' => "Niveau %s requis",
'reqSkillLevel' => "Niveau de compétence requis",
'school' => "École",
- 'type' => "Type",
+ 'type' => "Type : ",
'valueDelim' => " - ",
'pvp' => "JcJ",
@@ -2059,7 +2059,7 @@ $lang = array(
'refundable' => "Remboursable",
'noNeedRoll' => "Ne peut pas faire un jet de Besoin",
'atKeyring' => "Va dans le trousseau de clés",
- 'worth' => "Vaut",
+ 'worth' => "Vaut : ",
'consumable' => "Consommable",
'nonConsumable' => "Non-consommable",
'accountWide' => "Portant sur le compte",
@@ -2068,17 +2068,17 @@ $lang = array(
'prospectable' => "Prospectable",
'disenchantable'=> "Desencantable",
'cantDisenchant'=> "Ne peut pas être désenchanté",
- 'repairCost' => "Cout de réparation",
- 'tool' => "Outil",
+ 'repairCost' => "Cout de réparation : ",
+ 'tool' => "Outil : ",
'cost' => "Coût",
'content' => "Contenu",
'_transfer' => 'Cet objet sera converti en %s si vous transférez en %s.',
'_unavailable' => "Cet objet n'est pas disponible pour les joueurs.",
'_rndEnchants' => "Enchantements aléatoires",
'_chance' => "(%s%% de chance)",
- 'slot' => "Emplacement",
- '_quality' => "Qualité",
- 'usableBy' => "Utilisable par",
+ 'slot' => "Emplacement : ",
+ '_quality' => "Qualité : ",
+ 'usableBy' => "Utilisable par : ",
'buyout' => "Vente immédiate",
'each' => "chacun",
'tabOther' => "Autre",
@@ -2110,7 +2110,7 @@ $lang = array(
'range' => ["Dégâts : %d - %d", "%d - %d points de dégâts (%s)", "+ %d - %d points de dégâts", "+%d - %d points de dégâts (%s)" ],
'ammo' => ["Ajoute %g dégâts par seconde", "Ajoute %g points de dégâts (%s) par seconde", "+ %g points de dégâts par seconde", "+ %g points de dégâts (%s) par seconde" ]
),
- 'gems' => "Gemmes",
+ 'gems' => "Gemmes : ",
'socketBonus' => "Bonus de châsse: %s",
'socket' => array(
"Méta-châsse", "Châsse rouge", "Châsse jaune", "Châsse bleue", -1 => "Châsse prismatique"
diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php
index 24c97f08..79f6c974 100644
--- a/localization/locale_ruru.php
+++ b/localization/locale_ruru.php
@@ -37,7 +37,7 @@ $lang = array(
'quickFacts' => "Краткая информация",
'screenshots' => "Изображения",
'videos' => "Видео",
- 'side' => "Сторона",
+ 'side' => "Сторона: ",
'related' => "Дополнительная информация",
'contribute' => "Добавить",
// 'replyingTo' => "Ответ на комментарий от",
@@ -73,7 +73,7 @@ $lang = array(
'refineSearch' => 'Совет: Уточните поиск, добавив подкатегорию.',
'clear' => "Очистить",
'exactMatch' => "Полное совпадение",
- '_reqLevel' => "Требуется уровень",
+ '_reqLevel' => "Требуется уровень: ",
// infobox
'unavailable' => "Недоступно игрокам",
@@ -106,12 +106,12 @@ $lang = array(
'langOnly' => "Эта страница доступна только на %s языке.",
// calculators
- 'preset' => "Готовая таблица",
+ 'preset' => "Готовая таблица: ",
'addWeight' => "Добавить фильтр значимости",
'createWS' => "Отсортировать по значимости",
'jcGemsOnly' => "Использовать ювелирские",
'cappedHint' => 'Подсказка: Удалите характеристики с капом (например, меткость).',
- 'groupBy' => "Группировать",
+ 'groupBy' => "Группировать: ",
'gb' => array(
['Нет', 'none'], ['Слот', 'slot'], ['Уровень', 'level'], ['Источник', 'source']
),
@@ -345,7 +345,7 @@ $lang = array(
'reqLevel' => "Требуется уровень: %s",
'reqSkillLevel' => "Требуется уровень навыка",
'school' => "Школа",
- 'type' => "Тип",
+ 'type' => "Тип: ",
'valueDelim' => " - ",
'pvp' => "PvP",
@@ -2059,7 +2059,7 @@ $lang = array(
'refundable' => "Подлежит возврату",
'noNeedRoll' => 'Нельзя говорить "Мне это нужно"',
'atKeyring' => "Может быть помещён в связку для ключей",
- 'worth' => "Деньги",
+ 'worth' => "Деньги: ",
'consumable' => "Расходуется",
'nonConsumable' => "Не расходуется",
'accountWide' => "Привязано к учетной записи",
@@ -2068,17 +2068,17 @@ $lang = array(
'prospectable' => "Просеиваемое",
'disenchantable'=> "Распыляемый",
'cantDisenchant'=> "Нельзя распылить",
- 'repairCost' => "Цена починки",
- 'tool' => "Инструмент",
+ 'repairCost' => "Цена починки: ",
+ 'tool' => "Инструмент: ",
'cost' => "Цена",
'content' => "Материал",
'_transfer' => 'Этот предмет превратится в %s, если вы перейдете за %s.',
'_unavailable' => "Этот предмет не доступен игрокам.",
'_rndEnchants' => "Случайные улучшения",
'_chance' => "(шанс %s%%)",
- 'slot' => "Слот",
- '_quality' => "Качество",
- 'usableBy' => "Используется (кем)",
+ 'slot' => "Слот: ",
+ '_quality' => "Качество: ",
+ 'usableBy' => "Используется (кем): ",
'buyout' => "Цена выкупа",
'each' => "каждый",
'tabOther' => "Другое",
@@ -2111,7 +2111,7 @@ $lang = array(
'range' => ["Урон: %d - %d", "%d - %d ед. |3-6(%s)", "+ %d - %d ед. урона", "+%d - %d ед. урона (%s)" ],
'ammo' => ["Добавляет %g ед. урона в секунду", "Добавляет %g ед. урона (%s) в секунду", "+ ед. урона в секунду от боеприпасов (%g)", "+ %g %s ед. урона в секунду" ]
),
- 'gems' => "Самоцветы",
+ 'gems' => "Самоцветы: ",
'socketBonus' => "При соответствии цвета: %s",
'socket' => array(
"Особое гнездо", "Красное гнездо", "Желтое гнездо", "Синее гнездо", -1 => "Бесцветное гнездо"
diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php
index aec6c216..666689dd 100644
--- a/localization/locale_zhcn.php
+++ b/localization/locale_zhcn.php
@@ -37,7 +37,7 @@ $lang = array(
'quickFacts' => "相关信息",
'screenshots' => "屏幕截图",
'videos' => "视频",
- 'side' => "阵营",
+ 'side' => "阵营:",
'related' => "相关",
'contribute' => "贡献",
// 'replyingTo' => "The answer to a comment from",
@@ -73,7 +73,7 @@ $lang = array(
'refineSearch' => '提示:通过浏览 子类别搜索。',
'clear' => "清除",
'exactMatch' => "精确匹配",
- '_reqLevel' => "要求等级",
+ '_reqLevel' => "要求等级:",
// infobox
'unavailable' => "对玩家不可用", // alternative wording found: "No longer available to players" ... aw screw it <_<
@@ -106,12 +106,12 @@ $lang = array(
'langOnly' => "该页面仅以%s提供。",
// calculators
- 'preset' => "预设",
+ 'preset' => "预设:",
'addWeight' => "添加另一个权重",
'createWS' => "创建一个权重比例",
'jcGemsOnly' => "包含JC-only宝石",
'cappedHint' => '提示:移除 命中等级等上限属性的权重。',
- 'groupBy' => "按组",
+ 'groupBy' => "按组:",
'gb' => array(
["无", "none"], ["插槽", "slot"], ["等级", "level"], ["来源", "source"]
),
@@ -344,7 +344,7 @@ $lang = array(
'reqLevel' => "需要等级%s",
'reqSkillLevel' => "需要技能等级",
'school' => "类型",
- 'type' => "类型",
+ 'type' => "类型:",
'valueDelim' => "到",
'pvp' => "PvP",
@@ -2058,7 +2058,7 @@ $lang = array(
'refundable' => "可退还的",
'noNeedRoll' => "无法需求掷骰",
'atKeyring' => "可以放在钥匙链",
- 'worth' => "价值",
+ 'worth' => "价值:",
'consumable' => "消耗品",
'nonConsumable' => "非消耗品",
'accountWide' => "账号共享",
@@ -2067,17 +2067,17 @@ $lang = array(
'prospectable' => "可选矿",
'disenchantable'=> "可分解",
'cantDisenchant'=> "无法分解",
- 'repairCost' => "修理费用",
- 'tool' => "工具",
+ 'repairCost' => "修理费用:",
+ 'tool' => "工具:",
'cost' => "花费",
'content' => "内容",
'_transfer' => '这个物品将被转换到%s,如果你转移到%s。',
'_unavailable' => "这个物品对玩家不可用。",
'_rndEnchants' => "随机附魔",
'_chance' => "(%s%%几率)",
- 'slot' => "装备部位",
- '_quality' => "品质",
- 'usableBy' => "可用职业",
+ 'slot' => "装备部位:",
+ '_quality' => "品质:",
+ 'usableBy' => "可用职业:",
'buyout' => "一口价",
'each' => "每个",
'tabOther' => "其他",
@@ -2109,7 +2109,7 @@ $lang = array(
'range' => ["%d - %d伤害", "%d - %d 点%s伤害", "+ %d - %d伤害", "+%d - %d 点%s伤害" ],
'ammo' => ["每秒伤害提高%g", "每秒增加%g点%s系伤害", "每秒伤害+%g", "每秒+%g点%s伤害" ]
),
- 'gems' => "宝石",
+ 'gems' => "宝石:",
'socketBonus' => "镶孔奖励:%s",
'socket' => array(
"多彩插槽", "红色插槽", "黄色插槽", "蓝色插槽", -1 => "棱彩插槽"
diff --git a/setup/tools/filegen/itemsets.ss.php b/setup/tools/filegen/itemsets.ss.php
index 514b5f7f..0280f2ec 100644
--- a/setup/tools/filegen/itemsets.ss.php
+++ b/setup/tools/filegen/itemsets.ss.php
@@ -101,7 +101,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (!$itemQty || !$itemSpl || !isset($jsonBonus[$itemSpl]))
continue;
- if ($x = $jsonBonus[$itemSpl]->toJson(Stat::FLAG_ITEM))
+ if ($x = $jsonBonus[$itemSpl]->toJson(Stat::FLAG_ITEM, false))
{
if (!isset($setbonus[$itemQty]))
$setbonus[$itemQty] = [];
diff --git a/static/js/locale_dede.js b/static/js/locale_dede.js
index 68a054cb..7ee34a44 100644
--- a/static/js/locale_dede.js
+++ b/static/js/locale_dede.js
@@ -1283,7 +1283,8 @@ var g_item_subclasses = {
8: 'Verzauberkunstformel',
9: 'Angelbuch',
10: 'Juwelenschleifer-Vorlage',
- 11: 'Inschriften-Technik'
+ 11: 'Inschriften-Technik',
+ 12: 'Bergbauleitfäden'
},
11: {
2: 'Köcher',
diff --git a/static/js/locale_enus.js b/static/js/locale_enus.js
index c60dbdbf..a06c0c6f 100644
--- a/static/js/locale_enus.js
+++ b/static/js/locale_enus.js
@@ -1330,7 +1330,8 @@ var g_item_subclasses = {
8: 'Enchanting Formula',
9: 'Fishing Book',
10: 'Jewelcrafting Design',
- 11: 'Inscription Technique'
+ 11: 'Inscription Technique',
+ 12: 'Mining Guides'
},
11: {
2: 'Quiver',
diff --git a/static/js/locale_eses.js b/static/js/locale_eses.js
index 8cabdf1f..e4f82e5a 100644
--- a/static/js/locale_eses.js
+++ b/static/js/locale_eses.js
@@ -1283,7 +1283,8 @@ var g_item_subclasses = {
8: 'Fórmula de encantamiento',
9: 'Libro de pesca',
10: 'Boceto de joyería',
- 11: 'Técnica de Inscripción'
+ 11: 'Técnica de Inscripción',
+ 12: 'Guías de minería'
},
11: {
2: 'Carcaj',
diff --git a/static/js/locale_frfr.js b/static/js/locale_frfr.js
index b2f16454..42128086 100644
--- a/static/js/locale_frfr.js
+++ b/static/js/locale_frfr.js
@@ -1283,7 +1283,8 @@ var g_item_subclasses = {
8: 'Formule d\'enchantement',
9: 'Livre de pêche',
10: 'Dessin de joaillerie',
- 11: 'Technique de calligraphie'
+ 11: 'Technique de calligraphie',
+ 12: 'Guides de Minage'
},
11: {
2: 'Carquois',
diff --git a/static/js/locale_ruru.js b/static/js/locale_ruru.js
index bb57d724..8851c21b 100644
--- a/static/js/locale_ruru.js
+++ b/static/js/locale_ruru.js
@@ -1283,7 +1283,8 @@ var g_item_subclasses = {
8: 'Зачаровывание',
9: 'Рыбная ловля',
10: 'Ювелирное дело',
- 11: 'Технология Начертания'
+ 11: 'Технология Начертания',
+ 12: 'Руководства по Шахтерскому делу'
},
11: {
2: 'Колчан',
diff --git a/static/js/locale_zhcn.js b/static/js/locale_zhcn.js
index c21fdcbd..53d7cfda 100644
--- a/static/js/locale_zhcn.js
+++ b/static/js/locale_zhcn.js
@@ -1330,6 +1330,7 @@ var g_item_subclasses = {
9: "钓鱼书籍",
10: "宝石加工设计",
11: "铭文技能",
+ 12: "采矿指南"
},
11: {
2: '箭袋',
diff --git a/template/bricks/tooltip.tpl.php b/template/bricks/tooltip.tpl.php
index d4d3e29c..358ecfcf 100644
--- a/template/bricks/tooltip.tpl.php
+++ b/template/bricks/tooltip.tpl.php
@@ -1,5 +1,10 @@
-
+tooltip;
+?>
@@ -7,8 +12,6 @@
jsGlobals[Type::SPELL][2][$this->typeId]['buff']); // not set with items
-
if ($hasBuff):
?>
=Lang::spell('_aura'); ?>
@@ -25,7 +28,7 @@ endif;
?>