diff --git a/includes/types/itemset.class.php b/includes/types/itemset.class.php
index 7fdc4d3c..ece86b0e 100644
--- a/includes/types/itemset.class.php
+++ b/includes/types/itemset.class.php
@@ -136,7 +136,8 @@ class ItemsetListFilter extends Filter
// name [str]
if (isset($_v['na']))
- $parts[] = ['name_loc'.User::$localeId, $_v['na']];
+ if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
+ $parts[] = $_;
// quality [enum]
if (isset($_v['qu']))
diff --git a/pages/class.php b/pages/class.php
index c3856b71..9e535f99 100644
--- a/pages/class.php
+++ b/pages/class.php
@@ -38,7 +38,7 @@ class ClassPage extends GenericPage
protected function generateTitle()
{
- array_unshift($this->title, $this->subject->getField('name', true), Util::ucFirst(Lang::$game['class']));
+ array_unshift($this->title, $this->name, Util::ucFirst(Lang::$game['class']));
}
protected function generateContent()
diff --git a/pages/itemset.php b/pages/itemset.php
index 499cf9c4..e1596f46 100644
--- a/pages/itemset.php
+++ b/pages/itemset.php
@@ -4,278 +4,272 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-require 'includes/community.class.php';
-
-$_id = intVal($pageParam);
-$path = [0, 2];
-
-$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_ITEMSET, $_id, -1, User::$localeId]);
-
-if (!$smarty->loadCache($cacheKeyPage, $pageData))
+// menuId 2: Itemset g_initPath()
+// tabId 0: Database g_initHeader()
+class ItemsetPage extends GenericPage
{
- $iSet = new ItemsetList(array(['id', $_id]));
- if ($iSet->error)
- $smarty->notFound(Lang::$game['itemset'], $_id);
+ use DetailPage;
- $_ta = $iSet->getField('contentGroup');
- $_ty = $iSet->getField('type');
- $_ev = $iSet->getField('holidayId');
- $_sk = $iSet->getField('skillId');
- $_cl = $iSet->getField('classMask');
- $_lvl = $iSet->getField('reqLevel');
- $_na = $iSet->getField('name', true);
- $_cnt = count($iSet->getField('pieces'));
+ protected $type = TYPE_ITEMSET;
+ protected $typeId = 0;
+ protected $tpl = 'itemset';
+ protected $path = [0, 2];
+ protected $tabId = 0;
+ protected $mode = CACHETYPE_PAGE;
+ protected $js = array(
+ 'swfobject.js',
+ 'Summary.js'
+ );
- /***********/
- /* Infobox */
- /***********/
-
- $infobox = [];
- // unavailable (todo (low): set data)
- if ($iSet->getField('cuFlags') & CUSTOM_UNAVAILABLE)
- $infobox[] = Lang::$main['unavailable'];
-
- // holiday
- if ($_ev)
- $infobox[] = Lang::$game['eventShort'].Lang::$main['colon'].'[url=?event='.$_ev.']'.WorldEventList::getName($_ev).'[/url]';
-
- // itemLevel
- if ($min = $iSet->getField('minLevel'))
+ public function __construct($__, $id)
{
- $foo = Lang::$game['level'].Lang::$main['colon'].$min;
- $max = $iSet->getField('maxLevel');
+ parent::__construct();
- if ($min < $max)
- $foo .= ' - '.$max;
+ $this->typeId = intVal($id);
- $infobox[] = $foo;
+ $this->subject = new ItemsetList(array(['id', $this->typeId]));
+ if ($this->subject->error)
+ $this->notFound(Lang::$game['itemset']);
+
+ $this->name = $this->subject->getField('name', true);
+ $this->extendGlobalData($this->subject->getJSGlobals());
}
- // class
- if ($_cl)
+ protected function generatePath()
{
- $foo = [];
- for ($i = 0; $i < 11; $i++)
- if ($_cl & (1 << $i))
- $foo[] = (!fMod(count($foo) + 1, 3) ? '\n' : null) . '[class='.($i + 1).']';
-
- $t = count($foo) == 1 ? Lang::$game['class'] : Lang::$game['classes'];
- $infobox[] = Util::ucFirst($t).Lang::$main['colon'].implode(', ', $foo);
- }
-
- // required level
- if ($_lvl)
- $infobox[] = sprintf(Lang::$game['reqLevel'], $_lvl);
-
- // type
- if ($_ty)
- $infobox[] = Lang::$game['type'].Lang::$main['colon'].Lang::$itemset['types'][$_ty];
-
- // tag
- if ($_ta)
- $infobox[] = Lang::$itemset['_tag'].Lang::$main['colon'].'[url=?itemsets&filter=ta='.$_ta.']'.Lang::$itemset['notes'][$_ta].'[/url]';
-
- /****************/
- /* Main Content */
- /****************/
-
- // pieces + Summary
- $pieces = [];
- $eqList = [];
- $compare = [];
-
- if (!$iSet->pieceToSet)
- $cnd = [0];
- else
- $cnd = ['i.id', array_keys($iSet->pieceToSet)];
-
- $iList = new ItemList(array($cnd));
- $data = $iList->getListviewData(ITEMINFO_SUBITEMS | ITEMINFO_JSON);
- foreach ($iList->iterate() as $itemId => $__)
- {
- if (empty($data[$itemId]))
- continue;
-
- $slot = $iList->getField('slot');
- $disp = $iList->getField('displayId');
- if ($slot && $disp)
- $eqList[] = [$slot, $disp];
-
- $compare[] = $itemId;
-
- $pieces[] = array(
- 'id' => $itemId,
- 'name' => $iList->getField('name', true),
- 'quality' => $iList->getField('quality'),
- 'icon' => $iList->getField('iconString'),
- 'json' => json_encode($data[$itemId], JSON_NUMERIC_CHECK)
- );
- }
-
- // spells
- $foo = [];
- $spells = [];
- for ($i = 1; $i < 9; $i++)
- {
- $spl = $iSet->getField('spell'.$i);
- $qty = $iSet->getField('bonus'.$i);
-
- if ($spl && $qty)
+ if ($_ = $this->subject->getField('classMask'))
{
- $foo[] = $spl;
- $spells[] = array( // cant use spell as index, would change order
- 'id' => $spl,
- 'bonus' => $qty,
- 'desc' => ''
- );
+ $bit = log($_, 2);
+ if (intVal($bit) != $bit) // bit is float => multiple classes were set => skip out
+ return;
+
+ $this->path[] = $bit + 1;
}
}
- // sort by required pieces ASC
- usort($spells, function($a, $b) {
- if ($a['bonus'] == $b['bonus'])
- return 0;
-
- return ($a['bonus'] > $b['bonus']) ? 1 : -1;
- });
-
- $setSpells = new SpellList(array(['s.id', $foo]));
- foreach ($setSpells->iterate() as $spellId => $__)
+ protected function generateTitle()
{
- foreach ($spells as &$s)
+ array_unshift($this->title, $this->name, Util::ucFirst(Lang::$game['itemset']));
+ }
+
+ protected function generateContent()
+ {
+ $_ta = $this->subject->getField('contentGroup');
+ $_ty = $this->subject->getField('type');
+ $_cnt = count($this->subject->getField('pieces'));
+
+ /***********/
+ /* Infobox */
+ /***********/
+
+ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
+
+ // unavailable (todo (low): set data)
+ if ($this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE)
+ $infobox[] = Lang::$main['unavailable'];
+
+ // holiday
+ if ($h = $this->subject->getField('holidayId'))
{
- if ($spellId != $s['id'])
+ $infobox[] = Lang::$game['eventShort'].Lang::$main['colon'].'[event='.$h.']';
+ $this->extendGlobalIds(TYPE_GAMEVENT, $h);
+ }
+
+ // itemLevel
+ if ($min = $this->subject->getField('minLevel'))
+ {
+ $foo = Lang::$game['level'].Lang::$main['colon'].$min;
+ $max = $this->subject->getField('maxLevel');
+
+ if ($min < $max)
+ $foo .= ' - '.$max;
+
+ $infobox[] = $foo;
+ }
+
+ // class
+ if ($cl = Lang::getClassString($this->subject->getField('classMask'), $jsg, $qty, false))
+ {
+ $this->extendGlobalIds(TYPE_CLASS, $jsg);
+ $t = $qty == 1 ? Lang::$game['class'] : Lang::$game['classes'];
+ $infobox[] = Util::ucFirst($t).Lang::$main['colon'].$cl;
+ }
+
+ // required level
+ if ($lvl = $this->subject->getField('reqLevel'))
+ $infobox[] = sprintf(Lang::$game['reqLevel'], $lvl);
+
+ // type
+ if ($_ty)
+ $infobox[] = Lang::$game['type'].Lang::$main['colon'].Lang::$itemset['types'][$_ty];
+
+ // tag
+ if ($_ta)
+ $infobox[] = Lang::$itemset['_tag'].Lang::$main['colon'].'[url=?itemsets&filter=ta='.$_ta.']'.Lang::$itemset['notes'][$_ta].'[/url]';
+
+ /****************/
+ /* Main Content */
+ /****************/
+
+ // pieces + Summary
+ $pieces = [];
+ $eqList = [];
+ $compare = [];
+
+ if (!$this->subject->pieceToSet)
+ $cnd = [0];
+ else
+ $cnd = ['i.id', array_keys($this->subject->pieceToSet)];
+
+ $iList = new ItemList(array($cnd));
+ $data = $iList->getListviewData(ITEMINFO_SUBITEMS | ITEMINFO_JSON);
+ foreach ($iList->iterate() as $itemId => $__)
+ {
+ if (empty($data[$itemId]))
continue;
- $s['desc'] = $setSpells->parseText('description')[0];
+ $slot = $iList->getField('slot');
+ $disp = $iList->getField('displayId');
+ if ($slot && $disp)
+ $eqList[] = [$slot, $disp];
+
+ $compare[] = $itemId;
+
+ $pieces[] = array(
+ 'id' => $itemId,
+ 'name' => $iList->getField('name', true),
+ 'quality' => $iList->getField('quality'),
+ 'icon' => $iList->getField('iconString'),
+ 'json' => $data[$itemId]
+ );
}
- }
- // path
- if ($_cl)
- {
- for ($i = 0; $i < 11; $i++)
+ // spells
+ $foo = [];
+ $spells = [];
+ for ($i = 1; $i < 9; $i++)
{
- if ($_cl & (1 << $i))
- {
- if ($_cl == (1 << $i)) // only bit set, add path
- $path[] = $i + 1;
+ $spl = $this->subject->getField('spell'.$i);
+ $qty = $this->subject->getField('bonus'.$i);
- break; // break anyway (cant set multiple classes)
+ if ($spl && $qty)
+ {
+ $foo[] = $spl;
+ $spells[] = array( // cant use spell as index, would change order
+ 'id' => $spl,
+ 'bonus' => $qty,
+ 'desc' => ''
+ );
+ }
+ }
+
+ // sort by required pieces ASC
+ usort($spells, function($a, $b) {
+ if ($a['bonus'] == $b['bonus'])
+ return 0;
+
+ return ($a['bonus'] > $b['bonus']) ? 1 : -1;
+ });
+
+ $setSpells = new SpellList(array(['s.id', $foo]));
+ foreach ($setSpells->iterate() as $spellId => $__)
+ {
+ foreach ($spells as &$s)
+ {
+ if ($spellId != $s['id'])
+ continue;
+
+ $s['desc'] = $setSpells->parseText('description')[0];
+ }
+ }
+
+ $skill = '';
+ if ($_sk = $this->subject->getField('skillId'))
+ {
+ $spellLink = sprintf('%s (%s)', $_sk, Lang::$spell['cat'][11][$_sk][0], $this->subject->getField('skillLevel'));
+ $skill = ' – '.sprintf(Lang::$game['requires'], $spellLink).'';
+ }
+
+ $this->bonusExt = $skill;
+ $this->description = $_ta ? sprintf(Lang::$itemset['_desc'], $this->name, Lang::$itemset['notes'][$_ta], $_cnt) : sprintf(Lang::$itemset['_descTagless'], $this->name, $_cnt);
+ $this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE;
+ $this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
+ $this->pieces = $pieces;
+ $this->spells = $spells;
+ $this->expansion = 0;
+ $this->redButtons = array(
+ BUTTON_WOWHEAD => $this->typeId > 0, // bool only
+ BUTTON_LINKS => ['color' => '', 'linkId' => ''],
+ BUTTON_VIEW3D => ['type' => TYPE_ITEMSET, 'typeId' => $this->typeId, 'equipList' => $eqList],
+ BUTTON_COMPARE => ['eqList' => implode(':', $compare), 'qty' => $_cnt]
+ );
+ $this->compare = array(
+ 'level' => $this->subject->getField('reqLevel'),
+ 'items' => array_map(function ($v) {
+ return [[$v]];
+ }, $compare)
+ );
+
+ /**************/
+ /* Extra Tabs */
+ /**************/
+
+ // related sets (priority: 1: similar tag + class; 2: has event; 3: no tag + similar type, 4: similar type + profession)
+ $rel = [];
+
+ if ($_ta && count($this->path) == 3)
+ {
+ $rel[] = ['id', $this->typeId, '!'];
+ $rel[] = ['classMask', 1 << (end($this->path) - 1), '&'];
+ $rel[] = ['contentGroup', (int)$_ta];
+ }
+ else if ($this->subject->getField('holidayId'))
+ {
+ $rel[] = ['id', $this->typeId, '!'];
+ $rel[] = ['holidayId', 0, '!'];
+ }
+ else if ($this->subject->getField('skillId'))
+ {
+ $rel[] = ['id', $this->typeId, '!'];
+ $rel[] = ['contentGroup', 0];
+ $rel[] = ['skillId', 0, '!'];
+ $rel[] = ['type', $_ty];
+ }
+ else if (!$_ta && $_ty)
+ {
+ $rel[] = ['id', $this->typeId, '!'];
+ $rel[] = ['contentGroup', 0];
+ $rel[] = ['type', $_ty];
+ $rel[] = ['skillId', 0];
+ }
+
+ if ($rel)
+ {
+ $relSets = new ItemsetList($rel);
+ if (!$relSets->error)
+ {
+ $lv = array(
+ 'file' => 'itemset',
+ 'data' => $relSets->getListviewData(),
+ 'params' => array(
+ 'id' => 'see-also',
+ 'name' => '$LANG.tab_seealso',
+ 'tabs' => '$tabsRelated'
+ )
+ );
+
+ if (!$relSets->hasDiffFields(['classMask']))
+ $lv['params']['hiddenCols'] = "$['classes']";
+
+ $this->lvData[] = $lv;
+
+ $this->extendGlobalData($relSets->getJSGlobals());
}
}
}
-
- $skill = '';
- if ($_sk)
- {
- $spellLink = sprintf('%s (%s)', $_sk, Lang::$spell['cat'][11][$_sk][0], $iSet->getField('skillLevel'));
- $skill = ' – '.sprintf(Lang::$game['requires'], $spellLink).'';
- }
-
- // menuId 2: Itemset g_initPath()
- // tabId 0: Database g_initHeader()
- $pageData = array(
- 'page' => array(
- 'name' => $_na, // for page content
- 'bonusExt' => $skill,
- 'description' => $_ta ? sprintf(Lang::$itemset['_desc'], $_na, Lang::$itemset['notes'][$_ta], $_cnt) : sprintf(Lang::$itemset['_descTagless'], $_na, $_cnt),
- 'unavailable' => (bool)($iSet->getField('cuFlags') & CUSTOM_UNAVAILABLE),
- 'infobox' => $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null,
- 'title' => $_na." - ".Util::ucfirst(Lang::$game['itemset']),
- 'path' => json_encode($path, JSON_NUMERIC_CHECK),
- 'tab' => 0,
- 'type' => TYPE_ITEMSET,
- 'typeId' => $_id,
- 'reqJS' => array(
- STATIC_URL.'/js/Summary.js',
- STATIC_URL.'/js/swfobject.js'
- ),
- 'pieces' => $pieces,
- 'spells' => $spells,
- 'redButtons' => array(
- BUTTON_WOWHEAD => $_id > 0, // bool only
- BUTTON_LINKS => ['color' => '', 'linkId' => ''],
- BUTTON_VIEW3D => ['type' => TYPE_ITEMSET, 'typeId' => $_id, 'equipList' => $eqList],
- BUTTON_COMPARE => ['eqList' => implode(':', $compare), 'qty' => $_cnt]
- ),
- 'compare' => array(
- 'qty' => $_cnt,
- 'items' => $compare,
- 'level' => $_lvl
- ),
- ),
- 'relTabs' => []
- );
-
- $iSet->getJSGlobals();
-
- /**************/
- /* Extra Tabs */
- /**************/
-
- // related sets (priority: 1: similar tag + class; 2: has event; 3: no tag + similar type, 4: similar type + profession)
- $rel = [];
-
- if ($_ta && count($path) == 3)
- {
- $rel[] = ['id', $_id, '!'];
- $rel[] = ['classMask', 1 << (end($path) - 1), '&'];
- $rel[] = ['contentGroup', (int)$_ta];
- }
- else if ($_ev)
- {
- $rel[] = ['id', $_id, '!'];
- $rel[] = ['holidayId', 0, '!'];
- }
- else if ($_sk)
- {
- $rel[] = ['id', $_id, '!'];
- $rel[] = ['contentGroup', 0];
- $rel[] = ['skillId', 0, '!'];
- $rel[] = ['type', $_ty];
- }
- else if (!$_ta && $_ty)
- {
- $rel[] = ['id', $_id, '!'];
- $rel[] = ['contentGroup', 0];
- $rel[] = ['type', $_ty];
- $rel[] = ['skillId', 0];
- }
-
- if ($rel)
- {
- $relSets = new ItemsetList($rel);
- if (!$relSets->error)
- {
- $pageData['relTabs'][] = array(
- 'file' => 'itemset',
- 'data' => $relSets->getListviewData(),
- 'params' => array(
- 'id' => 'see-also',
- 'name' => '$LANG.tab_seealso',
- 'tabs' => '$tabsRelated'
- )
- );
-
- $mask = $relSets->hasDiffFields(['classMask']);
- if (!$mask)
- $pageData['related']['params']['hiddenCols'] = "$['classes']";
-
- $relSets->getJSGlobals();
- }
- }
-
- $smarty->saveCache($cacheKeyPage, $pageData);
}
-$smarty->updatePageVars($pageData['page']);
-$smarty->assign('community', CommunityContent::getAll(TYPE_ITEMSET, $_id)); // comments, screenshots, videos
-$smarty->assign('lang', array_merge(Lang::$main, Lang::$itemset, ['colon' => Lang::$main['colon']]));
-$smarty->assign('lvData', $pageData['relTabs']);
-// load the page
-$smarty->display('itemset.tpl');
?>
diff --git a/pages/itemsets.php b/pages/itemsets.php
index b364bce4..3a528bca 100644
--- a/pages/itemsets.php
+++ b/pages/itemsets.php
@@ -4,76 +4,83 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-$filter = [];
-$path = [0, 2];
-$filterHash = !empty($_GET['filter']) ? sha1(serialize($_GET['filter'])) : -1;
-$cacheKey = implode('_', [CACHETYPE_PAGE, TYPE_ITEMSET, -1, $filterHash, User::$localeId]);
-
-if (!$smarty->loadCache($cacheKey, $pageData, $filter))
+// menuId 2: Itemset g_initPath()
+// tabId 0: Database g_initHeader()
+class ItemsetsPage extends GenericPage
{
- $itemsetFilter = new ItemsetListFilter();
+ use ListPage;
- $itemsets = new ItemsetList([$itemsetFilter->getConditions()]);
- $itemsets->getJSGlobals();
+ protected $type = TYPE_ITEMSET;
+ protected $tpl = 'itemsets';
+ protected $path = [0, 2];
+ protected $tabId = 0;
+ protected $mode = CACHETYPE_PAGE;
+ protected $js = ['filters.js'];
- // recreate form selection
- $filter = array_merge($itemsetFilter->getForm('form'), $filter);
- $filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
- $filter['fi'] = $itemsetFilter->getForm();
-
- if (isset($filter['cl']))
- $path[] = $filter['cl'];
-
- // menuId 2: Itemset g_initPath()
- // tabId 0: Database g_initHeader()
- $pageData = array(
- 'page' => array(
- 'title' => Util::ucFirst(Lang::$game['itemsets']),
- 'path' => json_encode($path, JSON_NUMERIC_CHECK),
- 'tab' => 0,
- 'subCat' => $pageParam ? '='.$pageParam : '',
- 'reqJS' => array(
- STATIC_URL.'/js/filters.js',
- '?data=weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']
- )
- ),
- 'lv' => []
- );
-
- $lv = array(
- 'data' => $itemsets->getListviewData(), // listview content
- 'params' => []
- );
-
- if (!empty($filter['fi']['extraCols']))
- $lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
-
- // create note if search limit was exceeded
- if ($itemsets->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ public function __construct($pageCall, $pageParam)
{
- $lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsetsfound', $itemsets->getMatches(), CFG_SQL_LIMIT_DEFAULT);
- $lv['params']['_truncated'] = 1;
+ $this->getCategoryFromUrl($pageParam);;
+
+ parent::__construct();
+
+ $this->name = Util::ucFirst(Lang::$game['itemsets']);
}
- if ($itemsetFilter->error)
- $lv['params']['_errors'] = '$1';
+ protected function generateContent()
+ {
+ $itemsetFilter = new ItemsetListFilter();
- $pageData['lv'] = $lv;
+ $itemsets = new ItemsetList($itemsetFilter->getConditions());
+ $this->extendGlobalData($itemsets->getJSGlobals());
- $smarty->saveCache($cacheKey, $pageData, $filter);
+ // recreate form selection
+ $this->filter = array_merge($itemsetFilter->getForm('form'), $this->filter);
+ $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
+ $this->filter['fi'] = $itemsetFilter->getForm();
+
+ $this->addJS('?data=weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
+
+ $lv = array(
+ 'file' => 'itemset',
+ 'data' => $itemsets->getListviewData(), // listview content
+ 'params' => []
+ );
+
+ if (!empty($this->filter['fi']['extraCols']))
+ $lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
+
+ // create note if search limit was exceeded
+ if ($itemsets->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ {
+ $lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsetsfound', $itemsets->getMatches(), CFG_SQL_LIMIT_DEFAULT);
+ $lv['params']['_truncated'] = 1;
+ }
+
+ if ($itemsetFilter->error)
+ $lv['params']['_errors'] = '$1';
+
+ $this->lvData = $lv;
+
+ // sort for dropdown-menus
+ asort(Lang::$itemset['notes'], SORT_NATURAL);
+ asort(Lang::$game['cl']);
+ }
+
+ protected function generateTitle()
+ {
+ array_unshift($this->title, $this->name);
+
+ $form = (new ItemsetListFilter())->getForm('form');
+ if (isset($form['cl']))
+ array_unshift($this->title, Lang::$game['cl'][$form['cl']]);
+ }
+
+ protected function generatePath()
+ {
+ $form = (new ItemsetListFilter())->getForm('form');
+ if (isset($form['cl']))
+ $this->path[] = $form['cl'];
+ }
}
-
-// sort for dropdown-menus
-asort(Lang::$itemset['notes'], SORT_NATURAL);
-asort(Lang::$game['cl']);
-
-$smarty->updatePageVars($pageData['page']);
-$smarty->assign('filter', $filter);
-$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$itemset, Lang::$item, ['colon' => Lang::$main['colon']]));
-$smarty->assign('lvData', $pageData['lv']);
-
-// load the page
-$smarty->display('itemsets.tpl');
-
?>
diff --git a/pages/npc.php b/pages/npc.php
index d83f3b89..f18299ce 100644
--- a/pages/npc.php
+++ b/pages/npc.php
@@ -4,248 +4,674 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-require 'includes/community.class.php';
-
-$_id = intVal($pageParam);
-$_path = [0, 4];
-$_altIds = [];
-$_altNPCs = null;
-
-$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_NPC, $_id, -1, User::$localeId]);
-$cacheKeyTooltip = implode('_', [CACHETYPE_TOOLTIP, TYPE_NPC, $_id, -1, User::$localeId]);
-
-// AowowPower-request
-if (isset($_GET['power']))
+// menuId 4: NPC g_initPath()
+// tabId 0: Database g_initHeader()
+class NpcPage extends GenericPage
{
- header('Content-type: application/x-javascript; charsetUTF-8');
+ use DetailPage;
- Util::powerUseLocale(@$_GET['domain']);
+ protected $type = TYPE_NPC;
+ protected $typeId = 0;
+ protected $tpl = 'npc';
+ protected $path = [0, 4];
+ protected $tabId = 0;
+ protected $mode = CACHETYPE_PAGE;
+ protected $js = array(
+ 'swfobject.js',
+ // 'Mapper.js'
+ );
+ protected $css = array(
+ // ['path' => 'Mapper.css'],
+ // ['path' => 'Mapper_ie6.css', 'ieCond' => 'lte IE 6']
+ );
- if (!$smarty->loadCache($cacheKeyTooltip, $x))
+ public function __construct($__, $id)
{
- $npc = new CreatureList(array(['ct.id', $_id]));
- if ($npc->error)
- die('$WowheadPower.registerNpc('.$_id.', '.User::$localeId.', {})');
+ parent::__construct();
- $s = $npc->getSpawns(true);
+ // temp locale
+ if ($this->mode == CACHETYPE_TOOLTIP && isset($_GET['domain']))
+ Util::powerUseLocale($_GET['domain']);
- $x = '$WowheadPower.registerNpc('.$_id.', '.User::$localeId.", {\n";
- $x .= "\tname_".User::$localeString.": '".Util::jsEscape($npc->getField('name', true))."',\n";
- $x .= "\ttooltip_".User::$localeString.": '".Util::jsEscape($npc->renderTooltip())."',\n";
+ $this->typeId = intVal($id);
+
+ $this->subject = new CreatureList(array(['id', $this->typeId]));
+ if ($this->subject->error)
+ $this->notFound(Lang::$game['npc']);
+
+ $this->name = $this->subject->getField('name', true);
+ $this->subname = $this->subject->getField('subname', true);
+ }
+
+ protected function generatePath()
+ {
+ $this->path[] = $this->subject->getField('type');
+
+ if ($_ = $this->subject->getField('family'))
+ $this->path[] = $_;
+ }
+
+ protected function generateTitle()
+ {
+ array_unshift($this->title, $this->name, Util::ucFirst(Lang::$game['npc']));
+ }
+
+ protected function generateContent()
+ {
+ $_typeFlags = $this->subject->getField('typeFlags');
+ $_altIds = [];
+ $_altNPCs = null;
+ $position = null;
+
+ // difficulty entries of self
+ if ($this->subject->getField('cuFlags') & NPC_CU_DIFFICULTY_DUMMY)
+ {
+ // find and create link to regular creature
+ $regNPC = new CreatureList(array(['OR', ['difficultyEntry1', $this->typeId], ['difficultyEntry2', $this->typeId], ['difficultyEntry3', $this->typeId]]));
+ $position = [$regNPC->id, $regNPC->getField('name', true)];
+ }
+ else
+ {
+ for ($i = 1; $i < 4; $i++)
+ if ($_ = $this->subject->getField('difficultyEntry'.$i))
+ $_altIds[$_] = $i;
+
+ if ($_altIds)
+ $_altNPCs = new CreatureList(array(['id', array_keys($_altIds)]));
+ }
+
+ // hmm, this won't do if the creature is spawned by event/script
+ $mapType = 2; // should be 0, tmp-override until Zones
+ // $maps = DB::Aowow()->selectCol('SELECT DISTINCT map from creature WHERE id = ?d', $this->typeId);
+ // if (count($maps) == 1) // should only exist in one instance
+ // {
+ // $map = new ZoneList(array(1, ['mapId', $maps[0]], ['parentArea', 0]));
+ // $mapType = $map->getField('areaType');
+ // }
+
+ /***********/
+ /* Infobox */
+ /***********/
+
+ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
+
+ // Event
+ if ($_ = DB::Aowow()->selectRow('SELECT e.id, holidayId FROM ?_events e, game_event_creature gec, creature c WHERE e.id = ABS(gec.eventEntry) AND c.guid = gec.guid AND c.id = ?d', $this->typeId))
+ {
+ if ($h = $_['holidayId'])
+ {
+ Util::$pageTemplate->extendGlobalIds(TYPE_WORLDEVENT, $_['id']);
+ $infobox[] = Util::ucFirst(Lang::$game['eventShort']).Lang::$main['colon'].'[event='.$h.']';
+ }
+ }
+
+ // Level
+ if ($this->subject->getField('rank') != NPC_RANK_BOSS)
+ {
+ $level = $this->subject->getField('minLevel');
+ $maxLvl = $this->subject->getField('maxLevel');
+ if ($level < $maxLvl)
+ $level .= ' - '.$maxLvl;
+ }
+ else // Boss Level
+ $level = '??';
+
+ $infobox[] = Lang::$game['level'].Lang::$main['colon'].$level;
+
+ // Classification
+ if ($_ = $this->subject->getField('rank')) // != NPC_RANK_NORMAL
+ {
+ $str = $_typeFlags & 0x4 ? '[span class=icon-boss]'.Lang::$npc['rank'][$_].'[/span]' : Lang::$npc['rank'][$_];
+ $infobox[] = Lang::$npc['classification'].Lang::$main['colon'].$str;
+ }
+
+ // Reaction
+ $_ = function ($r)
+ {
+ if ($r == 1) return 2;
+ if ($r == -1) return 10;
+ return;
+ };
+ $infobox[] = Lang::$npc['react'].Lang::$main['colon'].'[color=q'.$_($this->subject->getField('A')).']A[/color] [color=q'.$_($this->subject->getField('H')).']H[/color]';
+
+ // Faction
+ $this->extendGlobalIds(TYPE_FACTION, $this->subject->getField('factionId'));
+ $infobox[] = Util::ucFirst(Lang::$game['faction']).Lang::$main['colon'].'[faction='.$this->subject->getField('factionId').']';
+
+ // Wealth
+ if ($_ = intVal(($this->subject->getField('minGold') + $this->subject->getField('maxGold')) / 2))
+ $infobox[] = Lang::$npc['worth'].Lang::$main['colon'].'[tooltip=tooltip_avgmoneydropped][money='.$_.'][/tooltip]';
+
+ // is Vehicle
+ if ($this->subject->getField('vehicleId'))
+ $infobox[] = Lang::$npc['vehicle'];
+
+ // AI
+ if (User::isInGroup(U_GROUP_EMPLOYEE))
+ {
+ if ($_ = $this->subject->getField('scriptName'))
+ $infobox[] = 'Script'.Lang::$main['colon'].$_;
+ else if ($_ = $this->subject->getField('aiName'))
+ $infobox[] = 'AI'.Lang::$main['colon'].$_;
+ }
+
+ // > Stats
+ $_nf = function ($num) { return number_format($num, 0, '', '.'); };
+ $stats = [];
+ $modes = []; // get difficulty versions if set
+ $hint = '[tooltip name=%3$s][table cellspacing=10][tr]%1s[/tr][/table][/tooltip][span class=tip tooltip=%3$s]%2s[/span]';
+ $modeRow = '[tr][td]%s [/td][td]%s[/td][/tr]';
+ // Health
+ $health = $this->subject->getBaseStats('health');
+ $stats['health'] = Util::ucFirst(Lang::$spell['powerTypes'][-2]).Lang::$main['colon'].($health[0] < $health[1] ? $_nf($health[0]).' - '.$_nf($health[1]) : $_nf($health[0]));
+
+ // Mana (may be 0)
+ $mana = $this->subject->getBaseStats('power');
+ $stats['mana'] = $mana[0] ? Lang::$spell['powerTypes'][0].Lang::$main['colon'].($mana[0] < $mana[1] ? $_nf($mana[0]).' - '.$_nf($mana[1]) : $_nf($mana[0])) : null;
+
+ // Armor
+ $armor = $this->subject->getBaseStats('armor');
+ $stats['armor'] = Lang::$npc['armor'].Lang::$main['colon'].($armor[0] < $armor[1] ? $_nf($armor[0]).' - '.$_nf($armor[1]) : $_nf($armor[0]));
+
+ // Melee Damage
+ $melee = $this->subject->getBaseStats('melee');
+ if ($_ = $this->subject->getField('dmgSchool')) // magic damage
+ $stats['melee'] = Lang::$npc['melee'].Lang::$main['colon'].$_nf($melee[0]).' - '.$_nf($melee[1]).' ('.Lang::$game['sc'][$_].')';
+ else // phys. damage
+ $stats['melee'] = Lang::$npc['melee'].Lang::$main['colon'].$_nf($melee[0]).' - '.$_nf($melee[1]);
+
+ // Ranged Damage
+ $ranged = $this->subject->getBaseStats('ranged');
+ $stats['ranged'] = Lang::$npc['ranged'].Lang::$main['colon'].$_nf($ranged[0]).' - '.$_nf($ranged[1]);
+
+ if (in_array($mapType, [1, 2])) // Dungeon or Raid
+ {
+ foreach ($_altIds as $id => $mode)
+ {
+ foreach ($_altNPCs->iterate() as $dId => $__)
+ {
+ if ($dId != $id)
+ continue;
+
+ $m = Lang::$npc['modes'][$mapType][$mode];
+
+ // Health
+ $health = $_altNPCs->getBaseStats('health');
+ $modes['health'][] = sprintf($modeRow, $m, $health[0] < $health[1] ? $_nf($health[0]).' - '.$_nf($health[1]) : $_nf($health[0]));
+
+ // Mana (may be 0)
+ $mana = $_altNPCs->getBaseStats('power');
+ $modes['mana'][] = $mana[0] ? sprintf($modeRow, $m, $mana[0] < $mana[1] ? $_nf($mana[0]).' - '.$_nf($mana[1]) : $_nf($mana[0])) : null;
+
+ // Armor
+ $armor = $_altNPCs->getBaseStats('armor');
+ $modes['armor'][] = sprintf($modeRow, $m, $armor[0] < $armor[1] ? $_nf($armor[0]).' - '.$_nf($armor[1]) : $_nf($armor[0]));
+
+ // Melee Damage
+ $melee = $_altNPCs->getBaseStats('melee');
+ if ($_ = $_altNPCs->getField('dmgSchool')) // magic damage
+ $modes['melee'][] = sprintf($modeRow, $m, $_nf($melee[0]).' - '.$_nf($melee[1]).' ('.Lang::$game['sc'][$_].')');
+ else // phys. damage
+ $modes['melee'][] = sprintf($modeRow, $m, $_nf($melee[0]).' - '.$_nf($melee[1]));
+
+ // Ranged Damage
+ $ranged = $_altNPCs->getBaseStats('ranged');
+ $modes['ranged'][] = sprintf($modeRow, $m, $_nf($ranged[0]).' - '.$_nf($ranged[1]));
+ }
+ }
+ }
+
+ if ($modes)
+ foreach ($stats as $k => $v)
+ if ($v)
+ $stats[$k] = sprintf($hint, implode('[/tr][tr]', $modes[$k]), $v, $k);
+
+ // < Stats
+ if ($stats)
+ $infobox[] = Lang::$npc['stats'].($modes ? ' ('.Lang::$npc['modes'][$mapType][0].')' : null).Lang::$main['colon'].'[ul][li]'.implode('[/li][li]', $stats).'[/li][/ul]';
+
+ /****************/
+ /* Main Content */
+ /****************/
+
+ // get spawns and such
+
+ // consider phaseMasks
+
+ // consider pooled spawns
+
+ // $this->mapper = true,
+ $this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
+ $this->position = $position;
+ $this->quotes = $this->getQuotes();
+ $this->reputation = $this->getOnKillRep($_altIds, $mapType);
+ $this->redButtons = array(
+ BUTTON_WOWHEAD => true,
+ BUTTON_LINKS => true,
+ BUTTON_VIEW3D => ['type' => TYPE_NPC, 'typeId' => $this->typeId, 'displayId' => $this->subject->getRandomModelId()]
+ );
+
+ /**************/
+ /* Extra Tabs */
+ /**************/
+
+ // tab: SAI
+ // hmm, how should this loot like
+
+ // tab: abilities / tab_controlledabilities (dep: VehicleId)
+ // SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86
+ $smartSpells = DB::Aowow()->selectCol('SELECT action_param1 FROM smart_scripts WHERE source_type = 0 AND action_type IN (11, 75, 85, 86) AND entryOrGUID = ?d', $this->typeId);
+ $tplSpells = [];
+ $conditions = ['OR'];
+
+ for ($i = 1; $i < 9; $i++)
+ if ($_ = $this->subject->getField('spell'.$i))
+ $tplSpells[] = $_;
+
+ if ($tplSpells)
+ $conditions[] = ['id', $tplSpells];
+
+ if ($smartSpells)
+ $conditions[] = ['id', $smartSpells];
+
+ if ($tplSpells || $smartSpells)
+ {
+ $abilities = new SpellList($conditions);
+ if (!$abilities->error)
+ {
+ $this->extendGlobalData($abilities->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
+ $normal = $abilities->getListviewData();
+ $controled = [];
+
+ if ($this->subject->getField('vehicleId')) // not quite right. All seats should be checked for allowed-to-cast-flag-something
+ {
+ foreach ($normal as $id => $values)
+ {
+ if (in_array($id, $smartSpells))
+ continue;
+
+ $controled[$id] = $values;
+ unset($normal[$id]);
+ }
+ }
+
+ if ($normal)
+ $this->lvData[] = array(
+ 'file' => 'spell',
+ 'data' => $normal,
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_abilities',
+ 'id' => 'abilities'
+ ]
+ );
+
+ if ($controled)
+ $this->lvData[] = array(
+ 'file' => 'spell',
+ 'data' => $controled,
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_controlledabilities',
+ 'id' => 'controlled-abilities'
+ ]
+ );
+ }
+ }
+
+ // tab: summoned by
+ $conditions = array(
+ 'OR',
+ ['AND', ['effect1Id', 28], ['effect1MiscValue', $this->typeId]],
+ ['AND', ['effect2Id', 28], ['effect2MiscValue', $this->typeId]],
+ ['AND', ['effect3Id', 28], ['effect3MiscValue', $this->typeId]]
+ );
+
+ $summoned = new SpellList($conditions);
+ if (!$summoned->error)
+ {
+ $this->extendGlobalData($summoned->getJSGlobals());
+
+ $this->lvData[] = array(
+ 'file' => 'spell',
+ 'data' => $summoned->getListviewData(),
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_summonedby',
+ 'id' => 'summoned-by'
+ ]
+ );
+ }
+
+ // tab: teaches
+ if ($this->subject->getField('npcflag') & NPC_FLAG_TRAINER)
+ {
+ $teachQuery = 'SELECT IFNULL(t2.spell, t1.spell) AS ARRAY_KEY, IFNULL(t2.spellcost, t1.spellcost) AS cost, IFNULL(t2.reqskill, t1.reqskill) AS reqSkillId,
+ IFNULL(t2.reqskillvalue, t1.reqskillvalue) AS reqSkillValue, IFNULL(t2.reqlevel, t1.reqlevel) AS reqLevel
+ FROM npc_trainer t1 LEFT JOIN npc_trainer t2 ON t2.entry = IF(t1.spell < 0, -t1.spell, null) WHERE t1.entry = ?d';
+
+ if ($tSpells = DB::Aowow()->select($teachQuery, $this->typeId))
+ {
+ $teaches = new SpellList(array(['id', array_keys($tSpells)]));
+ if (!$teaches->error)
+ {
+ $this->extendGlobalData($teaches->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
+ $data = $teaches->getListviewData();
+
+ $extra = [];
+ foreach ($tSpells as $sId => $train)
+ {
+ if (empty($data[$sId]))
+ continue;
+
+ if ($_ = $train['reqSkillId'])
+ {
+ $this->extendGlobalIds(TYPE_SKILL, $_);
+ if (!isset($extra[0]))
+ $extra[0] = 'Listview.extraCols.condition';
+
+ $data[$sId]['condition'][] = ['type' => TYPE_SKILL, 'typeId' => $_, 'status' => 1, 'reqSkillLvl' => $train['reqSkillValue']];
+ }
+
+ if ($_ = $train['reqLevel'])
+ {
+ if (!isset($extra[1]))
+ $extra[1] = "Listview.funcBox.createSimpleCol('reqLevel', LANG.tooltip_reqlevel, '7%', 'reqLevel')";
+
+ $data[$sId]['reqLevel'] = $_;
+ }
+
+ if ($_ = $train['cost'])
+ $data[$sId]['trainingcost'] = $_;
+ }
+
+ $this->lvData[] = array(
+ 'file' => 'spell',
+ 'data' => $data,
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_teaches',
+ 'id' => 'teaches',
+ 'visibleCols' => "$['trainingcost']",
+ 'extraCols' => $extra ? '$['.implode(', ', $extra).']' : null
+ ]
+ );
+ }
+ }
+ else
+ Util::addNote(U_GROUP_EMPLOYEE, 'NPC '.$this->typeId.' is flagged as trainer, but doesn\'t have any spells set');
+ }
+
+ // tab: sells
+ if ($sells = DB::Aowow()->selectCol('SELECT item FROM npc_vendor nv WHERE entry = ?d UNION SELECT item FROM game_event_npc_vendor genv JOIN creature c ON genv.guid = c.guid WHERE c.id = ?d', $this->typeId, $this->typeId))
+ {
+ $soldItems = new ItemList(array(['id', $sells]));
+ if (!$soldItems->error)
+ {
+ $this->extendGlobalData($soldItems->getJSGlobals());
+
+ $this->lvData[] = array(
+ 'file' => 'item',
+ 'data' => $soldItems->getListviewData(ITEMINFO_VENDOR, [TYPE_NPC => $this->typeId]),
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_sells',
+ 'id' => 'currency-for',
+ 'extraCols' => "$[Listview.extraCols.condition, Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack'), Listview.extraCols.cost]"
+ ]
+ );
+ }
+ }
+
+ // tabs: this creature contains..
+ $skinTab = ['tab_skinning', 'skinned-from'];
+ if ($_typeFlags & NPC_TYPEFLAG_HERBLOOT)
+ $skinTab = ['tab_gatheredfromnpc', 'gathered-from-npc'];
+ else if ($_typeFlags & NPC_TYPEFLAG_MININGLOOT)
+ $skinTab = ['tab_minedfromnpc', 'mined-from-npc'];
+ else if ($_typeFlags & NPC_TYPEFLAG_ENGINEERLOOT)
+ $skinTab = ['tab_salvagedfrom', 'salvaged-from-npc'];
+
+ /*
+ extraCols: [Listview.extraCols.count, Listview.extraCols.percent, Listview.extraCols.mode],
+ _totalCount: 22531,
+ computeDataFunc: Listview.funcBox.initLootTable,
+ onAfterCreate: Listview.funcBox.addModeIndicator,
+
+ modes:{"mode":1,"1":{"count":4408,"outof":16013},"4":{"count":4408,"outof":22531}}
+ */
+
+ $sourceFor = array(
+ [LOOT_CREATURE, $this->subject->getField('lootId'), '$LANG.tab_drops', 'drops', ['Listview.extraCols.percent'], [] , []],
+ [LOOT_PICKPOCKET, $this->subject->getField('pickpocketLootId'), '$LANG.tab_pickpocketing', 'pickpocketing', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
+ [LOOT_SKINNING, $this->subject->getField('skinLootId'), '$LANG.'.$skinTab[0], $skinTab[1], ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []]
+ );
+
+ // temp: manually add loot for difficulty-versions
+ $langref = array(
+ "-2" => '$LANG.tab_heroic',
+ "-1" => '$LANG.tab_normal',
+ 1 => '$$WH.sprintf(LANG.tab_normalX, 10)',
+ 2 => '$$WH.sprintf(LANG.tab_normalX, 25)',
+ 3 => '$$WH.sprintf(LANG.tab_heroicX, 10)',
+ 4 => '$$WH.sprintf(LANG.tab_heroicX, 25)'
+ );
+
+ if ($_altIds)
+ {
+ $sourceFor[0][2] = $langref[1];
+ foreach ($_altNPCs->iterate() as $id => $__)
+ {
+ $mode = $_altIds[$id];
+ array_splice($sourceFor, 1, 0, [[LOOT_CREATURE, $_altNPCs->getField('lootId'), $langref[$mode + 1], 'drops-'.$mode, ['Listview.extraCols.percent'], [], []]]);
+ }
+ }
+
+ $reqQuest = [];
+ foreach ($sourceFor as $sf)
+ {
+ $creatureLoot = new Loot();
+ if ($creatureLoot->getByContainer($sf[0], $sf[1]))
+ {
+ if ($_ = $creatureLoot->extraCols)
+ $sf[4] = array_merge($sf[4], $_);
+
+ $this->extendGlobalData($creatureLoot->jsGlobals);
+
+ foreach ($creatureLoot->iterate() as &$lv)
+ {
+ if (!$lv['quest'])
+ continue;
+
+ $sf[4][] = 'Listview.extraCols.condition';
+ $reqQuest[$lv['id']] = 0;
+ $lv['condition'][] = ['type' => TYPE_QUEST, 'typeId' => &$reqQuest[$lv['id']], 'status' => 1];
+ }
+
+ $this->lvData[] = array(
+ 'file' => 'item',
+ 'data' => $creatureLoot->getResult(),
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => $sf[2],
+ 'id' => $sf[3],
+ 'extraCols' => $sf[4] ? "$[".implode(', ', array_unique($sf[4]))."]" : null,
+ 'hiddenCols' => $sf[5] ? "$".json_encode($sf[5]) : null,
+ 'visibleCols' => $sf[6] ? '$'.json_encode($sf[6]) : null,
+ 'sort' => "$['-percent', 'name']",
+ ]
+ );
+ }
+ }
+
+ if ($reqIds = array_keys($reqQuest)) // apply quest-conditions as back-reference
+ {
+ $conditions = array(
+ 'OR',
+ ['reqSourceItemId1', $reqIds], ['reqSourceItemId2', $reqIds],
+ ['reqSourceItemId3', $reqIds], ['reqSourceItemId4', $reqIds],
+ ['reqItemId1', $reqIds], ['reqItemId2', $reqIds], ['reqItemId3', $reqIds],
+ ['reqItemId4', $reqIds], ['reqItemId5', $reqIds], ['reqItemId6', $reqIds]
+ );
+
+ $reqQuests = new QuestList($conditions);
+ $this->extendGlobalData($reqQuests->getJSGlobals());
+
+ foreach ($reqQuests->iterate() as $qId => $__)
+ {
+ if (empty($reqQuests->requires[$qId][TYPE_ITEM]))
+ continue;
+
+ foreach ($reqIds as $rId)
+ if (in_array($rId, $reqQuests->requires[$qId][TYPE_ITEM]))
+ $reqQuest[$rId] = $reqQuests->id;
+ }
+ }
+
+ // tab: starts quest
+ // tab: ends quest
+ $startEnd = new QuestList(array(['qse.type', TYPE_NPC], ['qse.typeId', $this->typeId]));
+ if (!$startEnd->error)
+ {
+ $this->extendGlobalData($startEnd->getJSGlobals());
+ $lvData = $startEnd->getListviewData();
+ $_ = [[], []];
+
+ foreach ($startEnd->iterate() as $id => $__)
+ {
+ $m = $startEnd->getField('method');
+ if ($m & 0x1)
+ $_[0][] = $lvData[$id];
+ if ($m & 0x2)
+ $_[1][] = $lvData[$id];
+ }
+
+ if ($_[0])
+ {
+ $this->lvData[] = array(
+ 'file' => 'quest',
+ 'data' => $_[0],
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_starts',
+ 'id' => 'starts'
+ ]
+ );
+ }
+
+ if ($_[1])
+ {
+ $this->lvData[] = array(
+ 'file' => 'quest',
+ 'data' => $_[1],
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_ends',
+ 'id' => 'ends'
+ ]
+ );
+ }
+ }
+
+ // tab: objective of quest
+ $conditions = array(
+ 'OR',
+ ['AND', ['reqNpcOrGo1', $this->typeId], ['reqNpcOrGoCount1', 0, '>']],
+ ['AND', ['reqNpcOrGo2', $this->typeId], ['reqNpcOrGoCount2', 0, '>']],
+ ['AND', ['reqNpcOrGo3', $this->typeId], ['reqNpcOrGoCount3', 0, '>']],
+ ['AND', ['reqNpcOrGo4', $this->typeId], ['reqNpcOrGoCount4', 0, '>']],
+ );
+
+ $objectiveOf = new QuestList($conditions);
+ if (!$objectiveOf->error)
+ {
+ $this->extendGlobalData($objectiveOf->getJSGlobals());
+
+ $this->lvData[] = array(
+ 'file' => 'quest',
+ 'data' => $objectiveOf->getListviewData(),
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_objectiveof',
+ 'id' => 'objective-of'
+ ]
+ );
+ }
+
+ // tab: criteria of [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE have no data set to check for]
+ $conditions = array(
+ ['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE]],
+ ['ac.value1', $this->typeId]
+ );
+
+ $crtOf = new AchievementList($conditions);
+ if (!$crtOf->error)
+ {
+ $this->extendGlobalData($crtOf->getJSGlobals());
+
+ $this->lvData[] = array(
+ 'file' => 'achievement',
+ 'data' => $crtOf->getListviewData(),
+ 'params' => [
+ 'tabs' => '$tabsRelated',
+ 'name' => '$LANG.tab_criteriaof',
+ 'id' => 'criteria-of'
+ ]
+ );
+ }
+ }
+
+ protected function generateTooltip($asError = false)
+ {
+ if ($asError)
+ return '$WowheadPower.registerNpc('.$this->typeId.', '.User::$localeId.', {})';
+
+ $s = $this->subject->getSpawns(true);
+
+ $x = '$WowheadPower.registerNpc('.$this->typeId.', '.User::$localeId.", {\n";
+ $x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true))."',\n";
+ $x .= "\ttooltip_".User::$localeString.": '".Util::jsEscape($this->subject->renderTooltip())."',\n";
// $x .= "\tmap: ".($s ? '{zone: '.$s[0].', coords: {0:'.json_encode($s[1], JSON_NUMERIC_CHECK).'}}' : '{}')."\n";
$x .= "});";
- $smarty->saveCache($cacheKeyTooltip, $x);
+ return $x;
}
- die($x);
-}
-
-// regular page
-if (!$smarty->loadCache($cacheKeyPage, $pageData))
-{
- $npc = new CreatureList(array(['ct.id', $_id]));
- if ($npc->error)
- $smarty->notFound(Lang::$game['npc'], $_id);
-
- // reconstruct path
- $_path[] = $npc->getField('type');
-
- $_typeFlags = $npc->getField('typeFlags');
- $_name = $npc->getField('name', true);
-
- if ($_ = $npc->getField('family'))
- $_path[] = $_;
-
- $position = null;
-
- // difficulty entrys of self
- if ($npc->getField('cuFlags') & NPC_CU_DIFFICULTY_DUMMY)
+ public function display($override = '')
{
- // find and create link to regular creature
- $regNPC = new CreatureList(array(['OR', ['difficultyEntry1', $_id], ['difficultyEntry2', $_id], ['difficultyEntry3', $_id]]));
- $position = [$regNPC->id, $regNPC->getField('name', true)];
- }
- else
- {
- for ($i = 1; $i < 4; $i++)
- if ($_ = $npc->getField('difficultyEntry'.$i))
- $_altIds[$_] = $i;
+ if ($this->mode != CACHETYPE_TOOLTIP)
+ return parent::display($override);
- if ($_altIds)
- $_altNPCs = new CreatureList(array(['id', array_keys($_altIds)]));
- }
-
- // hmm, this won't do, if th creature is spawned by event/script
- $mapType = 0;
- $maps = DB::Aowow()->selectCol('SELECT DISTINCT map from creature WHERE id = ?d', $_id);
- if (count($maps) == 1) // should only exist in one instance
- {
- $map = new ZoneList(array(1, ['mapId', $maps[0]]));
- $mapType = $map->getField('areaType'); //NYI
- }
-
- /***********/
- /* Infobox */
- /***********/
-
- $infobox = [];
-
- // Event
- if ($_ = DB::Aowow()->selectRow('SELECT e.id, holidayId FROM ?_events e, game_event_creature gec, creature c WHERE e.id = ABS(gec.eventEntry) AND c.guid = gec.guid AND c.id = ?d', $_id))
- {
- if ($h = $_['holidayId'])
+ if (!$this->loadCache($tt))
{
- Util::$pageTemplate->extendGlobalIds(TYPE_WORLDEVENT, $_['id']);
- $infobox[] = Util::ucFirst(Lang::$game['eventShort']).Lang::$colon.'[event='.$h.']';
+ $tt = $this->generateTooltip();
+ $this->saveCache($tt);
}
+
+ header('Content-type: application/x-javascript; charset=utf-8');
+ die($tt);
}
- // Level
- if ($npc->getField('rank') != NPC_RANK_BOSS)
+ public function notFound($typeStr)
{
- $level = $npc->getField('minLevel');
- $maxLvl = $npc->getField('maxLevel');
- if ($level < $maxLvl)
- $level .= ' - '.$maxLvl;
- }
- else // Boss Level
- $level = '??';
+ if ($this->mode != CACHETYPE_TOOLTIP)
+ return parent::notFound($typeStr);
- $infobox[] = Lang::$game['level'].Lang::$colon.$level;
-
- // Classification
- if ($_ = $npc->getField('rank')) // != NPC_RANK_NORMAL
- {
- $str = $_typeFlags & 0x4 ? '[span class=icon-boss]'.Lang::$npc['rank'][$_].'[/span]' : Lang::$npc['rank'][$_];
- $infobox[] = Lang::$npc['classification'].Lang::$colon.$str;
+ header('Content-type: application/x-javascript; charset=utf-8');
+ echo $this->generateTooltip(true);
+ exit();
}
- // Reaction
- $_ = function ($r)
- {
- if ($r == 1) return 2;
- if ($r == -1) return 10;
- return;
- };
- $infobox[] = Lang::$npc['react'].Lang::$colon.'[color=q'.$_($npc->getField('A')).']A[/color] [color=q'.$_($npc->getField('H')).']H[/color]';
-
- // Faction
- Util::$pageTemplate->extendGlobalIds(TYPE_FACTION, $npc->getField('factionId'));
- $infobox[] = Util::ucFirst(Lang::$game['faction']).Lang::$colon.'[faction='.$npc->getField('factionId').']';
-
- // Wealth
- if ($_ = intVal(($npc->getField('minGold') + $npc->getField('maxGold')) / 2))
- $infobox[] = Lang::$npc['worth'].Lang::$colon.'[tooltip=tooltip_avgmoneydropped][money='.$_.'][/tooltip]';
-
- // is Vehicle
- if ($npc->getField('vehicleId'))
- $infobox[] = Lang::$npc['vehicle'];
-
- // AI
- if (User::isInGroup(U_GROUP_STAFF))
- {
- if ($_ = $npc->getField('scriptName'))
- $infobox[] = 'Script'.Lang::$colon.$_;
- else if ($_ = $npc->getField('aiName'))
- $infobox[] = 'AI'.Lang::$colon.$_;
- }
-
- // > Stats
- $_nf = function ($num) { return number_format($num, 0, '', '.'); };
- $stats = [];
- $modes = []; // get difficulty versions if set
- $hint = '[tooltip name=%3$s][table cellspacing=10][tr]%1s[/tr][/table][/tooltip][span class=tip tooltip=%3$s]%2s[/span]';
- $modeRow = '[tr][td]%s [/td][td]%s[/td][/tr]';
- // Health
- $health = $npc->getBaseStats('health');
- $stats['health'] = Util::ucFirst(Lang::$spell['powerTypes'][-2]).Lang::$colon.($health[0] < $health[1] ? $_nf($health[0]).' - '.$_nf($health[1]) : $_nf($health[0]));
-
- // Mana (may be 0)
- $mana = $npc->getBaseStats('power');
- $stats['mana'] = $mana[0] ? Lang::$spell['powerTypes'][0].Lang::$colon.($mana[0] < $mana[1] ? $_nf($mana[0]).' - '.$_nf($mana[1]) : $_nf($mana[0])) : null;
-
- // Armor
- $armor = $npc->getBaseStats('armor');
- $stats['armor'] = Lang::$npc['armor'].Lang::$colon.($armor[0] < $armor[1] ? $_nf($armor[0]).' - '.$_nf($armor[1]) : $_nf($armor[0]));
-
- // Melee Damage
- $melee = $npc->getBaseStats('melee');
- if ($_ = $npc->getField('dmgSchool')) // magic damage
- $stats['melee'] = Lang::$npc['melee'].Lang::$colon.$_nf($melee[0]).' - '.$_nf($melee[1]).' ('.Lang::$game['sc'][$_].')';
- else // phys. damage
- $stats['melee'] = Lang::$npc['melee'].Lang::$colon.$_nf($melee[0]).' - '.$_nf($melee[1]);
-
- // Ranged Damage
- $ranged = $npc->getBaseStats('ranged');
- $stats['ranged'] = Lang::$npc['ranged'].Lang::$colon.$_nf($ranged[0]).' - '.$_nf($ranged[1]);
-
- if ($mapType == 1 || $mapType == 2) // Dungeon or Raid
- {
- foreach ($_altIds as $id => $mode)
- {
- foreach ($_altNPCs->iterate() as $dId => $__)
- {
- if ($dId != $id)
- continue;
-
- $m = Lang::$npc['modes'][$mapType][$mode];
-
- // Health
- $health = $_altNPCs->getBaseStats('health');
- $modes['health'][] = sprintf($modeRow, $m, $health[0] < $health[1] ? $_nf($health[0]).' - '.$_nf($health[1]) : $_nf($health[0]));
-
- // Mana (may be 0)
- $mana = $_altNPCs->getBaseStats('power');
- $modes['mana'][] = $mana[0] ? sprintf($modeRow, $m, $mana[0] < $mana[1] ? $_nf($mana[0]).' - '.$_nf($mana[1]) : $_nf($mana[0])) : null;
-
- // Armor
- $armor = $_altNPCs->getBaseStats('armor');
- $modes['armor'][] = sprintf($modeRow, $m, $armor[0] < $armor[1] ? $_nf($armor[0]).' - '.$_nf($armor[1]) : $_nf($armor[0]));
-
- // Melee Damage
- $melee = $_altNPCs->getBaseStats('melee');
- if ($_ = $_altNPCs->getField('dmgSchool')) // magic damage
- $modes['melee'][] = sprintf($modeRow, $m, $_nf($melee[0]).' - '.$_nf($melee[1]).' ('.Lang::$game['sc'][$_].')');
- else // phys. damage
- $modes['melee'][] = sprintf($modeRow, $m, $_nf($melee[0]).' - '.$_nf($melee[1]));
-
- // Ranged Damage
- $ranged = $_altNPCs->getBaseStats('ranged');
- $modes['ranged'][] = sprintf($modeRow, $m, $_nf($ranged[0]).' - '.$_nf($ranged[1]));
- }
- }
- }
-
- if ($modes)
- foreach ($stats as $k => $v)
- if ($v)
- $stats[$k] = sprintf($hint, implode('[/tr][tr]', $modes[$k]), $v, $k);
-
- // < Stats
- if ($stats)
- $infobox[] = Lang::$npc['stats'].($modes ? ' ('.Lang::$npc['modes'][$mapType][0].')' : null).Lang::$colon.'[ul][li]'.implode('[/li][li]', $stats).'[/li][/ul]';
-
-
- /****************/
- /* Main Content */
- /****************/
-
- // reputations (by mode)
- $spilledParents = [];
- $reputation = [];
- $_repFunc = function ($entries, &$spillover)
+ private function getRepForId($entries, &$spillover)
{
+ $result = [];
$q = 'SELECT f.id, f.parentFactionId, cor.creature_id AS npc,
IF(f.id = RewOnKillRepFaction1, RewOnKillRepValue1, RewOnKillRepValue2) AS qty,
IF(f.id = RewOnKillRepFaction1, MaxStanding1, MaxStanding2) AS maxRank,
IF(f.id = RewOnKillRepFaction1, isTeamAward1, isTeamAward2) AS spillover
FROM aowow_factions f JOIN creature_onkill_reputation cor ON f.Id = cor.RewOnKillRepFaction1 OR f.Id = cor.RewOnKillRepFaction2 WHERE cor.creature_id IN (?a)';
- $result = [];
- $repData = DB::Aowow()->select($q, (array)$entries);
-
- foreach ($repData as $_)
+ foreach (DB::Aowow()->select($q, (array)$entries) as $_)
{
$set = array(
'id' => $_['id'],
@@ -265,88 +691,95 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData))
}
return $result;
- };
-
- // base NPC
- if ($base = $_repFunc($_id, $spilledParents))
- $reputation[] = [Lang::$npc['modes'][1][0], $base];
-
- // difficulty dummys
- if ($_altIds)
- {
- $alt = [];
- $rep = $_repFunc(array_keys($_altIds), $spilledParents);
-
- // order by difficulty
- foreach ($rep as $r)
- $alt[$_altIds[$r['npc']]][] = $r;
-
- // apply by difficulty
- foreach ($alt as $mode => $dat)
- $reputation[] = [Lang::$npc['modes'][$mapType][$mode], $dat];
}
- // get spillover factions and apply
- if ($spilledParents)
+ private function getOnKillRep($dummyIds, $mapType)
{
- $spilled = new FactionList(array(['parentFactionId', array_keys($spilledParents)]));
+ $spilledParents = [];
+ $reputation = [];
- foreach($reputation as &$sets)
+ // base NPC
+ if ($base = $this->getRepForId($this->typeId, $spilledParents))
+ $reputation[] = [Lang::$npc['modes'][1][0], $base];
+
+ // difficulty dummys
+ if ($dummyIds)
{
- foreach ($sets[1] as &$row)
+ $alt = [];
+ $rep = $this->getRepForId(array_keys($dummyIds), $spilledParents);
+
+ // order by difficulty
+ foreach ($rep as $r)
+ $alt[$dummyIds[$r['npc']]][] = $r;
+
+ // apply by difficulty
+ foreach ($alt as $mode => $dat)
+ $reputation[] = [Lang::$npc['modes'][$mapType][$mode], $dat];
+ }
+
+ // get spillover factions and apply
+ if ($spilledParents)
+ {
+ $spilled = new FactionList(array(['parentFactionId', array_keys($spilledParents)]));
+
+ foreach($reputation as &$sets)
{
- if (empty($row['spillover']))
- continue;
-
- foreach ($spilled->iterate() as $spId => $__)
+ foreach ($sets[1] as &$row)
{
- // find parent
- if ($spilled->getField('parentFactionId') != $row['spillover'])
+ if (empty($row['spillover']))
continue;
- // don't readd parent
- if ($row['id'] == $spId)
- continue;
+ foreach ($spilled->iterate() as $spId => $__)
+ {
+ // find parent
+ if ($spilled->getField('parentFactionId') != $row['spillover'])
+ continue;
- $spMax = $spilledParents[$row['spillover']][1];
+ // don't readd parent
+ if ($row['id'] == $spId)
+ continue;
- $sets[1][] = array(
- 'id' => $spId,
- 'qty' => $spilledParents[$row['spillover']][0],
- 'name' => $spilled->getField('name', true),
- 'cap' => $spMax && $spMax < REP_EXALTED ? Lang::$game['rep'][$spMax] : null
- );
+ $spMax = $spilledParents[$row['spillover']][1];
+
+ $sets[1][] = array(
+ 'id' => $spId,
+ 'qty' => $spilledParents[$row['spillover']][0],
+ 'name' => $spilled->getField('name', true),
+ 'cap' => $spMax && $spMax < REP_EXALTED ? Lang::$game['rep'][$spMax] : null
+ );
+ }
}
}
}
+
+ return $reputation;
}
- // Quotes
- $quotes = [];
- $quoteQuery = '
- SELECT
- ct.groupid AS ARRAY_KEY, ct.id as ARRAY_KEY2, ct.`type`,
- IFNULL(bct.`Language`, ct.`language`) AS lang,
- IFNULL(bct.MaleText, IFNULL(bct.FemaleText, ct.`text`)) AS text_loc0,
- IFNULL(lbct.MaleText_loc2, IFNULL(lbct.FemaleText_loc2, lct.text_loc2)) AS text_loc2,
- IFNULL(lbct.MaleText_loc3, IFNULL(lbct.FemaleText_loc3, lct.text_loc3)) AS text_loc3,
- IFNULL(lbct.MaleText_loc6, IFNULL(lbct.FemaleText_loc6, lct.text_loc6)) AS text_loc6,
- IFNULL(lbct.MaleText_loc8, IFNULL(lbct.FemaleText_loc8, lct.text_loc8)) AS text_loc8
- FROM
- creature_text ct
- LEFT JOIN
- locales_creature_text lct ON ct.entry = lct.entry AND ct.groupid = lct.groupid AND ct.id = lct.id
- LEFT JOIN
- broadcast_text bct ON ct.BroadcastTextId = bct.ID
- LEFT JOIN
- locales_broadcast_text lbct ON ct.BroadcastTextId = lbct.ID
- WHERE
- ct.entry = ?d';
-
- if ($texts = DB::Aowow()->select($quoteQuery, $_id))
+ private function getQuotes()
{
- $nQuotes = 0;
- foreach ($texts as $text)
+ $nQuotes = 0;
+ $quotes = [];
+ $quoteQuery = '
+ SELECT
+ ct.groupid AS ARRAY_KEY, ct.id as ARRAY_KEY2, ct.`type`,
+ IFNULL(bct.`Language`, ct.`language`) AS lang,
+ IFNULL(bct.MaleText, IFNULL(bct.FemaleText, ct.`text`)) AS text_loc0,
+ IFNULL(lbct.MaleText_loc2, IFNULL(lbct.FemaleText_loc2, lct.text_loc2)) AS text_loc2,
+ IFNULL(lbct.MaleText_loc3, IFNULL(lbct.FemaleText_loc3, lct.text_loc3)) AS text_loc3,
+ IFNULL(lbct.MaleText_loc6, IFNULL(lbct.FemaleText_loc6, lct.text_loc6)) AS text_loc6,
+ IFNULL(lbct.MaleText_loc8, IFNULL(lbct.FemaleText_loc8, lct.text_loc8)) AS text_loc8
+ FROM
+ creature_text ct
+ LEFT JOIN
+ locales_creature_text lct ON ct.entry = lct.entry AND ct.groupid = lct.groupid AND ct.id = lct.id
+ LEFT JOIN
+ broadcast_text bct ON ct.BroadcastTextId = bct.ID
+ LEFT JOIN
+ locales_broadcast_text lbct ON ct.BroadcastTextId = lbct.ID
+ WHERE
+ ct.entry = ?d';
+
+ foreach (DB::Aowow()->select($quoteQuery, $this->typeId) as $text)
{
$group = [];
foreach ($text as $t)
@@ -357,23 +790,23 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData))
$text = '%s '.$text;
$line = array(
- 'type' => 2, // [type: 0, 12] say: yellow-ish
+ 'type' => 2, // [type: 0, 12] say: yellow-ish
'lang' => !empty($t['language']) ? Lang::$game['languages'][$t['language']] : null,
- 'text' => sprintf(Util::parseHtmlText(htmlentities($text)), $_name),
+ 'text' => sprintf(Util::parseHtmlText(htmlentities($text)), $this->name),
);
switch ($t['type'])
{
- case 1: // yell:
- case 14: $line['type'] = 1; break; // - dark red
- case 2: // emote:
- case 16: // "
- case 3: // boss emote:
- case 41: $line['type'] = 4; break; // - orange
- case 4: // whisper:
- case 15: // "
- case 5: // boss whisper:
- case 42: $line['type'] = 3; break; // - pink-ish
+ case 1: // yell:
+ case 14: $line['type'] = 1; break; // - dark red
+ case 2: // emote:
+ case 16: // "
+ case 3: // boss emote:
+ case 41: $line['type'] = 4; break; // - orange
+ case 4: // whisper:
+ case 15: // "
+ case 5: // boss whisper:
+ case 42: $line['type'] = 3; break; // - pink-ish
}
$nQuotes++;
@@ -381,420 +814,10 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData))
}
$quotes[] = $group;
}
- $quotes = [$quotes, $nQuotes];
+
+ return [$quotes, $nQuotes];
}
-
-
- // get spawns and such
-
-
- // consider phaseMasks
-
- // consider pooled spawns
-
-
- // menuId 4: NPC g_initPath()
- // tabId 0: Database g_initHeader()
- $pageData = array(
- 'page' => array(
- 'name' => $_name,
- 'subname' => $npc->getField('subname', true),
- 'infobox' => '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]',
- 'difficultyPH' => isset($difficultyPH) ? $difficultyPH : null,
- // 'mapper' => true,
- 'position' => $position,
- 'quotes' => $quotes,
- 'reputation' => $reputation,
- 'title' => $_name.' - '.Util::ucFirst(Lang::$game['npc']),
- 'path' => json_encode($_path, JSON_NUMERIC_CHECK),
- 'tab' => 0,
- 'type' => TYPE_NPC,
- 'typeId' => $_id,
- 'reqJS' => [STATIC_URL.'/js/swfobject.js'],
- 'redButtons' => array(
- BUTTON_WOWHEAD => true,
- BUTTON_LINKS => true,
- BUTTON_VIEW3D => ['type' => TYPE_NPC, 'typeId' => $_id, 'displayId' => $npc->getRandomModelId()]
- )
- ),
- 'relTabs' => []
- );
-
- /**************/
- /* Extra Tabs */
- /**************/
-
- // tab: SAI
- // hmm, how should this loot like
-
- // tab: abilities / tab_controlledabilities (dep: VehicleId)
- // SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86
- $smartSpells = DB::Aowow()->selectCol('SELECT action_param1 FROM smart_scripts WHERE source_type = 0 AND action_type IN (11, 75, 85, 86) AND entryOrGUID = ?d', $_id);
- $tplSpells = [];
- $conditions = ['OR'];
-
- for ($i = 1; $i < 9; $i++)
- if ($_ = $npc->getField('spell'.$i))
- $tplSpells[] = $_;
-
- if ($tplSpells)
- $conditions[] = ['id', $tplSpells];
-
- if ($smartSpells)
- $conditions[] = ['id', $smartSpells];
-
- if ($tplSpells || $smartSpells)
- {
- $abilities = new SpellList($conditions);
- if (!$abilities->error)
- {
- $abilities->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED);
- $normal = $abilities->getListviewData();
- $controled = [];
-
- if ($npc->getField('vehicleId')) // not quite right. All seats should be checked for allowed-to-cast-flag-something
- {
- foreach ($normal as $id => $values)
- {
- if (in_array($id, $smartSpells))
- continue;
-
- $controled[$id] = $values;
- unset($normal[$id]);
- }
- }
-
- if ($normal)
- $pageData['relTabs'][] = array(
- 'file' => 'spell',
- 'data' => $normal,
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_abilities',
- 'id' => 'abilities'
- ]
- );
-
- if ($controled)
- $pageData['relTabs'][] = array(
- 'file' => 'spell',
- 'data' => $controled,
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_controlledabilities',
- 'id' => 'controlled-abilities'
- ]
- );
- }
- }
-
- // tab: summoned by
- $conditions = array(
- 'OR',
- ['AND', ['effect1Id', 28], ['effect1MiscValue', $_id]],
- ['AND', ['effect2Id', 28], ['effect2MiscValue', $_id]],
- ['AND', ['effect3Id', 28], ['effect3MiscValue', $_id]]
- );
-
- $summoned = new SpellList($conditions);
- if (!$summoned->error)
- {
- $summoned->addGlobalsToJscript();
-
- $pageData['relTabs'][] = array(
- 'file' => 'spell',
- 'data' => $summoned->getListviewData(),
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_summonedby',
- 'id' => 'summoned-by'
- ]
- );
- }
-
-
- // tab: teaches
- if ($npc->getField('npcflag') & NPC_FLAG_TRAINER)
- {
- $teachQuery = 'SELECT IFNULL(t2.spell, t1.spell) AS ARRAY_KEY, IFNULL(t2.spellcost, t1.spellcost) AS cost, IFNULL(t2.reqskill, t1.reqskill) AS reqSkillId,
- IFNULL(t2.reqskillvalue, t1.reqskillvalue) AS reqSkillValue, IFNULL(t2.reqlevel, t1.reqlevel) AS reqLevel
- FROM npc_trainer t1 LEFT JOIN npc_trainer t2 ON t2.entry = IF(t1.spell < 0, -t1.spell, null) WHERE t1.entry = ?d';
-
- if ($tSpells = DB::Aowow()->select($teachQuery, $_id))
- {
- $teaches = new SpellList(array(['id', array_keys($tSpells)]));
- if (!$teaches->error)
- {
- $teaches->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED);
- $data = $teaches->getListviewData();
-
- $extra = [];
- foreach ($tSpells as $sId => $train)
- {
- if (empty($data[$sId]))
- continue;
-
- if ($_ = $train['reqSkillId'])
- {
- Util::$pageTemplate->extendGlobalIds(TYPE_SKILL, $_);
- if (!isset($extra[0]))
- $extra[0] = 'Listview.extraCols.condition';
-
- $data[$sId]['condition'][] = ['type' => TYPE_SKILL, 'typeId' => $_, 'status' => 1, 'reqSkillLvl' => $train['reqSkillValue']];
- }
-
- if ($_ = $train['reqLevel'])
- {
- if (!isset($extra[1]))
- $extra[1] = "Listview.funcBox.createSimpleCol('reqLevel', LANG.tooltip_reqlevel, '7%', 'reqLevel')";
-
- $data[$sId]['reqLevel'] = $_;
- }
-
- if ($_ = $train['cost'])
- $data[$sId]['trainingcost'] = $_;
- }
-
- $pageData['relTabs'][] = array(
- 'file' => 'spell',
- 'data' => $data,
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_teaches',
- 'id' => 'teaches',
- 'visibleCols' => "$['trainingcost']",
- 'extraCols' => $extra ? '$['.implode(', ', $extra).']' : null
- ]
- );
- }
- }
- else
- Util::$pageTemplate->internalNotice(U_GROUP_EMPLOYEE, 'NPC '.$_id.' is flagged as trainer, but doesn\'t have any spells set');
- }
-
- // tab: sells
- if ($sells = DB::Aowow()->selectCol('SELECT item FROM npc_vendor nv WHERE entry = ?d UNION SELECT item FROM game_event_npc_vendor genv JOIN creature c ON genv.guid = c.guid WHERE c.id = ?d', $_id, $_id))
- {
- $soldItems = new ItemList(array(['id', $sells]));
- if (!$soldItems->error)
- {
- $soldItems->addGlobalsToJscript();
-
- $pageData['relTabs'][] = array(
- 'file' => 'item',
- 'data' => $soldItems->getListviewData(ITEMINFO_VENDOR, [TYPE_NPC => $_id]),
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_sells',
- 'id' => 'currency-for',
- 'extraCols' => "$[Listview.extraCols.condition, Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack'), Listview.extraCols.cost]"
- ]
- );
- }
- }
-
- // tabs: this creature contains..
- $skinTab = ['tab_skinning', 'skinned-from'];
- if ($_typeFlags & NPC_TYPEFLAG_HERBLOOT)
- $skinTab = ['tab_gatheredfromnpc', 'gathered-from-npc'];
- else if ($_typeFlags & NPC_TYPEFLAG_MININGLOOT)
- $skinTab = ['tab_minedfromnpc', 'mined-from-npc'];
- else if ($_typeFlags & NPC_TYPEFLAG_ENGINEERLOOT)
- $skinTab = ['tab_salvagedfrom', 'salvaged-from-npc'];
-
-/*
- extraCols: [Listview.extraCols.count, Listview.extraCols.percent, Listview.extraCols.mode],
- _totalCount: 22531,
- computeDataFunc: Listview.funcBox.initLootTable,
- onAfterCreate: Listview.funcBox.addModeIndicator,
-
- modes:{"mode":1,"1":{"count":4408,"outof":16013},"4":{"count":4408,"outof":22531}}
-*/
-
- $sourceFor = array(
- [LOOT_CREATURE, $npc->getField('lootId'), '$LANG.tab_drops', 'drops', ['Listview.extraCols.percent'], [] , []],
- [LOOT_PICKPOCKET, $npc->getField('pickpocketLootId'), '$LANG.tab_pickpocketing', 'pickpocketing', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
- [LOOT_SKINNING, $npc->getField('skinLootId'), '$LANG.'.$skinTab[0], $skinTab[1], ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []]
- );
-
- // temp: manually add loot for difficulty-versions
- $langref = array(
- "-2" => '$LANG.tab_heroic',
- "-1" => '$LANG.tab_normal',
- 1 => '$$WH.sprintf(LANG.tab_normalX, 10)',
- 2 => '$$WH.sprintf(LANG.tab_normalX, 25)',
- 3 => '$$WH.sprintf(LANG.tab_heroicX, 10)',
- 4 => '$$WH.sprintf(LANG.tab_heroicX, 25)'
- );
-
- if ($_altIds)
- {
- $sourceFor[0][2] = $langref[1];
- foreach ($_altNPCs->iterate() as $id => $__)
- {
- $mode = $_altIds[$id];
- array_splice($sourceFor, 1, 0, [[LOOT_CREATURE, $_altNPCs->getField('lootId'), $langref[$mode + 1], 'drops-'.$mode, ['Listview.extraCols.percent'], [], []]]);
- }
- }
-
- $reqQuest = [];
- foreach ($sourceFor as $sf)
- {
- if ($itemLoot = Util::handleLoot($sf[0], $sf[1], User::isInGroup(U_GROUP_STAFF), $sf[4]))
- {
- foreach ($itemLoot as $l => $lv)
- {
- if (!$lv['quest'])
- continue;
-
- $sf[4][] = 'Listview.extraCols.condition';
-
- $reqQuest[$lv['id']] = 0;
-
- $itemLoot[$l]['condition'][] = ['type' => TYPE_QUEST, 'typeId' => &$reqQuest[$lv['id']], 'status' => 1];
- }
-
- $pageData['relTabs'][] = array(
- 'file' => 'item',
- 'data' => $itemLoot,
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => $sf[2],
- 'id' => $sf[3],
- 'extraCols' => $sf[4] ? "$[".implode(', ', array_unique($sf[4]))."]" : null,
- 'hiddenCols' => $sf[5] ? "$".json_encode($sf[5]) : null,
- 'visibleCols' => $sf[6] ? '$'.json_encode($sf[6]) : null,
- 'sort' => "$['-percent', 'name']",
- ]
- );
- }
- }
-
- if ($reqIds = array_keys($reqQuest)) // apply quest-conditions as back-reference
- {
- $conditions = array(
- 'OR',
- ['reqSourceItemId1', $reqIds], ['reqSourceItemId2', $reqIds],
- ['reqSourceItemId3', $reqIds], ['reqSourceItemId4', $reqIds],
- ['reqItemId1', $reqIds], ['reqItemId2', $reqIds], ['reqItemId3', $reqIds],
- ['reqItemId4', $reqIds], ['reqItemId5', $reqIds], ['reqItemId6', $reqIds]
- );
-
- $reqQuests = new QuestList($conditions);
- $reqQuests->addGlobalsToJscript();
-
- foreach ($reqQuests->iterate() as $qId => $__)
- {
- if (empty($reqQuests->requires[$qId][TYPE_ITEM]))
- continue;
-
- foreach ($reqIds as $rId)
- if (in_array($rId, $reqQuests->requires[$qId][TYPE_ITEM]))
- $reqQuest[$rId] = $reqQuests->id;
- }
- }
-
- // tab: starts quest
- // tab: ends quest
- $startEnd = new QuestList(array(['qse.type', TYPE_NPC], ['qse.typeId', $_id]));
- if (!$startEnd->error)
- {
- $startEnd->addGlobalsToJScript();
- $lvData = $startEnd->getListviewData();
- $_ = [[], []];
-
- foreach ($startEnd->iterate() as $id => $__)
- {
- $m = $startEnd->getField('method');
- if ($m & 0x1)
- $_[0][] = $lvData[$id];
- if ($m & 0x2)
- $_[1][] = $lvData[$id];
- }
-
- if ($_[0])
- {
- $pageData['relTabs'][] = array(
- 'file' => 'quest',
- 'data' => $_[0],
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_starts',
- 'id' => 'starts'
- ]
- );
- }
-
- if ($_[1])
- {
- $pageData['relTabs'][] = array(
- 'file' => 'quest',
- 'data' => $_[1],
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_ends',
- 'id' => 'ends'
- ]
- );
- }
- }
-
- // tab: objective of quest
- $conditions = array(
- 'OR',
- ['AND', ['reqNpcOrGo1', $_id], ['reqNpcOrGoCount1', 0, '>']],
- ['AND', ['reqNpcOrGo2', $_id], ['reqNpcOrGoCount2', 0, '>']],
- ['AND', ['reqNpcOrGo3', $_id], ['reqNpcOrGoCount3', 0, '>']],
- ['AND', ['reqNpcOrGo4', $_id], ['reqNpcOrGoCount4', 0, '>']],
- );
-
- $objectiveOf = new QuestList($conditions);
- if (!$objectiveOf->error)
- {
- $objectiveOf->addGlobalsToJScript();
-
- $pageData['relTabs'][] = array(
- 'file' => 'quest',
- 'data' => $objectiveOf->getListviewData(),
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_objectiveof',
- 'id' => 'objective-of'
- ]
- );
- }
-
- // tab: criteria of [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE have no data set to check for]
- $conditions = array(
- ['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE]],
- ['ac.value1', $_id]
- );
-
- $crtOf = new AchievementList($conditions);
- if (!$crtOf->error)
- {
- $crtOf->addGlobalsToJScript();
-
- $pageData['relTabs'][] = array(
- 'file' => 'achievement',
- 'data' => $crtOf->getListviewData(),
- 'params' => [
- 'tabs' => '$tabsRelated',
- 'name' => '$LANG.tab_criteriaof',
- 'id' => 'criteria-of'
- ]
- );
- }
-
- $smarty->saveCache($cacheKeyPage, $pageData);
}
-$smarty->updatePageVars($pageData['page']);
-$smarty->assign('community', CommunityContent::getAll(TYPE_NPC, $_id)); // comments, screenshots, videos
-$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$npc, ['colon' => Lang::$colon]));
-$smarty->assign('lvData', $pageData['relTabs']);
-
-// load the page
-$smarty->display('npc.tpl');
?>
diff --git a/pages/npcs.php b/pages/npcs.php
index d96d0efe..980cfff4 100644
--- a/pages/npcs.php
+++ b/pages/npcs.php
@@ -4,90 +4,95 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-$filter = [];
-$cats = Util::extractURLParams($pageParam);
-$path = [0, 4];
-$title = [Util::ucFirst(Lang::$game['npcs'])];
-$filterHash = !empty($_GET['filter']) ? sha1(serialize($_GET['filter'])) : -1;
-$cacheKey = implode('_', [CACHETYPE_PAGE, TYPE_NPC, -1, ($cats ? $cats[0] : -1).$filterHash, User::$localeId]);
-$validCats = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
-
-if (!Util::isValidPage($validCats, $cats))
- $smarty->error();
-
-if (!$smarty->loadCache($cacheKey, $pageData, $filter))
+// menuId 4: NPC g_initPath()
+// tabId 0: Database g_initHeader()
+class NpcsPage extends GenericPage
{
- $conditions = [];
- if ($cats)
+ use ListPage;
+
+ protected $type = TYPE_NPC;
+ protected $tpl = 'npcs';
+ protected $path = [0, 4];
+ protected $tabId = 0;
+ protected $mode = CACHETYPE_PAGE;
+ protected $validCats = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
+ protected $js = ['filters.js'];
+
+ public function __construct($pageCall, $pageParam)
{
- $conditions[] = ['type', $cats[0]];
- $path[] = $cats[0];
- array_unshift($title, Lang::$npc['cat'][$cats[0]]);
+ $this->getCategoryFromUrl($pageParam);;
+
+ parent::__construct();
+
+ $this->name = Util::ucFirst(Lang::$game['npcs']);
+ $this->subCat = $pageParam ? '='.$pageParam : '';
}
- $npcFilter = new CreatureListFilter();
- if ($_ = $npcFilter->getConditions())
- $conditions[] = $_;
-
- // beast subtypes are selected via filter
- $npcs = new CreatureList($conditions, ['extraOpts' => $npcFilter->extraOpts]);
-
- // recreate form selection
- $filter = array_merge($npcFilter->getForm('form'), $filter);
- $filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
- $filter['fi'] = $npcFilter->getForm();
-
- if (isset($filter['fa']))
- $path[] = $filter['fa'];
-
- // menuId 4: NPC g_initPath()
- // tabId 0: Database g_initHeader()
- $pageData = array(
- 'page' => array(
- 'petFamPanel' => ($cats && $cats[0] == 1),
- 'title' => implode(' - ', $title),
- 'path' => json_encode($path, JSON_NUMERIC_CHECK),
- 'tab' => 0,
- 'subCat' => $pageParam ? '='.$pageParam : '',
- 'reqJS' => array(
- STATIC_URL.'/js/filters.js'
- )
- ),
- 'lv' => []
- );
-
- $lv = array(
- 'data' => $npcs->getListviewData(), // listview content
- 'params' => []
- );
-
- if (!empty($filter['fi']['extraCols']))
- $lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
-
- // create note if search limit was exceeded
- if ($npcs->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ protected function generateContent()
{
- $lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_npcsfound', $npcs->getMatches(), CFG_SQL_LIMIT_DEFAULT);
- $lv['params']['_truncated'] = 1;
+ $conditions = [];
+
+ if ($this->category)
+ {
+ $conditions[] = ['type', $this->category[0]];
+ $this->petFamPanel = $this->category[0] == 1;
+ }
+ else
+ $this->petFamPanel = false;
+
+ $npcFilter = new CreatureListFilter();
+ if ($_ = $npcFilter->getConditions())
+ $conditions[] = $_;
+
+ // beast subtypes are selected via filter
+ $npcs = new CreatureList($conditions, ['extraOpts' => $npcFilter->extraOpts]);
+
+ // recreate form selection
+ $this->filter = array_merge($npcFilter->getForm('form'), $this->filter);
+ $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
+ $this->filter['fi'] = $npcFilter->getForm();
+
+ $lv = array(
+ 'file' => 'creature',
+ 'data' => $npcs->getListviewData(), // listview content
+ 'params' => []
+ );
+
+ if (!empty($this->filter['fi']['extraCols']))
+ $lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
+
+ // create note if search limit was exceeded
+ if ($npcs->getMatches() > CFG_SQL_LIMIT_DEFAULT)
+ {
+ $lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_npcsfound', $npcs->getMatches(), CFG_SQL_LIMIT_DEFAULT);
+ $lv['params']['_truncated'] = 1;
+ }
+
+ if ($npcFilter->error)
+ $lv['params']['_errors'] = '$1';
+
+ $this->lvData = $lv;
+
+ // sort for dropdown-menus
+ asort(Lang::$game['fa']);
}
- if ($npcFilter->error)
- $lv['params']['_errors'] = '$1';
+ protected function generateTitle()
+ {
+ array_unshift($this->title, $this->name);
+ if ($this->category)
+ array_unshift($this->title, Lang::$npc['cat'][$this->category[0]]);
+ }
- $pageData['lv'] = $lv;
+ protected function generatePath()
+ {
+ if ($this->category)
+ $this->path[] = $this->category[0];
- $smarty->saveCache($cacheKey, $pageData);
+ $form = (new CreatureListFilter())->getForm('form');
+ if (isset($form['fa']) && !is_array($form['fa']))
+ $this->path[] = $form['fa'];
+ }
}
-// sort for dropdown-menus
-asort(Lang::$game['fa']);
-
-$smarty->updatePageVars($pageData['page']);
-$smarty->assign('filter', $filter);
-$smarty->assign('lang', array_merge(Lang::$main, Lang::$npc, Lang::$game, ['colon' => lang::$colon]));
-$smarty->assign('lvData', $pageData['lv']);
-
-// load the page
-$smarty->display('npcs.tpl');
-
?>
diff --git a/pages/skill.php b/pages/skill.php
index 183c5738..a3f1522b 100644
--- a/pages/skill.php
+++ b/pages/skill.php
@@ -4,313 +4,368 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-require 'includes/community.class.php';
-
-$_id = intVal($pageParam);
-$_path = [0, 14];
-
-$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_SKILL, $_id, -1, User::$localeId]);
-
-if (!$smarty->loadCache($cacheKeyPage, $pageData))
+// menuId 14: Skill g_initPath()
+// tabId 0: Database g_initHeader()
+class SkillPage extends GenericPage
{
- $skill = new SkillList(array(['id', $_id]));
- if ($skill->error)
- $smarty->notFound(Lang::$game['skill'], $_id);
+ use DetailPage;
- $_cat = $skill->getField('typeCat');
+ protected $type = TYPE_SKILL;
+ protected $typeId = 0;
+ protected $tpl = 'detail-page-generic';
+ protected $path = [0, 14];
+ protected $tabId = 0;
+ protected $mode = CACHETYPE_PAGE;
- $_path[] = (in_array($_cat, [9, 11]) || $_id == 762) ? $_id : $_cat;
+ private $cat = 0;
- /****************/
- /* Main Content */
- /****************/
-
- // menuId 14: Skill g_initPath()
- // tabId 0: Database g_initHeader()
- $pageData = array(
- 'page' => array(
- 'title' => $skill->getField('name', true)." - ".Util::ucfirst(Lang::$game['skill']),
- 'name' => $skill->getField('name', true),
- 'path' => json_encode($_path, JSON_NUMERIC_CHECK),
- 'tab' => 0,
- 'type' => TYPE_SKILL,
- 'typeId' => $_id,
- 'headIcons' => [$skill->getField('iconString')],
- 'redButtons' => array(
- BUTTON_WOWHEAD => true,
- BUTTON_LINKS => true
- )
- ),
- 'relTabs' => []
- );
-
- /**************/
- /* Extra Tabs */
- /**************/
-
- if (in_array($_cat, [-5, 9, 11]))
+ public function __construct($__, $id)
{
- // tab: recipes [spells] (crafted)
- $condition = array(
- ['OR', ['s.reagent1', 0, '>'], ['s.reagent2', 0, '>'], ['s.reagent3', 0, '>'], ['s.reagent4', 0, '>'], ['s.reagent5', 0, '>'], ['s.reagent6', 0, '>'], ['s.reagent7', 0, '>'], ['s.reagent8', 0, '>']],
- ['OR', ['s.skillLine1', $_id], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $_id]]],
- 0
+ parent::__construct();
+
+ $this->typeId = intVal($id);
+
+ $this->subject = new SkillList(array(['id', $this->typeId]));
+ if ($this->subject->error)
+ $this->notFound(Lang::$game['skill']);
+
+ $this->name = $this->subject->getField('name', true);
+ $this->cat = $this->subject->getField('typeCat');
+ }
+
+ protected function generatePath()
+ {
+ $this->path[] = (in_array($this->cat, [9, 11]) || $this->typeId == 762) ? $this->typeId : $this->cat;
+ }
+
+ protected function generateTitle()
+ {
+ array_unshift($this->title, $this->name, Util::ucFirst(Lang::$game['class']));
+ }
+
+ protected function generateContent()
+ {
+ /****************/
+ /* Main Content */
+ /****************/
+
+ $this->headIcons = [$this->subject->getField('iconString')];
+ $this->redButtons = array(
+ BUTTON_WOWHEAD => true,
+ BUTTON_LINKS => true
);
- $recipes = new SpellList($condition); // also relevant for 3
- if (!$recipes->error)
- {
- $recipes->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED);
+ /**************/
+ /* Extra Tabs */
+ /**************/
- $pageData['relTabs'][] = array(
- 'file' => 'spell',
- 'data' => $recipes->getListviewData(),
- 'params' => array(
- 'tabs' => '$tabsRelated',
- 'id' => 'recipes',
- 'name' => '$LANG.tab_recipes',
- 'visibleCols' => "$['reagents', 'source']",
- 'note' => sprintf(Util::$filterResultString, '?spells='.$_cat.'.'.$_id.'&filter=cr=20;crs=1;crv=0')
- )
+ if (in_array($this->cat, [-5, 9, 11]))
+ {
+ // tab: recipes [spells] (crafted)
+ $condition = array(
+ ['OR', ['s.reagent1', 0, '>'], ['s.reagent2', 0, '>'], ['s.reagent3', 0, '>'], ['s.reagent4', 0, '>'], ['s.reagent5', 0, '>'], ['s.reagent6', 0, '>'], ['s.reagent7', 0, '>'], ['s.reagent8', 0, '>']],
+ ['OR', ['s.skillLine1', $this->typeId], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->typeId]]],
+ CFG_SQL_LIMIT_NONE
);
- }
- // tab: recipe Items [items] (Books)
- $filterRecipe = [null, 165, 197, 202, 164, 185, 171, 129, 333, 356, 755, 773, 186, 182];
- $conditions = array(
- ['requiredSkill', $_id],
- ['class', ITEM_CLASS_RECIPE],
- 0
- );
-
- $recipeItems = new ItemList($conditions);
- if (!$recipeItems->error)
- {
- $recipeItems->addGlobalsToJScript(GLOBALINFO_SELF);
-
- if ($_ = array_search($_id, $filterRecipe))
- $_ = sprintf(Util::$filterResultString, "?items=9.".$_);
-
- $pageData['relTabs'][] = array(
- 'file' => 'item',
- 'data' => $recipeItems->getListviewData(),
- 'params' => array(
- 'id' => 'recipe-items',
- 'name' => '$LANG.tab_recipeitems',
- 'tabs' => '$tabsRelated',
- 'note' => $_
- )
- );
- }
-
- // tab: crafted items [items]
- $filterItem = [null, 171, 164, 185, 333, 202, 129, 755, 165, 186, 197, null, null, 356, 182, 773];
- $created = [];
- foreach ($recipes->iterate() as $__)
- if ($idx = $recipes->canCreateItem())
- foreach ($idx as $i)
- $created[] = $recipes->getField('effect'.$i.'CreateItemId');
-
- if ($created)
- {
- $created = new ItemList(array(['i.id', $created], 0));
- if (!$created->error)
+ $recipes = new SpellList($condition); // also relevant for 3
+ if (!$recipes->error)
{
- $created->addGlobalsToJScript(GLOBALINFO_SELF);
+ $this->extendGlobalData($recipes->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
- if ($_ = array_search($_id, $filterItem))
- $_ = sprintf(Util::$filterResultString, "?items&filter=cr=86;crs=".$_.";crv=0");
-
- $pageData['relTabs'][] = array(
- 'file' => 'item',
- 'data' => $created->getListviewData(),
+ $this->lvData[] = array(
+ 'file' => 'spell',
+ 'data' => $recipes->getListviewData(),
'params' => array(
- 'id' => 'crafted-items',
- 'name' => '$LANG.tab_crafteditems',
+ 'tabs' => '$tabsRelated',
+ 'id' => 'recipes',
+ 'name' => '$LANG.tab_recipes',
+ 'visibleCols' => "$['reagents', 'source']",
+ 'note' => sprintf(Util::$filterResultString, '?spells='.$this->cat.'.'.$this->typeId.'&filter=cr=20;crs=1;crv=0')
+ )
+ );
+ }
+
+ // tab: recipe Items [items] (Books)
+ $filterRecipe = [null, 165, 197, 202, 164, 185, 171, 129, 333, 356, 755, 773, 186, 182];
+ $conditions = array(
+ ['requiredSkill', $this->typeId],
+ ['class', ITEM_CLASS_RECIPE],
+ CFG_SQL_LIMIT_NONE
+ );
+
+ $recipeItems = new ItemList($conditions);
+ if (!$recipeItems->error)
+ {
+ $this->extendGlobalData($recipeItems->getJSGlobals(GLOBALINFO_SELF));
+
+ if ($_ = array_search($this->typeId, $filterRecipe))
+ $_ = sprintf(Util::$filterResultString, "?items=9.".$_);
+
+ $this->lvData[] = array(
+ 'file' => 'item',
+ 'data' => $recipeItems->getListviewData(),
+ 'params' => array(
+ 'id' => 'recipe-items',
+ 'name' => '$LANG.tab_recipeitems',
'tabs' => '$tabsRelated',
'note' => $_
)
);
}
- }
- // tab: required by [item]
- $conditions = array(
- ['requiredSkill', $_id],
- ['class', ITEM_CLASS_RECIPE, '!'],
- 0
- );
+ // tab: crafted items [items]
+ $filterItem = [null, 171, 164, 185, 333, 202, 129, 755, 165, 186, 197, null, null, 356, 182, 773];
+ $created = [];
+ foreach ($recipes->iterate() as $__)
+ if ($idx = $recipes->canCreateItem())
+ foreach ($idx as $i)
+ $created[] = $recipes->getField('effect'.$i.'CreateItemId');
- $reqBy = new ItemList($conditions);
- if (!$reqBy->error)
- {
- $reqBy->addGlobalsToJScript(GLOBALINFO_SELF);
-
- if ($_ = array_search($_id, $filterItem))
- $_ = sprintf(Util::$filterResultString, "?items&filter=cr=99:168;crs=".$_.":2;crv=0:0");
-
- $pageData['relTabs'][] = array(
- 'file' => 'item',
- 'data' => $reqBy->getListviewData(),
- 'params' => array(
- 'id' => 'required-by',
- 'name' => '$LANG.tab_requiredby',
- 'tabs' => '$tabsRelated',
- 'note' => $_
- )
- );
- }
-
- // tab: required by [itemset]
- $conditions = array(
- ['skillId', $_id],
- 0
- );
-
- $reqBy = new ItemsetList($conditions);
- if (!$reqBy->error)
- {
- $reqBy->addGlobalsToJScript(GLOBALINFO_SELF);
-
- $pageData['relTabs'][] = array(
- 'file' => 'itemset',
- 'data' => $reqBy->getListviewData(),
- 'params' => array(
- 'id' => 'required-by-set',
- 'name' => '$LANG.tab_requiredby',
- 'tabs' => '$tabsRelated'
- )
- );
- }
- }
-
- // tab: spells [spells] (exclude first tab)
- $reqClass = 0x0;
- $reqRace = 0x0;
- $condition = array(
- ['AND', ['s.reagent1', 0], ['s.reagent2', 0], ['s.reagent3', 0], ['s.reagent4', 0], ['s.reagent5', 0], ['s.reagent6', 0], ['s.reagent7', 0], ['s.reagent8', 0]],
- ['OR', ['s.skillLine1', $_id], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $_id]]],
- 0
- );
-
- foreach (Util::$skillLineMask as $line1 => $sets)
- foreach ($sets as $idx => $set)
- if ($set[1] == $_id)
+ if ($created)
{
- $condition[1][] = array('AND', ['s.skillLine1', $line1], ['s.skillLine2OrMask', 1 << $idx, '&']);
- break 2;
+ $created = new ItemList(array(['i.id', $created], CFG_SQL_LIMIT_NONE));
+ if (!$created->error)
+ {
+ $this->extendGlobalData($created->getJSGlobals(GLOBALINFO_SELF));
+
+ if ($_ = array_search($this->typeId, $filterItem))
+ $_ = sprintf(Util::$filterResultString, "?items&filter=cr=86;crs=".$_.";crv=0");
+
+ $this->lvData[] = array(
+ 'file' => 'item',
+ 'data' => $created->getListviewData(),
+ 'params' => array(
+ 'id' => 'crafted-items',
+ 'name' => '$LANG.tab_crafteditems',
+ 'tabs' => '$tabsRelated',
+ 'note' => $_
+ )
+ );
+ }
}
- $spells = new SpellList($condition);
- if (!$spells->error)
- {
- foreach ($spells->iterate() as $__)
- {
- $reqClass |= $spells->getField('reqClassMask');
- $reqRace |= $spells->getField('reqRaceMask');
- }
-
- $spells->addGlobalsToJScript(GLOBALINFO_SELF);
-
- $pageData['relTabs'][] = array(
- 'file' => 'spell',
- 'data' => $spells->getListviewData(),
- 'params' => array(
- 'tabs' => '$tabsRelated',
- 'visibleCols' => "$['source']"
- )
- );
-
- switch ($_cat)
- {
- case -4:
- $pageData['spells']['params']['note'] = sprintf(Util::$filterResultString, '?spells=-4');
- break;
- case 7:
- if ($_id != 769) // Internal
- $pageData['spells']['params']['note'] = sprintf(Util::$filterResultString, '?spells='.$_cat.'.'.(log($reqClass, 2) + 1).'.'.$_id); // doesn't matter what spell; reqClass should be identical for all Class Spells
- break;
- case 9:
- case 11:
- $pageData['spells']['params']['note'] = sprintf(Util::$filterResultString, '?spells='.$_cat.'.'.$_id);
- break;
-
- }
- }
-
- // tab: trainers [npcs]
- if (in_array($_cat, [-5, 6, 7, 8, 9, 11]))
- {
- $list = [];
- if (@$tt = Util::$trainerTemplates[TYPE_SKILL][$_id])
- $list = DB::Aowow()->selectCol('SELECT DISTINCT entry FROM npc_trainer WHERE spell IN (?a) AND entry < 200000', $tt);
- else
- {
- $mask = 0;
- foreach (Util::$skillLineMask[-3] as $idx => $pair)
- if ($pair[1] == $_id)
- $mask |= 1 << $idx;
-
- $list = DB::Aowow()->selectCol('
- SELECT IF(t1.entry > 200000, t2.entry, t1.entry)
- FROM npc_trainer t1
- JOIN aowow_spell s ON s.id = t1.spell
- LEFT JOIN npc_trainer t2 ON t2.spell = -t1.entry
- WHERE s.typeCat IN (-11, 9) AND (s.skillLine1 = ?d OR (s.skillLine1 > 0 AND s.skillLine2OrMask = ?d) '.($mask ? ' OR (s.skilllIne1 = -3 AND s.skillLine2OrMask = '.$mask.')' : null).')',
- $_id,
- $_id
+ // tab: required by [item]
+ $conditions = array(
+ ['requiredSkill', $this->typeId],
+ ['class', ITEM_CLASS_RECIPE, '!'],
+ CFG_SQL_LIMIT_NONE
);
- }
- if ($list)
- {
- $trainer = new CreatureList(array(0, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&']));
-
- if (!$trainer->error)
+ $reqBy = new ItemList($conditions);
+ if (!$reqBy->error)
{
- $trainer->addGlobalsToJscript();
+ $this->extendGlobalData($reqBy->getJSGlobals(GLOBALINFO_SELF));
- $pageData['relTabs'][] = array(
- 'file' => 'creature',
- 'data' => $trainer->getListviewData(),
+ if ($_ = array_search($this->typeId, $filterItem))
+ $_ = sprintf(Util::$filterResultString, "?items&filter=cr=99:168;crs=".$_.":2;crv=0:0");
+
+ $this->lvData[] = array(
+ 'file' => 'item',
+ 'data' => $reqBy->getListviewData(),
'params' => array(
+ 'id' => 'required-by',
+ 'name' => '$LANG.tab_requiredby',
'tabs' => '$tabsRelated',
- 'id' => 'trainer',
- 'name' => '$LANG.tab_trainers',
+ 'note' => $_
+ )
+ );
+ }
+
+ // tab: required by [itemset]
+ $conditions = array(
+ ['skillId', $this->typeId],
+ CFG_SQL_LIMIT_NONE
+ );
+
+ $reqBy = new ItemsetList($conditions);
+ if (!$reqBy->error)
+ {
+ $this->extendGlobalData($reqBy->getJSGlobals(GLOBALINFO_SELF));
+
+ $this->lvData[] = array(
+ 'file' => 'itemset',
+ 'data' => $reqBy->getListviewData(),
+ 'params' => array(
+ 'id' => 'required-by-set',
+ 'name' => '$LANG.tab_requiredby',
+ 'tabs' => '$tabsRelated'
)
);
}
}
- }
- // tab: quests [quests]
- if (in_array($_cat, [9, 11])) // only for professions
- {
- $sort = 0;
- switch ($_id)
+ // tab: spells [spells] (exclude first tab)
+ $reqClass = 0x0;
+ $reqRace = 0x0;
+ $condition = array(
+ ['AND', ['s.reagent1', 0], ['s.reagent2', 0], ['s.reagent3', 0], ['s.reagent4', 0], ['s.reagent5', 0], ['s.reagent6', 0], ['s.reagent7', 0], ['s.reagent8', 0]],
+ ['OR', ['s.skillLine1', $this->typeId], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->typeId]]],
+ CFG_SQL_LIMIT_NONE
+ );
+
+ foreach (Util::$skillLineMask as $line1 => $sets)
+ foreach ($sets as $idx => $set)
+ if ($set[1] == $this->typeId)
+ {
+ $condition[1][] = array('AND', ['s.skillLine1', $line1], ['s.skillLine2OrMask', 1 << $idx, '&']);
+ break 2;
+ }
+
+ $spells = new SpellList($condition);
+ if (!$spells->error)
{
- case 182: $sort = 24; break; // Herbalism
- case 356: $sort = 101; break; // Fishing
- case 164: $sort = 121; break; // Blacksmithing
- case 171: $sort = 181; break; // Alchemy
- case 165: $sort = 182; break; // Leatherworking
- case 202: $sort = 201; break; // Engineering
- case 197: $sort = 264; break; // Tailoring
- case 185: $sort = 304; break; // Cooking
- case 129: $sort = 324; break; // First Aid
- case 773: $sort = 371; break; // Inscription
- case 755: $sort = 373; break; // Jewelcrafting
+ foreach ($spells->iterate() as $__)
+ {
+ $reqClass |= $spells->getField('reqClassMask');
+ $reqRace |= $spells->getField('reqRaceMask');
+ }
+
+ $this->extendGlobalData($spells->getJSGlobals(GLOBALINFO_SELF));
+
+ $lv = array(
+ 'file' => 'spell',
+ 'data' => $spells->getListviewData(),
+ 'params' => array(
+ 'tabs' => '$tabsRelated',
+ 'visibleCols' => "$['source']"
+ )
+ );
+
+ switch ($this->cat)
+ {
+ case -4:
+ $lv['params']['note'] = sprintf(Util::$filterResultString, '?spells=-4');
+ break;
+ case 7:
+ if ($this->typeId != 769) // Internal
+ $lv['params']['note'] = sprintf(Util::$filterResultString, '?spells='.$this->cat.'.'.(log($reqClass, 2) + 1).'.'.$this->typeId); // doesn't matter what spell; reqClass should be identical for all Class Spells
+ break;
+ case 9:
+ case 11:
+ $lv['params']['note'] = sprintf(Util::$filterResultString, '?spells='.$this->cat.'.'.$this->typeId);
+ break;
+ }
+
+ $this->lvData[] = $lv;
}
- if ($sort)
+ // tab: trainers [npcs]
+ if (in_array($this->cat, [-5, 6, 7, 8, 9, 11]))
{
- $quests = new QuestList(array(['zoneOrSort', -$sort], 0));
- if (!$quests->error)
+ $list = [];
+ if (@$tt = Util::$trainerTemplates[TYPE_SKILL][$this->typeId])
+ $list = DB::Aowow()->selectCol('SELECT DISTINCT entry FROM npc_trainer WHERE spell IN (?a) AND entry < 200000', $tt);
+ else
{
- $quests->addGlobalsToJScript();
- $pageData['relTabs'][] = array(
- 'file' => 'quest',
- 'data' => $quests->getListviewData(),
+ $mask = 0;
+ foreach (Util::$skillLineMask[-3] as $idx => $pair)
+ if ($pair[1] == $this->typeId)
+ $mask |= 1 << $idx;
+
+ $list = DB::Aowow()->selectCol('
+ SELECT IF(t1.entry > 200000, t2.entry, t1.entry)
+ FROM npc_trainer t1
+ JOIN aowow_spell s ON s.id = t1.spell
+ LEFT JOIN npc_trainer t2 ON t2.spell = -t1.entry
+ WHERE s.typeCat IN (-11, 9) AND (s.skillLine1 = ?d OR (s.skillLine1 > 0 AND s.skillLine2OrMask = ?d) '.($mask ? ' OR (s.skilllIne1 = -3 AND s.skillLine2OrMask = '.$mask.')' : null).')',
+ $this->typeId,
+ $this->typeId
+ );
+ }
+
+ if ($list)
+ {
+ $trainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&']));
+
+ if (!$trainer->error)
+ {
+ $this->extendGlobalData($trainer->getJSGlobals());
+
+ $this->lvData[] = array(
+ 'file' => 'creature',
+ 'data' => $trainer->getListviewData(),
+ 'params' => array(
+ 'tabs' => '$tabsRelated',
+ 'id' => 'trainer',
+ 'name' => '$LANG.tab_trainers',
+ )
+ );
+ }
+ }
+ }
+
+ // tab: quests [quests]
+ if (in_array($this->cat, [9, 11])) // only for professions
+ {
+ $sort = 0;
+ switch ($this->typeId)
+ {
+ case 182: $sort = 24; break; // Herbalism
+ case 356: $sort = 101; break; // Fishing
+ case 164: $sort = 121; break; // Blacksmithing
+ case 171: $sort = 181; break; // Alchemy
+ case 165: $sort = 182; break; // Leatherworking
+ case 202: $sort = 201; break; // Engineering
+ case 197: $sort = 264; break; // Tailoring
+ case 185: $sort = 304; break; // Cooking
+ case 129: $sort = 324; break; // First Aid
+ case 773: $sort = 371; break; // Inscription
+ case 755: $sort = 373; break; // Jewelcrafting
+ }
+
+ if ($sort)
+ {
+ $quests = new QuestList(array(['zoneOrSort', -$sort], CFG_SQL_LIMIT_NONE));
+ if (!$quests->error)
+ {
+ $this->extendGlobalData($quests->getJSGlobals());
+ $this->lvData[] = array(
+ 'file' => 'quest',
+ 'data' => $quests->getListviewData(),
+ 'params' => array(
+ 'tabs' => '$tabsRelated',
+ )
+ );
+ }
+ }
+ }
+
+ // tab: related classes (apply classes from [spells])
+ $class = [];
+ for ($i = 0; $i < 11; $i++)
+ if ($reqClass & (1 << $i))
+ $class[] = $i + 1;
+
+ if ($class)
+ {
+ $classes = new CharClassList(array(['id', $class]));
+ if (!$classes->error)
+ {
+ $this->lvData[] = array(
+ 'file' => 'class',
+ 'data' => $classes->getListviewData(),
+ 'params' => array(
+ 'tabs' => '$tabsRelated',
+ )
+ );
+ }
+ }
+
+ // tab: related races (apply races from [spells])
+ $race = [];
+ for ($i = 0; $i < 12; $i++)
+ if ($reqRace & (1 << $i))
+ $race[] = $i + 1;
+
+ if ($race)
+ {
+ $races = new CharRaceList(array(['id', $race]));
+ if (!$races->error)
+ {
+ $this->lvData[] = array(
+ 'file' => 'race',
+ 'data' => $races->getListviewData(),
'params' => array(
'tabs' => '$tabsRelated',
)
@@ -318,58 +373,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData))
}
}
}
-
- // tab: related classes (apply classes from [itemset])
- $class = [];
- for ($i = 0; $i < 11; $i++)
- if ($reqClass & (1 << $i))
- $class[] = $i + 1;
-
- if ($class)
- {
- $classes = new CharClassList(array(['id', $class]));
- if (!$classes->error)
- {
- $pageData['relTabs'][] = array(
- 'file' => 'class',
- 'data' => $classes->getListviewData(),
- 'params' => array(
- 'tabs' => '$tabsRelated',
- )
- );
- }
- }
-
- // tab: related races (apply races from [itemset])
- $race = [];
- for ($i = 0; $i < 12; $i++)
- if ($reqRace & (1 << $i))
- $race[] = $i + 1;
-
- if ($race)
- {
- $races = new CharRaceList(array(['id', $race]));
- if (!$races->error)
- {
- $pageData['relTabs'][] = array(
- 'file' => 'race',
- 'data' => $races->getListviewData(),
- 'params' => array(
- 'tabs' => '$tabsRelated',
- )
- );
- }
- }
-
- $smarty->saveCache($cacheKeyPage, $pageData);
}
-$smarty->updatePageVars($pageData['page']);
-$smarty->assign('community', CommunityContent::getAll(TYPE_SKILL, $_id)); // comments, screenshots, videos
-$smarty->assign('lang', array_merge(Lang::$main));
-$smarty->assign('lvData', $pageData['relTabs']);
-
-// load the page
-$smarty->display('detail-page-generic.tpl');
?>
diff --git a/pages/skills.php b/pages/skills.php
index 7c54a090..88672a6b 100644
--- a/pages/skills.php
+++ b/pages/skills.php
@@ -4,53 +4,57 @@ if (!defined('AOWOW_REVISION'))
die('illegal access');
-$cat = Util::extractURLParams($pageParam);
-$path = [0, 14];
-$title = [Util::ucFirst(Lang::$game['skills'])];
-$cacheKey = implode('_', [CACHETYPE_PAGE, TYPE_SKILL, -1, $cat ? $cat[0] : -1, User::$localeId]);
-$validCats = [-6, -5, -4, 6, 7, 8, 9, 10, 11];
-
-if (!Util::isValidPage($validCats, $cat))
- $smarty->error();
-
-if (!$smarty->loadCache($cacheKey, $pageData))
+// menuId 14: Skill g_initPath()
+// tabId 0: Database g_initHeader()
+class SkillsPage extends GenericPage
{
- $conditions = [['categoryId', 12, '!']]; // DND
- if ($cat)
+ use ListPage;
+
+ protected $type = TYPE_SKILL;
+ protected $tpl = 'list-page-generic';
+ protected $path = [0, 14];
+ protected $tabId = 0;
+ protected $mode = CACHETYPE_PAGE;
+ protected $validCats = [-6, -5, -4, 6, 7, 8, 9, 10, 11];
+
+ public function __construct($pageCall, $pageParam)
{
- $conditions[] = ['typeCat', $cat[0]];
- $path[] = $cat[0];
- array_unshift($title, Lang::$skill['cat'][$cat[0]]);
+ $this->getCategoryFromUrl($pageParam);;
+
+ parent::__construct();
+
+ $this->name = Util::ucFirst(Lang::$game['skills']);
}
- $skills = new SkillList($conditions);
+ protected function generateContent()
+ {
+ $conditions = [];
+ if (User::isInGroup(U_GROUP_EMPLOYEE))
+ $conditions[] = ['categoryId', 12, '!']; // GENERIC (DND)
- // menuId 14: Skill g_initPath()
- // tabId 0: Database g_initHeader()
- $pageData = array(
- 'page' => array(
- 'title' => implode(' - ', $title),
- 'path' => json_encode($path, JSON_NUMERIC_CHECK),
- 'tab' => 0
- ),
- 'lv' => array(
- array(
- 'file' => 'skill',
- 'data' => $skills->getListviewData(),
- 'params' => []
- )
- )
- );
+ if ($this->category)
+ $conditions[] = ['typeCat', $this->category[0]];
- $smarty->saveCache($cacheKey, $pageData);
+ $skills = new SkillList($conditions);
+
+ $this->lvData[] = array(
+ 'file' => 'skill',
+ 'data' => $skills->getListviewData(), // listview content
+ 'params' => []
+ );
+ }
+
+ protected function generateTitle()
+ {
+ if ($this->category)
+ array_unshift($this->title, Lang::$skill['cat'][$this->category[0]]);
+ }
+
+ protected function generatePath()
+ {
+ if ($this->category)
+ $this->path[] = $this->category[0];
+ }
}
-
-$smarty->updatePageVars($pageData['page']);
-$smarty->assign('lang', Lang::$main);
-$smarty->assign('lvData', $pageData['lv']);
-
-// load the page
-$smarty->display('list-page-generic.tpl');
-
?>
diff --git a/static/js/global.js b/static/js/global.js
index 8bbef298..f9e22272 100644
--- a/static/js/global.js
+++ b/static/js/global.js
@@ -6235,7 +6235,7 @@ Listview.extraCols = {
id: 'condition',
name: LANG.requires,
- width: '30%',
+ width: '25%',
compute: function(row, td) {
if (!row.condition || !$WH.is_array(row.condition)) {
return;
diff --git a/template/pages/itemset.tpl b/template/pages/itemset.tpl
deleted file mode 100644
index cbad0248..00000000
--- a/template/pages/itemset.tpl
+++ /dev/null
@@ -1,81 +0,0 @@
-{include file='header.tpl'}
-
-
-
-
-
-{if !empty($announcements)}
- {foreach from=$announcements item=item}
- {include file='bricks/announcement.tpl' an=$item}
- {/foreach}
-{/if}
-
-
-
-{include file='bricks/infobox.tpl'}
-
-
-{include file='bricks/headIcons.tpl'}
-
-{include file='bricks/redButtons.tpl'}
-
-
{$name}{else}>{$name}{/if}
-
-{include file='bricks/article.tpl'}
-
-{$description}
-
-
-
-
-
-
-
-{if $unavailable}
-
-
{$lang._unavailable}
-{/if}
-
-
{$lang._setBonuses}{$bonusExt}
-
- {$lang._conveyBonus}
-
-{section name=i loop=$spells}
-
-{/section}
-
-
-
{$lang.summary}
-
-
-
-
-
{$lang.related}
-
-
-{include file='bricks/tabsRelated.tpl' tabs=$lvData}
-
-{include file='bricks/contribute.tpl'}
-
-
-
-
-{include file='footer.tpl'}
diff --git a/template/pages/itemset.tpl.php b/template/pages/itemset.tpl.php
new file mode 100644
index 00000000..dfb27d65
--- /dev/null
+++ b/template/pages/itemset.tpl.php
@@ -0,0 +1,94 @@
+brick('header'); ?>
+
+
+
+
+
+brick('announcement'); ?>
+
+
+
+brick('infobox'); ?>
+
+
+brick('redButtons');
+
+if ($this->expansion):
+ echo '
'.$this->name."
\n";
+else:
+ echo '
'.$this->name."
\n";
+endif;
+
+$this->brick('article');
+
+echo $this->description;
+?>
+
+
+
+
+
+
+unavailable):
+?>
+
+
+
+
+
bonusExt; ?>
+
+
+
+spells as $i => $s):
+ echo ' '.$s['bonus'].' '.Lang::$itemset['_pieces'].Lang::$main['colon'].'
'.$s['desc']." \n";
+endforeach;
+?>
+
+
+
+
+
+
+
+
+
+
+brick('tabsRelated');
+
+$this->brick('contribute');
+?>
+
+
+
+
+brick('footer'); ?>
diff --git a/template/pages/itemsets.tpl b/template/pages/itemsets.tpl
deleted file mode 100644
index a50d391b..00000000
--- a/template/pages/itemsets.tpl
+++ /dev/null
@@ -1,114 +0,0 @@
-{include file='header.tpl'}
-
-
-
-
-
-{if !empty($announcements)}
- {foreach from=$announcements item=item}
- {include file='bricks/announcement.tpl' an=$item}
- {/foreach}
-{/if}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{include file='footer.tpl'}
diff --git a/template/pages/itemsets.tpl.php b/template/pages/itemsets.tpl.php
new file mode 100644
index 00000000..6497bda8
--- /dev/null
+++ b/template/pages/itemsets.tpl.php
@@ -0,0 +1,133 @@
+brick('header');
+$f = $this->filter
+?>
+
+
+
+
+
+brick('announcement'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+brick('footer'); ?>
diff --git a/template/pages/npc.tpl b/template/pages/npc.tpl.php
similarity index 51%
rename from template/pages/npc.tpl
rename to template/pages/npc.tpl.php
index 02681177..e3d1fa90 100644
--- a/template/pages/npc.tpl
+++ b/template/pages/npc.tpl.php
@@ -1,40 +1,42 @@
-{include file='header.tpl'}
+brick('header'); ?>
-{if !empty($announcements)}
- {foreach from=$announcements item=item}
- {include file='bricks/announcement.tpl' an=$item}
- {/foreach}
-{/if}
+brick('announcement'); ?>
-{include file='bricks/infobox.tpl'}
+brick('infobox'); ?>
-{include file='bricks/redButtons.tpl'}
+brick('redButtons'); ?>
-
{$name}{if $subname} <{$subname}>{/if}
+
name.($this->subname ? ' <'.$this->subname.'>' : null); ?>
-{include file='bricks/article.tpl'}
+brick('article');
-{if is_array($position)}
-
+if (is_array($this->position)):
+ echo '
\n";
+?>
-{elseif $position}
-
{#This_NPC_can_be_found_in#} {strip}
+position)):
+?>
+ {#This_NPC_can_be_found_in#}
{foreach from=$position item=zone name=zone}
',type:'{$point.type}'
- {rdelim}]
+ }]
{if !$smarty.foreach.point.last},{/if}
{/foreach}
]
{/if}
- {rdelim});
+ });
$WH.ge('mapper-generic').style.display='block';
{else}
$WH.ge('mapper-generic').style.display='none';
@@ -72,57 +74,84 @@
{$zone.name}{if $zone.population > 1} ({$zone.population}){/if}{if $smarty.foreach.zone.last}.{else}, {/if}
{/foreach}
-{/strip}
+
-{else}
- {$lang.unkPosition}
-{/if}
+
{$lang.quotes} ({$quotes[1]})
-
{strip}
- {foreach from=$quotes[0] item=group}
- {if $group|@count > 1}{/if}
- {/foreach}
- {/strip}
-{/if}
+if ($this->quotes[0]):
+?>
+
+
+quotes[0] as $group):
+ if (count($group) > 1 && count($this->quotes[0]) > 1):
+ echo "\n";
+ endif;
+
+ endforeach;
+?>
+
+reputation):
+?>
+
+reputation as $set):
+ if (count($this->reputation) > 1):
+ echo '
- '.$set[0].'
';
+ endif;
+
+ echo '';
+
+ foreach ($set[1] as $itr):
+ echo ''.$itr['qty'].' '.Lang::$npc['repWith'] .
+ '
'.$itr['name'].''.($itr['cap'] && $itr['qty'] > 0 ? ' ('.sprintf(Lang::$npc['stopsAt'], $itr['cap']).')' : null).'
';
+ endforeach;
+
+ echo '
';
+
+ if (count($this->reputation) > 1):
+ echo '
';
+ endif;
+ endforeach;
+endif;
+?>
+
-{include file='bricks/tabsRelated.tpl' tabs=$lvData}
-
-{include file='bricks/contribute.tpl'}
+brick('tabsRelated');
+$this->brick('contribute');
+?>
-{include file='footer.tpl'}
+brick('footer'); ?>
diff --git a/template/pages/npcs.tpl b/template/pages/npcs.tpl
deleted file mode 100644
index 8df93b93..00000000
--- a/template/pages/npcs.tpl
+++ /dev/null
@@ -1,112 +0,0 @@
-{include file='header.tpl'}
-
-
-
-
-
-{if !empty($announcements)}
- {foreach from=$announcements item=item}
- {include file='bricks/announcement.tpl' an=$item}
- {/foreach}
-{/if}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{include file='footer.tpl'}
diff --git a/template/pages/npcs.tpl.php b/template/pages/npcs.tpl.php
new file mode 100644
index 00000000..944e8e57
--- /dev/null
+++ b/template/pages/npcs.tpl.php
@@ -0,0 +1,123 @@
+brick('header');
+$f = $this->filter; // shorthand
+?>
+
+
+
+
+
+brick('announcement'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+brick('footer'); ?>