diff --git a/includes/types/achievement.class.php b/includes/types/achievement.class.php index 367849f8..07601b0c 100644 --- a/includes/types/achievement.class.php +++ b/includes/types/achievement.class.php @@ -161,7 +161,7 @@ class AchievementList extends BaseType { // link to title - todo (low): crosslink case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: - $crtName = Util::ucFirst(Lang::$game['title']).Lang::$colon.$crtName; + $crtName = Util::ucFirst(Lang::$game['title']).Lang::$main['colon'].$crtName; break; // link to quest case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: diff --git a/includes/types/item.class.php b/includes/types/item.class.php index b31e1f8d..baabc71c 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -718,13 +718,25 @@ class ItemList extends BaseType $x .= Lang::$item['durability'].' '.$dur.' / '.$dur.'
'; // required classes - if ($classes = Lang::getClassString($this->curTpl['requiredClass'])) + if ($classes = Lang::getClassString($this->curTpl['requiredClass'], $jsg, $__, $interactive)) + { + foreach ($jsg as $js) + if (empty($this->jsGlobals[TYPE_CLASS][$js])) + $this->jsGlobals[TYPE_CLASS][$js] = $js; + $x .= Lang::$game['classes'].Lang::$main['colon'].$classes.'
'; + } // required races - if ($races = Lang::getRaceString($this->curTpl['requiredRace'])) + if ($races = Lang::getRaceString($this->curTpl['requiredRace'], $__, $jsg, $__, $interactive)) + { + foreach ($jsg as $js) + if (empty($this->jsGlobals[TYPE_RACE][$js])) + $this->jsGlobals[TYPE_RACE][$js] = $js; + if ($races != Lang::$game['ra'][0]) // not "both", but display combinations like: troll, dwarf $x .= Lang::$game['races'].Lang::$main['colon'].$races.'
'; + } // required honorRank (not used anymore) if ($rhr = $this->curTpl['requiredHonorRank']) diff --git a/includes/types/quest.class.php b/includes/types/quest.class.php index 6c8ee8ba..fbe4f474 100644 --- a/includes/types/quest.class.php +++ b/includes/types/quest.class.php @@ -332,10 +332,10 @@ class QuestList extends BaseType if ($_ = $this->getField('rewardOrReqMoney')) if ($_ < 0) - $xReq .= '
- '.Lang::$quest['money'].Lang::$colon.Util::formatMoney(abs($_)); + $xReq .= '
- '.Lang::$quest['money'].Lang::$main['colon'].Util::formatMoney(abs($_)); if ($xReq) - $x .= '

'.Lang::$quest['requirements'].Lang::$colon.''.$xReq; + $x .= '

'.Lang::$quest['requirements'].Lang::$main['colon'].''.$xReq; $x .= ''; diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 0762c845..7a447bb8 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -373,6 +373,15 @@ class SpellList extends BaseType $tools = []; for ($i = 1; $i <= 2; $i++) { + // TotemCategory + if ($_ = $this->curTpl['toolCategory'.$i]) + { + $tc = DB::Aowow()->selectRow('SELECT * FROM ?_totemcategory WHERE id = ?d', $_); + $tools[$i + 1] = array( + 'id' => $_, + 'name' => Util::localizedString($tc, 'name')); + } + // Tools if (!$this->curTpl['tool'.$i]) continue; @@ -390,15 +399,6 @@ class SpellList extends BaseType break; } - - // TotemCategory - if ($_ = $this->curTpl['toolCategory'.$i]) - { - $tc = DB::Aowow()->selectRow('SELECT * FROM ?_totemcategory WHERE id = ?d', $_); - $tools[$i + 1] = array( - 'id' => $_, - 'name' => Util::localizedString($tc, 'name')); - } } $this->tools = array_reverse($tools); @@ -1533,7 +1533,7 @@ Lasts 5 min. $?$gte($pl,68)[][Cannot be used on items level 138 and higher.] if ($cId != $this->curTpl['effect'.$idx.'CreateItemId']) continue; - $createItem = $this->relItems->renderTooltip([], true, $this->id); + $createItem = $this->relItems->renderTooltip(true, $this->id); break 2; } } diff --git a/includes/utilities.php b/includes/utilities.php index 920c8c87..92e655ab 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -1288,9 +1288,10 @@ class Util return []; } + // note: omits required spell and chance in skill_discovery_template $data = array_merge( DB::Aowow()->selectCol('SELECT spellId FROM spell_learn_spell WHERE entry IN (?a)', $lookup), - DB::Aowow()->selectCol('SELECT spellId FROM skill_discovery_template WHERE reqSpell IN (?a)', $lookup), // note: omits required spell and chance + DB::Aowow()->selectCol('SELECT spellId FROM skill_discovery_template WHERE reqSpell IN (?a)', $lookup), $extraIds ); diff --git a/index.php b/index.php index 22ef36af..9c297aca 100644 --- a/index.php +++ b/index.php @@ -12,10 +12,10 @@ if (!file_exists('config/config.php')) // include all necessities, set up basics require 'includes/kernel.php'; -if (version_compare(PHP_VERSION, '5.4.0') <= 0) +if (version_compare(PHP_VERSION, '5.5.0') <= 0) { if (User::isInGroup(U_GROUP_EMPLOYEE)) - Util::addNote(U_GROUP_EMPLOYEE, 'PHP Version 5.4.0 or higher required! Your version is '.PHP_VERSION."[br]Core functions are unavailable!"); + Util::addNote(U_GROUP_EMPLOYEE, 'PHP Version 5.5.0 or higher required! Your version is '.PHP_VERSION."[br]Core functions are unavailable!"); else (new GenericPage)->maintenance(); } diff --git a/localization/lang.class.php b/localization/lang.class.php index 966ccfa9..d6902bd4 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -217,7 +217,7 @@ class Lang return implode(', ', $tmp); } - public static function getClassString($classMask, $asHTML = true, &$n = 0) + public static function getClassString($classMask, &$ids = [], &$n = 0, $asHTML = true) { $classMask &= CLASS_MASK_ALL; // clamp to available classes.. @@ -227,26 +227,25 @@ class Lang $tmp = []; $i = 1; $base = $asHTML ? '%2$s' : '[class=%d]'; - $br = $asHTML ? '' : '\n'; + $br = $asHTML ? '' : '[br]'; while ($classMask) { if ($classMask & (1 << ($i - 1))) { - $tmp[] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $i, self::$game['cl'][$i]); + $tmp[$i] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $i, self::$game['cl'][$i]); $classMask &= ~(1 << ($i - 1)); - - if (!$asHTML) - Util::$pageTemplate->extendGlobalIds(TYPE_CLASS, $i); } $i++; } - $n = count($tmp); + $n = count($tmp); + $ids = array_keys($tmp); + return implode(', ', $tmp); } - public static function getRaceString($raceMask, &$side = 0, $asHTML = true, &$n = 0) + public static function getRaceString($raceMask, &$side = 0, &$ids = [], &$n = 0, $asHTML = true) { $raceMask &= RACE_MASK_ALL; // clamp to available races.. @@ -256,7 +255,7 @@ class Lang $tmp = []; $i = 1; $base = $asHTML ? '%s' : '[race=%d]'; - $br = $asHTML ? '' : '\n'; + $br = $asHTML ? '' : '[br]'; if (!$raceMask) { @@ -280,16 +279,15 @@ class Lang { if ($raceMask & (1 << ($i - 1))) { - $tmp[] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $i, self::$game['ra'][$i]); + $tmp[$i] = (!fMod(count($tmp) + 1, 3) ? $br : null).sprintf($base, $i, self::$game['ra'][$i]); $raceMask &= ~(1 << ($i - 1)); - - if (!$asHTML) - Util::$pageTemplate->extendGlobalIds(TYPE_RACE, $i); } $i++; } - $n = count($tmp); + $n = count($tmp); + $ids = array_keys($tmp); + return implode(', ', $tmp); } } diff --git a/pages/spell.php b/pages/spell.php index dc3f567f..cbc1d0a6 100644 --- a/pages/spell.php +++ b/pages/spell.php @@ -4,249 +4,1135 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); -require 'includes/community.class.php'; - -$_id = intVal($pageParam); -$_path = [0, 1]; - -$cacheKeyPage = implode('_', [CACHETYPE_PAGE, TYPE_SPELL, $_id, -1, User::$localeId]); -$cacheKeyTooltip = implode('_', [CACHETYPE_TOOLTIP, TYPE_SPELL, $_id, -1, User::$localeId]); - -// AowowPower-request -if (isset($_GET['power'])) +// menuId 1: Spell g_initPath() +// tabId 0: Database g_initHeader() +class SpellPage extends GenericPage { - header('Content-type: application/x-javascript; charsetUTF-8'); + use DetailPage; - Util::powerUseLocale(@$_GET['domain']); + protected $type = TYPE_SPELL; + protected $typeId = 0; + protected $tpl = 'spell'; + protected $path = [0, 1]; + protected $tabId = 0; + protected $mode = CACHETYPE_PAGE; + protected $js = ['swfobject.js']; - if (!$smarty->loadCache($cacheKeyTooltip, $x)) + private $difficulties = []; + private $firstRank = 0; + + public function __construct($__, $id) { - $spell = new SpellList(array(['s.id', $_id])); - if ($spell->error) - die('$WowheadPower.registerSpell('.$_id.', '.User::$localeId.', {});'); + parent::__construct(); - $x = '$WowheadPower.registerSpell('.$_id.', '.User::$localeId.", {\n"; + // temp locale + if ($this->mode == CACHETYPE_TOOLTIP && isset($_GET['domain'])) + Util::powerUseLocale($_GET['domain']); + + $this->typeId = intVal($id); + + $this->subject = new SpellList(array(['id', $this->typeId])); + if ($this->subject->error) + $this->notFound(Lang::$game['spell']); + + $jsg = $this->subject->getJSGlobals(GLOBALINFO_ANY, $extra); + $this->extendGlobalData($jsg, $extra); + + $this->name = $this->subject->getField('name', true); + + // has difficulty versions of itself + $this->difficulties = DB::Aowow()->selectRow( + 'SELECT normal10 AS "0", normal25 AS "1", + heroic10 AS "2", heroic25 AS "3" + FROM ?_spelldifficulty + WHERE normal10 = ?d OR normal25 = ?d OR + heroic10 = ?d OR heroic25 = ?d', + $this->typeId, $this->typeId, $this->typeId, $this->typeId + ); + + // returns self or firstRank + $this->firstRank = DB::Aowow()->selectCell( + 'SELECT IF(s1.rankId <> 1 AND s2.id, s2.id, s1.id) + FROM ?_spell s1 + LEFT JOIN ?_spell s2 + ON s1.SpellFamilyId = s2.SpelLFamilyId AND s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 AND + s1.SpellFamilyFlags2 = s2.SpellFamilyFlags2 AND s1.SpellFamilyFlags3 = s2.SpellFamilyFlags3 AND + s1.name_loc0 = s2.name_loc0 AND s2.RankId = 1 + WHERE s1.id = ?d', + $this->typeId + ); + } + + protected function generatePath() + { + $cat = $this->subject->getField('typeCat'); + $cf = $this->subject->getField('cuFlags'); + + $this->path[] = $cat; + + // reconstruct path + switch ($cat) + { + case -2: + case 7: + case -13: + if ($cl = $this->subject->getField('reqClassMask')) + $this->path[] = log($cl, 2) + 1; + + if ($cat == -13) + $this->path[] = ($cf & (SPELL_CU_GLYPH_MAJOR | SPELL_CU_GLYPH_MINOR)) >> 6; + else + $this->path[] = $this->subject->getField('skillLines')[0]; + + break; + case 9: + case -3: + case 11: + $this->path[] = $this->subject->getField('skillLines')[0]; + + if ($cat == 11) + if ($_ = $this->subject->getField('reqSpellId')) + $this->path[] = $_; + + break; + case -11: + foreach (SpellList::$skillLines as $line => $skills) + if (in_array($this->subject->getField('skillLines')[0], $skills)) + $this->path[] = $line; + break; + case -7: // only spells unique in skillLineAbility will always point to the right skillLine :/ + if ($cf & SPELL_CU_PET_TALENT_TYPE0) + $this->path[] = 411; // Ferocity + else if ($cf & SPELL_CU_PET_TALENT_TYPE1) + $this->path[] = 409; // Tenacity + else if ($cf & SPELL_CU_PET_TALENT_TYPE2) + $this->path[] = 410; // Cunning + } + } + + protected function generateTitle() + { + array_unshift($this->title, $this->name, Util::ucFirst(Lang::$game['spell'])); + } + + protected function generateContent() + { + $_cat = $this->subject->getField('typeCat'); + + /***********/ + /* Infobox */ + /***********/ + + $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); + + // level + if (!in_array($_cat, [-5, -6])) // not mount or vanity pet + { + if ($_ = $this->subject->getField('talentLevel')) + $infobox[] = '[li]'.(in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::$game['reqLevel'], $_) : Lang::$game['level'].Lang::$main['colon'].$_).'[/li]'; + else if ($_ = $this->subject->getField('spellLevel')) + $infobox[] = '[li]'.(in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::$game['reqLevel'], $_) : Lang::$game['level'].Lang::$main['colon'].$_).'[/li]'; + } + + // races + if ($_ = Lang::getRaceString($this->subject->getField('reqRaceMask'), $__, $jsg, $n, false)) + { + if ($_ != Lang::$game['ra'][0]) // omit: "both" + { + $this->extendGlobalIds(TYPE_RACE, $jsg); + $t = $n == 1 ? Lang::$game['race'] : Lang::$game['races']; + $infobox[] = '[li]'.Util::ucFirst($t).Lang::$main['colon'].$_.'[/li]'; + } + } + + // classes + if ($_ = Lang::getClassString($this->subject->getField('reqClassMask'), $jsg, $n, false)) + { + $this->extendGlobalIds(TYPE_CLASS, $jsg); + $t = $n == 1 ? Lang::$game['class'] : Lang::$game['classes']; + $infobox[] = '[li]'.Util::ucFirst($t).Lang::$main['colon'].$_.'[/li]'; + } + + // spell focus + if ($_ = $this->subject->getField('spellFocusObject')) + { + $bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellFocusObject WHERE id = ?d', $_); + $focus = new GameObjectList(array(['spellFocusId', $_], 1)); + $infobox[] = '[li]'.Lang::$game['requires2'].' '.($focus->error ? Util::localizedString($bar, 'name') : '[url=?object='.$focus->id.']'.Util::localizedString($bar, 'name').'[/url]').'[/li]'; + } + + // primary & secondary trades + if (in_array($_cat, [9, 11])) + { + // skill + if ($_ = $this->subject->getField('skillLines')[0]) + { + $rSkill = new SkillList(array(['id', $_])); + if (!$rSkill->error) + { + $this->extendGlobalData($rSkill->getJSGlobals()); + + $bar = sprintf(Lang::$game['requires'], '[skill='.$rSkill->id.']'); + if ($_ = $this->subject->getField('learnedAt')) + $bar .= ' ('.$_.')'; + + $infobox[] = '[li]'.$bar.'[/li]'; + } + } + + // specialization + if ($_ = $this->subject->getField('reqSpellId')) + { + $rSpell = new SpellList(array(['id', $_])); + if (!$rSpell->error) + { + $this->extendGlobalData($rSpell->getJSGlobals()); + $infobox[] = '[li]'.Lang::$game['requires2'].' [spell='.$rSpell->id.'][/li]'; + } + } + + // difficulty + if ($_ = $this->subject->getColorsForCurrent()) + { + $bar = []; + for ($i = 0; $i < 4; $i++) + if ($_[$i]) + $bar[] = '[color=r'.($i + 1).']'.$_[$i].'[/color]'; + + $infobox[] = '[li]'.Lang::$game['difficulty'].Lang::$main['colon'].implode(' ', $bar).'[/li]'; + } + } + + // accquisition.. + if ($_ = @$this->subject->sources[$this->subject->id]) + { + if (array_key_exists(10, $_)) // ..starter spell + $infobox[] = '[li]'.Lang::$spell['starter'].'[/li]'; + else if (array_key_exists(7, $_)) // ..discovery + $infobox[] = '[li]'.Lang::$spell['discovered'].'[/li]'; + } + + // training cost + if ($cost = DB::Aowow()->selectCell('SELECT spellcost FROM npc_trainer WHERE spell = ?d', $this->subject->id)) + $infobox[] = '[li]'.Lang::$spell['trainingCost'].Lang::$main['colon'].'[money='.$cost.'][/li]'; + + // used in mode + foreach ($this->difficulties as $n => $id) + if ($id == $this->typeId) // "Mode" seems to be multilingual acceptable + $infobox[] = '[li]Mode'.Lang::$main['colon'].Lang::$game['modes'][$n].'[/li]'; + + + /****************/ + /* Main Content */ + /****************/ + + $redButtons = array( + BUTTON_LINKS => ['color' => 'ff71d5ff', 'linkId' => Util::$typeStrings[TYPE_SPELL].':'.$this->typeId], + BUTTON_VIEW3D => false, + BUTTON_WOWHEAD => true + ); + + $this->reagents = $this->createReagentList(); + $this->scaling = $this->createScalingData(); + $this->items = $this->createRequiredItems(); + $this->tools = $this->createTools(); + $this->effects = $this->createEffects($infobox, $redButtons); + $this->infobox = $infobox ? '[ul]'.implode('', $infobox).'[/ul]' : null; + $this->powerCost = $this->subject->createPowerCostForCurrent(); + $this->castTime = $this->subject->createCastTimeForCurrent(false, false); + $this->name = $this->subject->getField('name', true); + $this->headIcons = [$this->subject->getField('iconString'), $this->subject->getField('stackAmount')]; + $this->level = $this->subject->getField('spellLevel'); + $this->rangeName = $this->subject->getField('rangeText', true); + $this->range = $this->subject->getField('rangeMaxHostile'); + $this->gcd = Util::formatTime($this->subject->getField('startRecoveryTime')); + $this->gcdCat = null; // todo (low): nyi; find out how this works [n/a; normal; ..] + $this->school = [Util::asHex($this->subject->getField('schoolMask')), Lang::getMagicSchools($this->subject->getField('schoolMask'))]; + $this->dispel = Lang::$game['dt'][$this->subject->getField('dispelType')]; + $this->mechanic = Lang::$game['me'][$this->subject->getField('mechanic')]; + $this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE; + $this->redButtons = $redButtons; + + // minRange exists.. prepend + if ($_ = $this->subject->getField('rangeMinHostile')) + $this->range = $_.' - '.$this->range; + + if ($this->subject->getField('attributes2') & 0x80000) + $this->stances = Lang::getStances($this->subject->getField('stanceMask')); + + if (($_ = $this->subject->getField('recoveryTime')) && $_ > 0) + $this->cooldown = Util::formatTime($_); + + if (($_ = $this->subject->getField('duration')) && $_ > 0) + $this->duration = Util::formatTime($_); + + + + // factionchange-equivalent + /* nyi + $pendant = DB::Aowow()->selectCell('SELECT IF(hordethis->typeId = ?d, alliancethis->typeId, -hordethis->typeId) FROM player_factionchange_spells WHERE alliancethis->typeId = ?d OR hordethis->typeId = ?d', $this->typeId, $this->typeId, $this->typeId); + if ($pendant) + { + $altiSpell = new SpellList(array(['id', abs($pendant)])); + if (!$altSpell->error) + { + $this->transfer = array( + 'id' => $altItem->id, + 'icon' => $altItem->getField('iconString'), + 'name' => $altItem->getField('name', true), + 'facInt' => $pendant > 0 ? 'alliance' : 'horde', + 'facName' => $pendant > 0 ? Lang::$game['si'][1] : Lang::$game['si'][2] + ); + ) + } + */ + + /**************/ + /* Extra Tabs */ + /**************/ + + $j = [null, 'A', 'B', 'C']; + + // tab: modifies $this + $sub = ['OR']; + $conditions = [ + ['s.typeCat', [0, -9, -8], '!'], // uncategorized (0), GM (-9), NPC-Spell (-8); NPC includes totems, lightwell and others :/ + ['s.spellFamilyId', $this->subject->getField('spellFamilyId')], + &$sub + ]; + + for ($i = 1; $i < 4; $i++) + { + // Flat Mods (107), Pct Mods (108), No Reagent Use (256) .. include dummy..? (4) + if (!in_array($this->subject->getField('effect'.$i.'AuraId'), [107, 108, 256 /*, 4*/])) + continue; + + $m1 = $this->subject->getField('effect1SpellClassMask'.$j[$i]); + $m2 = $this->subject->getField('effect2SpellClassMask'.$j[$i]); + $m3 = $this->subject->getField('effect3SpellClassMask'.$j[$i]); + + if (!$m1 && !$m2 && !$m3) + continue; + + $sub[] = ['s.spellFamilyFlags1', $m1, '&']; + $sub[] = ['s.spellFamilyFlags2', $m2, '&']; + $sub[] = ['s.spellFamilyFlags3', $m3, '&']; + } + + if (count($sub) > 1) + { + $modSpells = new SpellList($conditions); + if (!$modSpells->error) + { + if (!$modSpells->hasSetFields(['skillLines'])) + $msH = "$['skill']"; + + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $modSpells->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'modifies', + 'name' => '$LANG.tab_modifies', + 'visibleCols' => "$['level']", + 'hiddenCols' => isset($msH) ? $msH : null + ] + ); + + $this->extendGlobalData($modSpells->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + } + + // tab: modified by $this + $sub = ['OR']; + $conditions = [ + ['s.spellFamilyId', $this->subject->getField('spellFamilyId')], + &$sub + ]; + + for ($i = 1; $i < 4; $i++) + { + $m1 = $this->subject->getField('spellFamilyFlags1'); + $m2 = $this->subject->getField('spellFamilyFlags2'); + $m3 = $this->subject->getField('spellFamilyFlags3'); + + if (!$m1 && !$m2 && !$m3) + continue; + + $sub[] = array( + 'AND', + ['s.effect'.$i.'AuraId', [107, 108, 256 /*, 4*/]], + [ + 'OR', + ['s.effect1SpellClassMask'.$j[$i], $m1, '&'], + ['s.effect2SpellClassMask'.$j[$i], $m2, '&'], + ['s.effect3SpellClassMask'.$j[$i], $m3, '&'] + ] + ); + } + + if (count($sub) > 1) + { + $modsSpell = new SpellList($conditions); + if (!$modsSpell->error) + { + if (!$modsSpell->hasSetFields(['skillLines'])) + $mbH = "$['skill']"; + + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $modsSpell->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'modified-by', + 'name' => '$LANG.tab_modifiedby', + 'visibleCols' => "$['level']", + 'hiddenCols' => isset($mbH) ? $mbH : null + ] + ); + + $this->extendGlobalData($modsSpell->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + } + + // tab: see also + $conditions = array( + ['s.schoolMask', $this->subject->getField('schoolMask')], + ['s.effect1Id', $this->subject->getField('effect1Id')], + ['s.effect2Id', $this->subject->getField('effect2Id')], + ['s.effect3Id', $this->subject->getField('effect3Id')], + ['s.id', $this->subject->id, '!'], + ['s.name_loc'.User::$localeId, $this->subject->getField('name', true)] + ); + + $saSpells = new SpellList($conditions); + if (!$saSpells->error) + { + $data = $saSpells->getListviewData(); + if ($this->difficulties) // needs a way to distinguish between dungeon and raid :x; creature using this -> map -> areaType? + { + $saE = '$[Listview.extraCols.mode]'; + + foreach ($data as $id => &$d) + { + $d['modes'] = ['mode' => 0]; + + if ($this->difficulties[0] == $id) // b0001000 + { + if (!$this->difficulties[2] && !$this->difficulties[3]) + $d['modes']['mode'] |= 0x2; + else + $d['modes']['mode'] |= 0x8; + } + + if ($this->difficulties[1] == $id) // b0010000 + { + if (!$this->difficulties[2] && !$this->difficulties[3]) + $d['modes']['mode'] |= 0x1; + else + $d['modes']['mode'] |= 0x10; + } + + if ($this->difficulties[2] == $id) // b0100000 + $d['modes']['mode'] |= 0x20; + + if ($this->difficulties[3] == $id) // b1000000 + $d['modes']['mode'] |= 0x40; + } + } + + if (!$saSpells->hasSetFields(['skillLines'])) + $saH = "$['skill']"; + + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $data, + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'see-also', + 'name' => '$LANG.tab_seealso', + 'visibleCols' => "$['level']", + 'extraCols' => isset($saE) ? $saE : null, + 'hiddenCols' => isset($saH) ? $saH : null + ] + ); + + $this->extendGlobalData($saSpells->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + + // tab: used by - itemset + $conditions = array( + 'OR', + ['spell1', $this->subject->id], ['spell2', $this->subject->id], ['spell3', $this->subject->id], ['spell4', $this->subject->id], + ['spell5', $this->subject->id], ['spell6', $this->subject->id], ['spell7', $this->subject->id], ['spell8', $this->subject->id] + ); + + $ubSets = new ItemsetList($conditions); + if (!$ubSets->error) + { + $this->lvData[] = array( + 'file' => 'itemset', + 'data' => $ubSets->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'used-by-itemset', + 'name' => '$LANG.tab_usedby' + ] + ); + + $this->extendGlobalData($ubSets->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + + // tab: used by - item + $conditions = array( + 'OR', // 6: learn spell + ['AND', ['spellTrigger1', 6, '!'], ['spellId1', $this->subject->id]], + ['AND', ['spellTrigger2', 6, '!'], ['spellId2', $this->subject->id]], + ['AND', ['spellTrigger3', 6, '!'], ['spellId3', $this->subject->id]], + ['AND', ['spellTrigger4', 6, '!'], ['spellId4', $this->subject->id]], + ['AND', ['spellTrigger5', 6, '!'], ['spellId5', $this->subject->id]] + ); + + $ubItems = new ItemList($conditions); + if (!$ubItems->error) + { + $this->lvData[] = array( + 'file' => 'item', + 'data' => $ubItems->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'used-by-item', + 'name' => '$LANG.tab_usedby' + ] + ); + + $this->extendGlobalData($ubItems->getJSGlobals(GLOBALINFO_SELF)); + } + + // tab: used by - object + $conditions = array( + 'OR', + ['onUseSpell', $this->subject->id], ['onSuccessSpell', $this->subject->id], + ['auraSpell', $this->subject->id], ['triggeredSpell', $this->subject->id] + ); + + $ubObjects = new GameObjectList($conditions); + if (!$ubObjects->error) + { + $this->lvData[] = array( + 'file' => 'object', + 'data' => $ubObjects->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'used-by-object', + 'name' => '$LANG.tab_usedby' + ] + ); + + $this->extendGlobalData($ubObjects->getJSGlobals()); + } + + // tab: criteria of + $conditions = array( + ['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL] + ], + ['ac.value1', $this->typeId] + ); + $coAchievemnts = new AchievementList($conditions); + if (!$coAchievemnts->error) + { + $this->lvData[] = array( + 'file' => 'achievement', + 'data' => $coAchievemnts->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'criteria-of', + 'name' => '$LANG.tab_criteriaof' + ] + ); + + $this->extendGlobalData($coAchievemnts->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + + // tab: contains + // spell_loot_template & skill_extra_item_template + $extraItem = DB::Aowow()->selectRow('SELECT * FROM skill_extra_item_template WHERE spellid = ?d', $this->subject->id); + $spellLoot = new Loot(); + + if ($spellLoot->getByContainer(LOOT_SPELL, $this->subject->id) || $extraItem) + { + $lv = $spellLoot->getResult(); + $extraCols = $spellLoot->extraCols; + $extraCols[] = 'Listview.extraCols.percent'; + + if ($extraItem && $this->subject->canCreateItem()) + { + $foo = $this->subject->relItems->getListviewData(); + + for ($i = 1; $i < 4; $i++) + { + if (($bar = $this->subject->getField('effect'.$i.'CreateItemId')) && isset($foo[$bar])) + { + $lv[$bar] = $foo[$bar]; + $lv[$bar]['percent'] = $extraItem['additionalCreateChance']; + $lv[$bar]['condition'][] = ['type' => TYPE_SPELL, 'typeId' => $extraItem['requiredSpecialization'], 'status' => 2]; + $this->extendGlobalIds(TYPE_SPELL, $extraItem['requiredSpecialization']); + + $extraCols[] = 'Listview.extraCols.condition'; + if ($max = $extraItem['additionalMaxNum']) + { + $lv[$bar]['mincount'] = 1; + $lv[$bar]['maxcount'] = $max; + } + + break; // skill_extra_item_template can only contain 1 item + } + } + } + + $this->lvData[] = array( + 'file' => 'item', + 'data' => $lv, + 'params' => [ + 'tabs' => '$tabsRelated', + 'name' => '$LANG.tab_contains', + 'id' => 'contains', + 'hiddenCols' => "$['side', 'slot', 'source', 'reqlevel']", + 'extraCols' => '$'.json_encode($extraCols, JSON_NUMERIC_CHECk) + ] + ); + } + + // tab: exclusive with + if ($this->firstRank) { + $linkedSpells = DB::Aowow()->selectCol( // dont look too closely ..... please..? + 'SELECT IF(sg2.spell_id < 0, sg2.id, sg2.spell_id) AS ARRAY_KEY, IF(sg2.spell_id < 0, sg2.spell_id, sr.stack_rule) + FROM spell_group sg1 + JOIN spell_group sg2 + ON (sg1.id = sg2.id OR sg1.id = -sg2.spell_id) AND sg1.spell_id != sg2.spell_id + LEFT JOIN spell_group_stack_rules sr + ON sg1.id = sr.group_id + WHERE sg1.spell_id = ?d', + $this->firstRank + ); + + if ($linkedSpells) + { + $extraSpells = []; + foreach ($linkedSpells as $k => $v) + { + if ($v > 0) + continue; + + $extraSpells += DB::Aowow()->selectCol( // recursive case (recursive and regular ids are not mixed in a group) + 'SELECT sg2.spell_id AS ARRAY_KEY, sr.stack_rule + FROM spell_group sg1 + JOIN spell_group sg2 + ON sg2.id = -sg1.spell_id AND sg2.spell_id != ?d + LEFT JOIN spell_group_stack_rules sr + ON sg1.id = sr.group_id + WHERE sg1.id = ?d', + $this->firstRank, + $k + ); + + unset($linkedSpells[$k]); + } + + $groups = $linkedSpells + $extraSpells; + $stacks = new SpellList(array(['s.id', array_keys($groups)])); + + if (!$stacks->error) + { + $data = $stacks->getListviewData(); + foreach ($data as $k => $d) + $data[$k]['stackRule'] = $groups[$k]; + + if (!$stacks->hasSetFields(['skillLines'])) + $sH = "$['skill']"; + + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $data, + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'spell-group-stack', + 'name' => 'Stack Group', // todo (med): localize + 'visibleCols' => "$['stackRules']", + 'hiddenCols' => isset($sH) ? $sH : null + ] + ); + + $this->extendGlobalData($stacks->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + } + } + + // tab: linked with + $rows = DB::Aowow()->select(' + SELECT spell_trigger AS `trigger`, + spell_effect AS effect, + type, + IF(ABS(spell_effect) = ?d, ABS(spell_trigger), ABS(spell_effect)) AS related + FROM spell_linked_spell + WHERE ABS(spell_effect) = ?d OR ABS(spell_trigger) = ?d', + $this->typeId, $this->typeId, $this->typeId + ); + + $related = []; + foreach ($rows as $row) + $related[] = $row['related']; + + if ($related) + $linked = new SpellList(array(['s.id', $related])); + + if (isset($linked) && !$linked->error) + { + $lv = $linked->getListviewData(); + $data = []; + + foreach ($rows as $r) + { + foreach ($lv as $dk => $d) + { + if ($r['related'] != $dk) + continue; + + $lv[$dk]['linked'] = [$r['trigger'], $r['effect'], $r['type']]; + $data[] = $lv[$dk]; + break; + } + } + + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $data, + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'spell-link', + 'name' => 'Linked with', // todo (med): localize + 'hiddenCols' => "$['skill', 'name']", + 'visibleCols' => "$['linkedTrigger', 'linkedEffect']" + ] + ); + + $this->extendGlobalData($linked->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + } + + + // tab: triggered by + $conditions = array( + 'OR', + ['AND', ['OR', ['effect1Id', SpellList::$effects['trigger']], ['effect1AuraId', SpellList::$auras['trigger']]], ['effect1TriggerSpell', $this->subject->id]], + ['AND', ['OR', ['effect2Id', SpellList::$effects['trigger']], ['effect2AuraId', SpellList::$auras['trigger']]], ['effect2TriggerSpell', $this->subject->id]], + ['AND', ['OR', ['effect3Id', SpellList::$effects['trigger']], ['effect3AuraId', SpellList::$auras['trigger']]], ['effect3TriggerSpell', $this->subject->id]], + ); + + $trigger = new SpellList($conditions); + if (!$trigger->error) + { + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $trigger->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'triggered-by', + 'name' => '$LANG.tab_triggeredby' + ] + ); + + $this->extendGlobalData($trigger->getJSGlobals(GLOBALINFO_SELF)); + } + + // tab: used by - creature + // SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86 + $conditions = array( + 'OR', + ['spell1', $this->typeId], ['spell2', $this->typeId], ['spell3', $this->typeId], ['spell4', $this->typeId], + ['spell5', $this->typeId], ['spell6', $this->typeId], ['spell7', $this->typeId], ['spell8', $this->typeId] + ); + if ($_ = DB::Aowow()->selectCol('SELECT entryOrGUID FROM smart_scripts WHERE entryorguid > 0 AND source_type = 0 AND action_type IN (11, 75, 85, 86) AND action_param1 = ?d', $this->typeId)) + $conditions[] = ['id', $_]; + + $ubCreature = new CreatureList($conditions); + if (!$ubCreature->error) + { + $this->lvData[] = array( + 'file' => 'creature', + 'data' => $ubCreature->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'used-by-npc', + 'name' => '$LANG.tab_usedby' + ] + ); + + $this->extendGlobalData($ubCreature->getJSGlobals(GLOBALINFO_SELF)); + } + + // tab: zone + if ($areas = DB::Aowow()->select('SELECT * FROM spell_area WHERE spell = ?d', $this->typeId)) + { + $zones = new ZoneList(array(['id', array_column($areas, 'area')])); + if (!$zones->error) + { + $lvZones = $zones->getListviewData(); + $this->extendGlobalData($zones->getJSGlobals()); + + $lv = []; + $parents = []; + foreach ($areas as $a) + { + if (empty($lvZones[$a['area']])) + continue; + + $_ = ['condition' => []]; + $extra = false; + if ($a['aura_spell']) + { + $this->extendGlobalIds(TYPE_SPELL, $a['aura_spell']); + $_['condition'][] = array( + 'type' => TYPE_SPELL, + 'typeId' => abs($a['aura_spell']), + 'status' => $a['aura_spell'] > 0 ? 1 : 0 + ); + } + + if ($a['quest_start']) // status for quests needs work + { + $this->extendGlobalIds(TYPE_QUEST, $a['quest_start']); + $_['condition'][] = array( + 'type' => TYPE_QUEST, + 'typeId' => $a['quest_start'], + 'status' => $a['quest_start_status'] & 0x8 ? 1 : 2 + ); + } + + if ($a['quest_end'] && $a['quest_end'] != $a['quest_start']) + { + $this->extendGlobalIds(TYPE_QUEST, $a['quest_end']); + $_['condition'][] = array( + 'type' => TYPE_QUEST, + 'typeId' => $a['quest_end'], + 'status' => $a['quest_start_status'] & 0x8 ? 1 : 0 + ); + } + + if ($a['racemask']) + { + $foo = []; + for ($i = 0; $i < 10; $i++) + if ($a['racemask'] & $i) + $foo[] = $i + 1; + + $this->extendGlobalIds(TYPE_RACE, $foo); + $_['condition'][] = array( + 'type' => TYPE_RACE, + 'typeId' => $a['racemask'], + 'status' => 1 + ); + } + + if ($a['gender'] != 2) // 2: both + $_['condition'][] = ['gender' => $a['gender'] + 1]; + + if ($_['condition']) + $extra = true; + + $row = array_merge($_, $lvZones[$a['area']]); + + // merge subzones, into one row, if: conditions match && parentZone is shared + if ($p = $zones->getEntry($a['area'])['parentArea']) + { + $parents[] = $p; + $row['parentArea'] = $p; + $row['subzones'] = [$a['area']]; + } + else + $row['parentArea'] = 0; + + $set = false; + foreach ($lv as &$v) + { + if ($v['condition'] != $row['condition'] || ($v['parentArea'] != $row['parentArea'] && $v['id'] != $row['parentArea'])) + continue; + + if (!$row['parentArea'] && $v['id'] != $row['parentArea']) + continue; + + $set = true; + $v['subzones'][] = $row['id']; + break; + } + + // add self as potential subzone; IF we are a parentZone without added children, we get filtered in JScript + if (!$set) + { + $row['subzones'] = [$row['id']]; + $lv[] = $row; + } + } + + // overwrite lvData with parent-lvData (condition and subzones are kept) + if ($parents) + { + $parents = (new ZoneList(array(['id', $parents])))->getListviewData(); + foreach ($lv as &$_) + if (isset($parents[$_['parentArea']])) + $_ = array_merge($_, $parents[$_['parentArea']]); + } + + $this->lvData[] = array( + 'file' => 'zone', + 'data' => $lv, + 'params' => [ + 'tabs' => '$tabsRelated', + 'extraCols' => $extra ? '$[Listview.extraCols.condition]' : null, + 'hiddenCols' => $extra ? "$['instancetype']" : null + ] + ); + } + } + + // tab: teaches + if ($ids = Util::getTaughtSpells($this->subject)) + { + $teaches = new SpellList(array(['id', $ids])); + if (!$teaches->error) + { + $this->extendGlobalData($teaches->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + $vis = ['level', 'schools']; + $hid = []; + if (!$teaches->hasSetFields(['skillLines'])) + $hid[] = 'skill'; + + foreach ($teaches->iterate() as $__) + { + if (!$teaches->canCreateItem()) + continue; + + $vis[] = 'reagents'; + break; + } + + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $teaches->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'teaches-spell', + 'name' => '$LANG.tab_teaches', + 'visibleCols' => '$'.json_encode($vis), + 'hiddenCols' => $hid ? '$'.json_encode($hid) : null + ] + ); + } + } + + // tab: taught by npc (source:6 => trainer) + $src = @$this->subject->sources[$this->typeId]; + if (!empty($src) && in_array(6, array_keys($src))) + { + $list = []; + if (count($src[6]) == 1 && $src[6][0] == 0) // multiple trainer + { + $tt = null; + // Professions + if (in_array($_cat, [9, 11])) + $tt = @Util::$trainerTemplates[TYPE_SKILL][$this->subject->getField('skillLines')[0]]; + // Class Spells + else if ($_cat == 7 && $this->subject->getField('reqClassMask')) + { + $clId = log($this->subject->getField('reqClassMask'), 2) + 1 ; + if (intVal($clId) == $clId) // only one class was set, so float == int + $tt = @Util::$trainerTemplates[TYPE_CLASS][$clId]; + } + + if ($tt) + $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] == $this->typeId) + $mask |= 1 << $idx; + + $list = DB::Aowow()->selectCol(' + SELECT IF(t1.entry > 200000, t2.entry, t1.entry) + FROM npc_trainer t1 + LEFT JOIN npc_trainer t2 ON t2.spell = -t1.entry + WHERE t1.spell = ?d', + $this->typeId + ); + } + } + else if ($src[6]) + $list = array_values($src[6]); + + if ($list) + { + $tbTrainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&'])); + if (!$tbTrainer->error) + { + $this->extendGlobalData($tbTrainer->getJSGlobals()); + $this->lvData[] = array( + 'file' => 'creature', + 'data' => $tbTrainer->getListviewData(), + 'params' => array( + 'tabs' => '$tabsRelated', + 'id' => 'taught-by-npc', + 'name' => '$LANG.tab_taughtby', + ) + ); + } + } + } + + // tab: taught by spell + $conditions = array( + 'OR', + ['AND', ['effect1Id', SpellList::$effects['teach']], ['effect1TriggerSpell', $this->subject->id]], + ['AND', ['effect2Id', SpellList::$effects['teach']], ['effect2TriggerSpell', $this->subject->id]], + ['AND', ['effect3Id', SpellList::$effects['teach']], ['effect3TriggerSpell', $this->subject->id]], + ); + + $tbSpell = new SpellList($conditions); + $tbsData = []; + if (!$tbSpell->error) + { + $tbsData = $tbSpell->getListviewData(); + $this->lvData[] = array( + 'file' => 'spell', + 'data' => $tbsData, + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'taught-by-spell', + 'name' => '$LANG.tab_taughtby' + ] + ); + + $this->extendGlobalData($tbSpell->getJSGlobals(GLOBALINFO_SELF)); + } + + // tab: taught by quest + $conditions = ['OR', ['sourceSpellId', $this->typeId], ['rewardSpell', $this->typeId]]; + if ($tbsData) + { + $conditions[] = ['rewardSpell', array_keys($tbsData)]; + if (User::isInGroup(U_GROUP_EMPLOYEE)) + $conditions[] = ['rewardSpellCast', array_keys($tbsData)]; + } + if (User::isInGroup(U_GROUP_EMPLOYEE)) + $conditions[] = ['rewardSpellCast', $this->typeId]; + + $tbQuest = new QuestList($conditions); + if (!$tbQuest->error) + { + $this->lvData[] = array( + 'file' => 'quest', + 'data' => $tbQuest->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'reward-from-quest', + 'name' => '$LANG.tab_rewardfrom' + ] + ); + + $this->extendGlobalData($tbQuest->getJSGlobals()); + } + + // tab: taught by item (i'd like to precheck $this->subject->sources, but there is no source:item only complicated crap like "drop" and "vendor") + $conditions = array( + 'OR', + ['AND', ['spellTrigger1', 6], ['spellId1', $this->subject->id]], + ['AND', ['spellTrigger2', 6], ['spellId2', $this->subject->id]], + ['AND', ['spellTrigger3', 6], ['spellId3', $this->subject->id]], + ['AND', ['spellTrigger4', 6], ['spellId4', $this->subject->id]], + ['AND', ['spellTrigger5', 6], ['spellId5', $this->subject->id]], + ); + + $tbItem = new ItemList($conditions); + if (!$tbItem->error) + { + $this->lvData[] = array( + 'file' => 'item', + 'data' => $tbItem->getListviewData(), + 'params' => [ + 'tabs' => '$tabsRelated', + 'id' => 'taught-by-item', + 'name' => '$LANG.tab_taughtby' + ] + ); + + $this->extendGlobalData($tbItem->getJSGlobals(GLOBALINFO_SELF)); + } + + // find associated NPC, Item and merge results + // taughtbypets (unused..?) + // taughtbyquest (usually the spell casted as quest reward teaches something; exclude those seplls from taughtBySpell) + // taughtbytrainers + // taughtbyitem + + + /* NEW + conditions + */ + + } + + protected function generateTooltip($asError = false) + { + if ($asError) + die('$WowheadPower.registerSpell('.$this->typeId.', '.User::$localeId.', {});'); + + $x = '$WowheadPower.registerSpell('.$this->typeId.', '.User::$localeId.", {\n"; $pt = []; - if ($n = $spell->getField('name', true)) + if ($n = $this->subject->getField('name', true)) $pt[] = "\tname_".User::$localeString.": '".Util::jsEscape($n)."'"; - if ($i = $spell->getField('iconString')) + if ($i = $this->subject->getField('iconString')) $pt[] = "\ticon: '".urlencode($i)."'"; - if ($tt = $spell->renderTooltip()) + if ($tt = $this->subject->renderTooltip()) { $pt[] = "\ttooltip_".User::$localeString.": '".Util::jsEscape($tt[0])."'"; $pt[] = "\tspells_".User::$localeString.": ".json_encode($tt[1], JSON_UNESCAPED_UNICODE); } - if ($btt = $spell->renderBuff()) + if ($btt = $this->subject->renderBuff()) { $pt[] = "\tbuff_".User::$localeString.": '".Util::jsEscape($btt[0])."'"; $pt[] = "\tbuffspells_".User::$localeString.": ".json_encode($btt[1], JSON_UNESCAPED_UNICODE);; } $x .= implode(",\n", $pt)."\n});"; - $smarty->saveCache($cacheKeyTooltip, $x); + return $x; } - die($x); -} - -// regular page -if (!$smarty->loadCache($cacheKeyPage, $pageData)) -{ - $spell = new SpellList(array(['s.id', $_id])); - if ($spell->error) - $smarty->notFound(Lang::$game['spell'], $_id); - - $spell->addGlobalsToJScript(GLOBALINFO_ANY); - - $_cat = $spell->getField('typeCat'); - $l = [null, 'A', 'B', 'C']; - $_path[] = $_cat; - - // reconstruct path - switch($_cat) + public function display($override = '') { - case -2: - case 7: - case -13: - $cl = $spell->getField('reqClassMask'); - $i = 1; + if ($this->mode != CACHETYPE_TOOLTIP) + return parent::display($override); - while ($cl > 0) - { - if ($cl & (1 << ($i - 1))) - { - $_path[] = $i; - break; - } - $i++; - } - - if ($_cat == -13) - { - $_path[] = ($spell->getField('cuFlags') & (SPELL_CU_GLYPH_MAJOR | SPELL_CU_GLYPH_MINOR)) >> 6; - break; - } - case 9: - case -3: - case 11: - $_path[] = $spell->getField('skillLines')[0]; - - if ($_cat == 11) - if ($_ = $spell->getField('reqSpellId')) - $_path[] = $_; - - break; - case -11: - foreach (SpellList::$skillLines as $line => $skills) - if (in_array($spell->getField('skillLines')[0], $skills)) - $_path[] = $line; - break; - case -7: // only spells unique in skillLineAbility will always point to the right skillLine :/ - $_ = $spell->getField('cuFlags'); - if ($_ & SPELL_CU_PET_TALENT_TYPE0) - $_path[] = 411; // Ferocity - else if ($_ & SPELL_CU_PET_TALENT_TYPE1) - $_path[] = 409; // Tenacity - else if ($_ & SPELL_CU_PET_TALENT_TYPE2) - $_path[] = 410; // Cunning - } - - // has difficulty versions of itself - $difficulties = DB::Aowow()->selectRow( - 'SELECT normal10 AS "0", - normal25 AS "1", - heroic10 AS "2", - heroic25 AS "3" - FROM ?_spelldifficulty - WHERE normal10 = ?d OR - normal25 = ?d OR - heroic10 = ?d OR - heroic25 = ?d', - $_id, $_id, $_id, $_id - ); - - // returns self or firstRank - $firstRank = DB::Aowow()->selectCell( - 'SELECT IF(s1.rankId <> 1 AND s2.id, s2.id, s1.id) - FROM ?_spell s1 - LEFT JOIN ?_spell s2 - ON s1.SpellFamilyId = s2.SpelLFamilyId AND - s1.SpellFamilyFlags1 = s2.SpelLFamilyFlags1 AND - s1.SpellFamilyFlags2 = s2.SpellFamilyFlags2 AND - s1.SpellFamilyFlags3 = s2.SpellFamilyFlags3 AND - s1.name_loc0 = s2.name_loc0 AND - s2.RankId = 1 - WHERE s1.id = ?d', - $_id - ); - - /***********/ - /* Infobox */ - /***********/ - - $infobox = []; - - if (!in_array($_cat, [-5, -6])) // not mount or vanity pet - { - if ($_ = $spell->getField('talentLevel')) // level - $infobox[] = '[li]'.(in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::$game['reqLevel'], $_) : Lang::$game['level'].Lang::$colon.$_).'[/li]'; - else if ($_ = $spell->getField('spellLevel')) - $infobox[] = '[li]'.(in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::$game['reqLevel'], $_) : Lang::$game['level'].Lang::$colon.$_).'[/li]'; - } - - // races - if ($_ = Lang::getRaceString($spell->getField('reqRaceMask'), $__, false, $n)) - { - if ($_ != Lang::$game['ra'][0]) // omit: "both" + if (!$this->loadCache($tt)) { - $t = $n == 1 ? Lang::$game['race'] : Lang::$game['races']; - $infobox[] = '[li]'.Util::ucFirst($t).Lang::$colon.$_.'[/li]'; - } - } - - // classes - if ($_ = Lang::getClassString($spell->getField('reqClassMask'), false, $n)) - { - $t = $n == 1 ? Lang::$game['class'] : Lang::$game['classes']; - $infobox[] = '[li]'.Util::ucFirst($t).Lang::$colon.$_.'[/li]'; - } - - if ($_ = $spell->getField('spellFocusObject')) // spellFocus - { - $bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellFocusObject WHERE id = ?d', $_); - $focus = new GameObjectList(array(['spellFocusId', $_], 1)); - $infobox[] = '[li]'.Lang::$game['requires2'].' '.($focus->error ? Util::localizedString($bar, 'name') : '[url=?object='.$focus->id.']'.Util::localizedString($bar, 'name').'[/url]').'[/li]'; - } - - if (in_array($_cat, [9, 11])) // primary & secondary trades - { - // skill - if ($_ = $spell->getField('skillLines')[0]) - { - $rSkill = new SkillList(array(['id', $_])); - if (!$rSkill->error) - { - $rSkill->addGlobalsToJScript(); - - $bar = sprintf(Lang::$game['requires'], '[skill='.$rSkill->id.']'); - if ($_ = $spell->getField('learnedAt')) - $bar .= ' ('.$_.')'; - - $infobox[] = '[li]'.$bar.'[/li]'; - } + $tt = $this->generateTooltip(); + $this->saveCache($tt); } - // specialization - if ($_ = $spell->getField('reqSpellId')) - { - $rSpell = new SpellList(array(['id', $_])); - if (!$rSpell->error) - { - $rSpell->addGlobalsToJScript(); - $infobox[] = '[li]'.Lang::$game['requires2'].' [spell='.$rSpell->id.'][/li]'; - } - } - - // difficulty - if ($_ = $spell->getColorsForCurrent()) - { - $bar = []; - for ($i = 0; $i < 4; $i++) - if ($_[$i]) - $bar[] = '[color=r'.($i + 1).']'.$_[$i].'[/color]'; - - $infobox[] = '[li]'.Lang::$game['difficulty'].Lang::$colon.implode(' ', $bar).'[/li]'; - } + header('Content-type: application/x-javascript; charset=utf-8'); + die($tt); } - // accquisition.. - if ($_ = @$spell->sources[$spell->id]) + public function notFound($typeStr) { - if (array_key_exists(10, $_)) // ..starter spell - $infobox[] = '[li]'.Lang::$spell['starter'].'[/li]'; - else if (array_key_exists(7, $_)) // ..discovery - $infobox[] = '[li]'.Lang::$spell['discovered'].'[/li]'; + if ($this->mode != CACHETYPE_TOOLTIP) + return parent::notFound($typeStr); + + header('Content-type: application/x-javascript; charset=utf-8'); + echo $this->generateTooltip(true); + exit(); } - // training cost - if ($cost = DB::Aowow()->selectCell('SELECT spellcost FROM npc_trainer WHERE spell = ?d', $spell->id)) - $infobox[] = '[li]'.Lang::$spell['trainingCost'].Lang::$colon.'[money='.$cost.'][/li]'; - - // used in mode - foreach ($difficulties as $n => $id) - if ($id == $_id) // "Mode" seems to be multilingual acceptable - $infobox[] = '[li]Mode'.Lang::$colon.Lang::$game['modes'][$n].'[/li]'; - - - /****************/ - /* Main Content */ - /****************/ - - // chain reagents by method of accquisition - $reagentResult = []; - $enhanced = false; - $reagents = $spell->getReagentsForCurrent(); - $appendReagentItem = function(&$reagentResult, $_iId, $_qty, $_mult, $_level, $_path, $alreadyUsed) use (&$appendCreateSpell) + private function appendReagentItem(&$reagentResult, $_iId, $_qty, $_mult, $_level, $_path, $alreadyUsed) { if (in_array($_iId, $alreadyUsed)) return false; @@ -266,7 +1152,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if (!$item) return false; - Util::$pageTemplate->extendGlobalIds(TYPE_ITEM, $item['id']); + $this->extendGlobalIds(TYPE_ITEM, $item['id']); $_level++; @@ -289,18 +1175,16 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) $reagentResult[] = $data; $alreadyUsed[] = $item['id']; - if (!$appendCreateSpell($reagentResult, $item['id'], $data['qty'], $data['level'], $data['path'], $alreadyUsed)) + if (!$this->appendReagentSpell($reagentResult, $item['id'], $data['qty'], $data['level'], $data['path'], $alreadyUsed)) $reagentResult[$idx]['final'] = true; return true; - }; - $appendCreateSpell = function(&$reagentResult, $_iId, $_qty, $_level, $_path, $alreadyUsed) use (&$appendReagentItem) + } + + private function appendReagentSpell(&$reagentResult, $_iId, $_qty, $_level, $_path, $alreadyUsed) { $_level++; - // when results are found executes in <10ms - // when no results are found executes in ~0.35sec - // dafuque?! - // ""solution"": index effect1Id and effect1CreateItemId and pray, that tradeSpells only use the first index >.< + // assume that tradeSpells only use the first index to create items, so this runs somewhat efficiently >.< $spells = DB::Aowow()->select(' SELECT reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8, reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8, @@ -310,7 +1194,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) WHERE (effect1CreateItemId = ?d AND effect1Id = 24)',// OR // (effect2CreateItemId = ?d AND effect2Id = 24) OR // (effect3CreateItemId = ?d AND effect3Id = 24)', - $_iId//, $_iId, $_iId + $_iId //, $_iId, $_iId ); if (!$spells) @@ -322,7 +1206,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if (in_array(-$sId, $alreadyUsed)) continue; - Util::$pageTemplate->extendGlobalIds(TYPE_SPELL, $sId); + $this->extendGlobalIds(TYPE_SPELL, $sId); $data = array( 'type' => TYPE_SPELL, @@ -345,7 +1229,7 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($row['reagent'.$i] <= 0 || $row['reagentCount'.$i] <= 0) continue; - if ($appendReagentItem($reagentResult, $row['reagent'.$i], $row['reagentCount'.$i], $data['qty'], $data['level'], $data['path'], $_aU)) + if ($this->appendReagentItem($reagentResult, $row['reagent'.$i], $row['reagentCount'.$i], $data['qty'], $data['level'], $data['path'], $_aU)) { $hasUnusedReagents = true; $didAppendSomething = true; @@ -357,98 +1241,160 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) } return $didAppendSomething; - }; - - if ($reagents) - { - - foreach ($spell->relItems->iterate() as $iId => $__) - { - if (!in_array($iId, array_keys($reagents))) - continue; - - $data = array( - 'type' => TYPE_ITEM, - 'typeId' => $iId, - 'typeStr' => Util::$typeStrings[TYPE_ITEM], - 'quality' => $spell->relItems->getField('quality'), - 'name' => $spell->relItems->getField('name', true), - 'icon' => $spell->relItems->getField('iconString'), - 'qty' => $reagents[$iId][1], - 'path' => TYPE_ITEM.'-'.$iId, // id of the html-element - 'level' => 0 // depths in array, used for indentation - ); - - $idx = count($reagentResult); - $reagentResult[] = $data; - - // start with self and current original item in usedEntries (spell < 0; item > 0) - if ($appendCreateSpell($reagentResult, $iId, $data['qty'], 0, $data['path'], [-$_id, $iId])) - $enhanced = true; - else - $reagentResult[$idx]['final'] = true; - } } - // increment all indizes (by prepending null and removing it again) - array_unshift($reagentResult, null); - unset($reagentResult[0]); - - // menuId 1: Spell g_initPath() - // tabId 0: Database g_initHeader() - $pageData = array( - 'page' => array( - 'title' => $spell->getField('name', true).' - '.Util::ucFirst(Lang::$game['spell']), - 'path' => json_encode($_path, JSON_NUMERIC_CHECK), - 'tab' => 0, - 'type' => TYPE_SPELL, - 'typeId' => $_id, - 'reqJS' => [STATIC_URL.'/js/swfobject.js'], - 'redButtons' => array( - BUTTON_LINKS => ['color' => 'ff71d5ff', 'linkId' => Util::$typeStrings[TYPE_SPELL].':'.$_id], - BUTTON_VIEW3D => false, - BUTTON_WOWHEAD => true - ), - 'infobox' => $infobox, - 'scaling' => '', - 'powerCost' => $spell->createPowerCostForCurrent(), - 'castTime' => $spell->createCastTimeForCurrent(false, false), - 'tools' => $spell->getToolsForCurrent(), - 'reagents' => [$enhanced, $reagentResult], - 'name' => $spell->getField('name', true), - 'headIcons' => [$spell->getField('iconString'), $spell->getField('stackAmount')], - 'level' => $spell->getField('spellLevel'), - 'rangeName' => $spell->getField('rangeText', true), - 'range' => $spell->getField('rangeMaxHostile'), - 'gcd' => Util::formatTime($spell->getField('startRecoveryTime')), - 'gcdCat' => null, // todo (low): nyi; find out how this works [n/a; normal; ..] - 'school' => User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Util::asHex($spell->getField('schoolMask')), Lang::getMagicSchools($spell->getField('schoolMask'))) : Lang::getMagicSchools($spell->getField('schoolMask')), - 'dispel' => Lang::$game['dt'][$spell->getField('dispelType')], - 'mechanic' => Lang::$game['me'][$spell->getField('mechanic')], - ), - 'relTabs' => [] - ); - - if ($spell->getField('attributes2') & 0x80000) - $pageData['page']['stances'] = Lang::getStances($spell->getField('stanceMask')); - - if (($_ = $spell->getField('recoveryTime')) && $_ > 0) - $pageData['page']['cooldown'] = Util::formatTime($_); - - if (($_ = $spell->getField('duration')) && $_ > 0) - $pageData['page']['duration'] = Util::formatTime($_); - - // minRange exists.. prepend - if ($_ = $spell->getField('rangeMinHostile')) - $pageData['page']['range'] = $_.' - '.$pageData['page']['range']; - - // parse itemClass & itemSubClassMask - $class = $spell->getField('equippedItemClass'); - $subClass = $spell->getField('equippedItemSubClassMask'); - $invType = $spell->getField('equippedItemInventoryTypeMask'); - - if ($class > 0 && $subClass > 0) + private function createReagentList() { + $reagentResult = []; + $enhanced = false; + + if ($reagents = $this->subject->getReagentsForCurrent()) + { + foreach ($this->subject->relItems->iterate() as $iId => $__) + { + if (!in_array($iId, array_keys($reagents))) + continue; + + $data = array( + 'type' => TYPE_ITEM, + 'typeId' => $iId, + 'typeStr' => Util::$typeStrings[TYPE_ITEM], + 'quality' => $this->subject->relItems->getField('quality'), + 'name' => $this->subject->relItems->getField('name', true), + 'icon' => $this->subject->relItems->getField('iconString'), + 'qty' => $reagents[$iId][1], + 'path' => TYPE_ITEM.'-'.$iId, // id of the html-element + 'level' => 0 // depths in array, used for indentation + ); + + $idx = count($reagentResult); + $reagentResult[] = $data; + + // start with self and current original item in usedEntries (spell < 0; item > 0) + if ($this->appendReagentSpell($reagentResult, $iId, $data['qty'], 0, $data['path'], [-$this->typeId, $iId])) + $enhanced = true; + else + $reagentResult[$idx]['final'] = true; + } + } + + // increment all indizes (by prepending null and removing it again) + array_unshift($reagentResult, null); + unset($reagentResult[0]); + + return [$enhanced, $reagentResult]; + } + + private function createScalingData() // calculation mostly like seen in TC + { + $scaling = array_merge( + array( + 'directSP' => -1, + 'dotSP' => -1, + 'directAP' => 0, + 'dotAP' => 0 + ), + (array)DB::Aowow()->selectRow('SELECT direct_bonus AS directSP, dot_bonus AS dotSP, ap_bonus AS directAP, ap_dot_bonus AS dotAP FROM spell_bonus_data WHERE entry = ?d', $this->firstRank) + ); + + if (!$this->subject->isDamagingSpell() && !$this->subject->isHealingSpell()) + return $scaling; + + foreach ($scaling as $k => $v) + { + // only calculate for class/pet spells + if ($v != -1 || !in_array($this->subject->getField('typeCat'), [-2, -3, -7, 7])) + continue; + + + // no known calculation for physical abilities + if ($k == 'directAP' || $k == 'dotAP') + continue; + + // dont use spellPower to scale physical Abilities + if ($this->subject->getField('schoolMask') == 0x1 && ($k == 'directSP' || $k == 'dotSP')) + continue; + + $isDOT = false; + $pMask = $this->subject->periodicEffectsMask(); + + if ($k == 'dotSP' || $k == 'dotAP') + { + if ($pMask) + $isDOT = true; + else + continue; + } + else // if all used effects are periodic, dont calculate direct component + { + $bar = true; + for ($i = 1; $i < 4; $i++) + { + if (!$this->subject->getField('effect'.$i.'Id')) + continue; + + if ($pMask & 1 << ($i - 1)) + continue; + + $bar = false; + } + + if ($bar) + continue; + } + + // Damage over Time spells bonus calculation + $dotFactor = 1.0; + if ($isDOT) + { + $dotDuration = $this->subject->getField('duration'); + // 200% limit + if ($dotDuration > 0) + { + if ($dotDuration > 30000) + $dotDuration = 30000; + if (!$this->subject->isChanneledSpell()) + $dotFactor = $dotDuration / 15000; + } + } + + // Distribute Damage over multiple effects, reduce by AoE + $castingTime = $this->subject->getCastingTimeForBonus($isDOT); + + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for ($j = 1; $j < 4; ++$j) + { + // SPELL_EFFECT_HEALTH_LEECH || SPELL_AURA_PERIODIC_LEECH + if ($this->subject->getField('effectId'.$j) == 9 || $this->subject->getField('effect'.$j.'AuraId') == 53) + { + $castingTime /= 2; + break; + } + } + + if ($this->subject->isHealingSpell()) + $castingTime *= 1.88; + + // SPELL_SCHOOL_MASK_NORMAL + if ($this->subject->getField('schoolMask') != 0x1) + $scaling[$k] = ($castingTime / 3500.0) * $dotFactor; + else + $scaling[$k] = 0; // would be 1 ($dotFactor), but we dont want it to be displayed + } + + return $scaling; + } + + private function createRequiredItems() + { + // parse itemClass & itemSubClassMask + $class = $this->subject->getField('equippedItemClass'); + $subClass = $this->subject->getField('equippedItemSubClassMask'); + $invType = $this->subject->getField('equippedItemInventoryTypeMask'); + + if ($class <= 0 || $subClass <= 0) + return; + $title = ['Class: '.$class, 'SubClass: '.Util::asHex($subClass)]; $text = Lang::getRequiredItems($class, $subClass, false); @@ -473,1422 +1419,518 @@ if (!$smarty->loadCache($cacheKeyPage, $pageData)) if ($invType & 1 << $k && $str) $_[] = $str; - $title[] = Lang::$item['slot'].Lang::$colon.Util::asHex($invType); - $text .= ' '.Lang::$spell['_inSlot'].Lang::$colon.implode(', ', $_); + $title[] = Lang::$item['slot'].Lang::$main['colon'].Util::asHex($invType); + $text .= ' '.Lang::$spell['_inSlot'].Lang::$main['colon'].implode(', ', $_); } - $pageData['page']['items'] = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, implode(' | ', $title), $text) : $text; + return [$title, $text]; } - // prepare Tools - foreach ($pageData['page']['tools'] as $k => $tool) + private function createTools() { - if (isset($tool['itemId'])) // Tool - $pageData['page']['tools'][$k]['url'] = '?item='.$tool['itemId']; - else // ToolCat + $tools = $this->subject->getToolsForCurrent(); + + // prepare Tools + foreach ($tools as &$tool) { - $pageData['page']['tools'][$k]['quality'] = ITEM_QUALITY_HEIRLOOM - ITEM_QUALITY_NORMAL; - $pageData['page']['tools'][$k]['url'] = '?items&filter=cr=91;crs='.$tool['id'].';crv=0'; + if (isset($tool['itemId'])) // Tool + $tool['url'] = '?item='.$tool['itemId']; + else // ToolCat + { + $tool['quality'] = ITEM_QUALITY_HEIRLOOM - ITEM_QUALITY_NORMAL; + $tool['url'] = '?items&filter=cr=91;crs='.$tool['id'].';crv=0'; + } } + + return $tools; } - // spell scaling - $scaling = array_merge( - array( - 'directSP' => -1, - 'dotSP' => -1, - 'directAP' => 0, - 'dotAP' => 0 - ), - (array)DB::Aowow()->selectRow('SELECT direct_bonus AS directSP, dot_bonus AS dotSP, ap_bonus AS directAP, ap_dot_bonus AS dotAP FROM spell_bonus_data WHERE entry = ?d', $firstRank) - ); - - foreach ($scaling as $k => $v) + private function createEffects(&$infobox, &$redButtons) { - // only calculate for class/pet spells - if ($v != -1 || !in_array($spell->getField('typeCat'), [-2, -3, -7, 7])) - continue; + // proc data .. maybe use more information..? + $procData = DB::Aowow()->selectRow('SELECT IF(ppmRate > 0, -ppmRate, customChance) AS chance, cooldown FROM world.spell_proc_event WHERE entry = ?d', $this->typeId); + if (empty($procData['chance'])) + $procData['chance'] = $this->subject->getField('procChance'); - if (!$spell->isDamagingSpell() || $spell->isHealingSpell()) + if (!isset($procData['cooldown'])) + $procData['cooldown'] = 0; + + $effects = []; + $spellIdx = array_unique(array_merge($this->subject->canTriggerSpell(), $this->subject->canTeachSpell())); + $itemIdx = $this->subject->canCreateItem(); + + // Iterate through all effects: + for ($i = 1; $i < 4; $i++) { - $scaling[$k] = 0; - continue; - } - - // no known calculation for physical abilities - if ($k == 'directAP' || $k == 'dotAP') - continue; - - // dont use spellPower to scale physical Abilities - if ($spell->getField('schoolMask') == 0x1 && ($k == 'directSP' || $k == 'dotSP')) - continue; - - $isDOT = false; - $pMask = $spell->periodicEffectsMask(); - - if ($k == 'dotSP' || $k == 'dotAP') - { - if ($pMask) - $isDOT = true; - else + if ($this->subject->getField('effect'.$i.'Id') <= 0) continue; - } - else // if all used effects are periodic, dont calculate direct component - { - $bar = true; - for ($i = 1; $i < 4; $i++) + + $effId = (int)$this->subject->getField('effect'.$i.'Id'); + $effMV = (int)$this->subject->getField('effect'.$i.'MiscValue'); + $effBP = (int)$this->subject->getField('effect'.$i.'BasePoints'); + $effDS = (int)$this->subject->getField('effect'.$i.'DieSides'); + $effRPPL = $this->subject->getField('effect'.$i.'RealPointsPerLevel'); + $effAura = (int)$this->subject->getField('effect'.$i.'AuraId'); + $foo = &$effects[]; + + // Icons: + // .. from item + if (in_array($i, $itemIdx)) { - if (!$spell->getField('effect'.$i.'Id')) - continue; + $_ = $this->subject->getField('effect'.$i.'CreateItemId'); + foreach ($this->subject->relItems->iterate() as $itemId => $__) + { + if ($itemId != $_) + continue; - if ($pMask & 1 << ($i - 1)) - continue; + $foo['icon'] = array( + 'id' => $this->subject->relItems->id, + 'name' => $this->subject->relItems->getField('name', true), + 'quality' => $this->subject->relItems->getField('quality'), + 'count' => $effDS + $effBP, + 'icon' => $this->subject->relItems->getField('iconString') + ); - $bar = false; + break; + } + + if ($effDS > 1) + $foo['icon']['count'] = "'".($effBP + 1).'-'.$foo['icon']['count']."'"; } - - if ($bar) - continue; - } - - // Damage over Time spells bonus calculation - $dotFactor = 1.0; - if ($isDOT) - { - $dotDuration = $spell->getField('duration'); - // 200% limit - if ($dotDuration > 0) + // .. from spell + else if (in_array($i, $spellIdx)) { - if ($dotDuration > 30000) - $dotDuration = 30000; - if (!$spell->isChanneledSpell()) - $dotFactor = $dotDuration / 15000; - } - } + $_ = $this->subject->getField('effect'.$i.'TriggerSpell'); + if (!$_) + $_ = $this->subject->getField('effect'.$i.'MiscValue'); - // Distribute Damage over multiple effects, reduce by AoE - $castingTime = $spell->getCastingTimeForBonus($isDOT); - - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for ($j = 1; $j < 4; ++$j) - { - // SPELL_EFFECT_HEALTH_LEECH || SPELL_AURA_PERIODIC_LEECH - if ($spell->getField('effectId'.$j) == 9 || $spell->getField('effect'.$j.'AuraId') == 53) - { - $castingTime /= 2; - break; - } - } - - if ($spell->isHealingSpell()) - $castingTime *= 1.88; - - if ($spell->getField('schoolMask') != 0x1) // SPELL_SCHOOL_MASK_NORMAL - $scaling[$k] = ($castingTime / 3500.0) * $dotFactor; - else - $scaling[$k] = 0; // would be 1 ($dotFactor), but we dont want it to be displayed - } - - foreach ($scaling as $k => $v) - if ($v > 0) - $pageData['page']['scaling'] .= sprintf(Lang::$spell['scaling'][$k], $v * 100).'
'; - - // proc data .. maybe use more information..? - $procData = DB::Aowow()->selectRow('SELECT IF(ppmRate > 0, -ppmRate, customChance) AS chance, cooldown FROM world.spell_proc_event WHERE entry = ?d', $_id); - if (empty($procData['chance'])) - $procData['chance'] = $spell->getField('procChance'); - - if (!isset($procData['cooldown'])) - $procData['cooldown'] = 0; - - // Iterate through all effects: - $pageData['page']['effect'] = []; - - $spellIdx = array_unique(array_merge($spell->canTriggerSpell(), $spell->canTeachSpell())); - $itemIdx = $spell->canCreateItem(); - - for ($i = 1; $i < 4; $i++) - { - if ($spell->getField('effect'.$i.'Id') <= 0) - continue; - - $effId = (int)$spell->getField('effect'.$i.'Id'); - $effMV = (int)$spell->getField('effect'.$i.'MiscValue'); - $effBP = (int)$spell->getField('effect'.$i.'BasePoints'); - $effDS = (int)$spell->getField('effect'.$i.'DieSides'); - $effRPPL = $spell->getField('effect'.$i.'RealPointsPerLevel'); - $effAura = (int)$spell->getField('effect'.$i.'AuraId'); - $foo = &$pageData['page']['effect'][]; - - // Icons: - // .. from item - if (in_array($i, $itemIdx)) - { - $_ = $spell->getField('effect'.$i.'CreateItemId'); - foreach ($spell->relItems->iterate() as $itemId => $__) - { - if ($itemId != $_) - continue; + $trig = new SpellList(array(['s.id', (int)$_])); $foo['icon'] = array( - 'id' => $spell->relItems->id, - 'name' => $spell->relItems->getField('name', true), - 'quality' => $spell->relItems->getField('quality'), - 'count' => $effDS + $effBP, - 'icon' => $spell->relItems->getField('iconString') - ); - } - - if ($effDS > 1) - $foo['icon']['count'] = "'".($effBP + 1).'-'.$foo['icon']['count']."'"; - } - // .. from spell - else if (in_array($i, $spellIdx)) - { - $_ = $spell->getField('effect'.$i.'TriggerSpell'); - if (!$_) - $_ = $spell->getField('effect'.$i.'MiscValue'); - - $trig = new SpellList(array(['s.id', (int)$_])); - - $foo['icon'] = array( - 'id' => $_, - 'name' => $trig->error ? Util::ucFirst(Lang::$game['spell']).' #'.$_ : $trig->getField('name', true), - 'count' => 0 - ); - - $trig->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - - // Effect Name - $foo['name'] = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, 'EffectId: '.$effId, Util::$spellEffectStrings[$effId]) : Util::$spellEffectStrings[$effId]; - - if ($spell->getField('effect'.$i.'RadiusMax') > 0) - $foo['radius'] = $spell->getField('effect'.$i.'RadiusMax'); - - if (!($itemIdx && $spell->relItems && !$spell->relItems->error) && (!in_array($i, $spellIdx) || in_array($effAura, [225, 227]))) - $foo['value'] = ($effDS && $effDS != 1 ? ($effBP + 1).Lang::$game['valueDelim'] : null).($effBP + $effDS); - - if ($effRPPL != 0) - $foo['value'] = (isset($foo['value']) ? $foo['value'] : '0').sprintf(Lang::$spell['costPerLevel'], $effRPPL); - - if ($spell->getField('effect'.$i.'Periode') > 0) - $foo['interval'] = Util::formatTime($spell->getField('effect'.$i.'Periode')); - - if ($_ = $spell->getField('effect'.$i.'Mechanic')) - $foo['mechanic'] = Lang::$game['me'][$_]; - - if ($procData['chance'] && $procData['chance'] < 100) - if (in_array($i, $spell->canTriggerSpell())) - $foo['procData'] = array( - $procData['chance'], - $procData['cooldown'] ? Util::formatTime($procData['cooldown'] * 1000, true) : null + 'id' => $_, + 'name' => $trig->error ? Util::ucFirst(Lang::$game['spell']).' #'.$_ : $trig->getField('name', true), + 'count' => 0 ); - // parse masks and indizes - switch ($effId) - { - case 8: // Power Drain - case 30: // Energize - case 137: // Energize Pct - $_ = @Lang::$spell['powerTypes'][$effMV]; - if ($_ && User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else if (!$_) - $_ = $effMV; - - if ($effMV == POWER_RAGE || $effMV == POWER_RUNIC_POWER) - $foo['value'] = ($effDS && $effDS != 1 ? (($effBP + 1) / 10).Lang::$game['valueDelim'] : null).(($effBP + $effDS) / 10); - - $foo['name'] .= ' ('.$_.')'; - break; - case 16: // QuestComplete - if ($_ = QuestList::getName($effMV)) - $foo['name'] .= Lang::$colon.'('.$_.')'; - else - $foo['name'] .= Lang::$colon.Util::ucFirst(Lang::$game['quest']).' #'.$effMV;; - break; - case 28: // Summon - case 90: // Kill Credit - $_ = Lang::$game['npc'].' #'.$effMV; - if ($summon = $spell->getModelInfo($_id)) - { - $_ = '('.$summon['displayName'].')'; - $pageData['page']['redButtons'][BUTTON_VIEW3D] = ['type' => TYPE_NPC, 'displayId' => $summon['displayId']]; - } - - $foo['name'] .= Lang::$colon.$_; - break; - case 33: // Open Lock - $_ = @Lang::$spell['lockType'][$effMV]; - if ($_ && User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else if (!$_) - $_ = $effMV; - - $foo['name'] .= ' ('.$_.')'; - break; - case 53: // Enchant Item Perm - case 54: // Enchant Item Temp - case 156: // Enchant Item Prismatic - if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemEnchantment WHERE id = ?d', $effMV)) - $foo['name'] .= ' '.Util::localizedString($_, 'text').' ('.$effMV.')'; - else - $foo['name'] .= ' #'.$effMV; - break; - case 38: // Dispel [miscValue => Types] - case 126: // Steal Aura - $_ = @Lang::$game['dt'][$effMV]; - if ($_ && User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else if (!$_) - $_ = $effMV; - - $foo['name'] .= ' ('.$_.')'; - break; - case 39: // Learn Language - $_ = @Lang::$game['languages'][$effMV]; - if ($_ && User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else if (!$_) - $_ = $effMV; - - $foo['name'] .= ' ('.$_.')'; - break; - case 50: // Trans Door - case 76: // Summon Object (Wild) - // case 86: // Activate Object - case 104: // Summon Object (slot 1) - case 105: // Summon Object (slot 2) - case 106: // Summon Object (slot 3) - case 107: // Summon Object (slot 4) - $_ = Util::ucFirst(Lang::$game['gameObject']).' #'.$effMV; - if ($summon = $spell->getModelInfo($_id)) - { - $_ = '('.$summon['displayName'].')'; - $pageData['page']['redButtons'][BUTTON_VIEW3D] = ['type' => TYPE_OBJECT, 'displayId' => $summon['displayId']]; - } - - - $foo['name'] .= Lang::$colon.$_; - break; - case 74: // Apply Glyph - if ($_ = DB::Aowow()->selectCell('SELECT spellId FROM ?_glyphProperties WHERE id = ?d', $effMV)) - { - if ($n = SpellList::getName($_)) - $foo['name'] .= Lang::$colon.'('.$n.')'; - else - $foo['name'] .= Lang::$colon.Util::ucFirst(Lang::$game['spell']).' #'.$effMV; - } - else - $foo['name'] .= ' #'.$effMV;; - break; - case 95: // Skinning - switch ($effMV) - { - case 0: $_ = Lang::$game['ct'][1].', '.Lang::$game['ct'][2]; break; // Beast, Dragonkin - case 1: - case 2: $_ = Lang::$game['ct'][4]; break; // Elemental (nature based, earth based) - case 3: $_ = Lang::$game['ct'][9]; break; // Mechanic - default; $_ = ''; - } - if (User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else - $_ = $effMV; - - $foo['name'] .= ' ('.$_.')'; - break; - case 108: // Dispel Mechanic - $_ = @Lang::$game['me'][$effMV]; - if ($_ && User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else if (!$_) - $_ = $effMV; - - $foo['name'] .= ' ('.$_.')'; - break; - case 118: // Require Skill - if ($_ = SkillList::getName($effMV)) - $foo['name'] .= Lang::$colon.'('.$_.')'; - else - $foo['name'] .= Lang::$colon.Util::ucFirst(Lang::$game['skill']).' #'.$effMV;; - break; - case 146: // Activate Rune - $_ = @Lang::$spell['powerRunes'][$effMV]; - if ($_ && User::isInGroup(U_GROUP_STAFF)) - $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_); - else if (!$_) - $_ = $effMV; - - $foo['name'] .= ' ('.$_.')'; - break; - case 123: // Send Taxi - effMV is taxiPathId. We only use paths for flightmasters for now, so spell-triggered paths are not in the table - default: - { - if (($effMV || $effId == 97) && $effId != 155) - $foo['name'] .= ' ('.$effMV.')'; + $this->extendGlobalData($trig->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); } - // Aura - case 6: // Simple - case 27: // AA Persistent - case 35: // AA Party - case 65: // AA Raid - case 119: // AA Pet - case 128: // AA Friend - case 129: // AA Enemy - case 143: // AA Owner - { - if ($effAura > 0 && isset(Util::$spellAuraStrings[$effAura])) - { - $foo['name'] .= User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, 'AuraId: '.$effAura, Lang::$colon.Util::$spellAuraStrings[$effAura]) : Lang::$colon.Util::$spellAuraStrings[$effAura]; - $bar = $effMV; - switch ($effAura) + // Effect Name + $foo['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'EffectId: '.$effId, Util::$spellEffectStrings[$effId]) : Util::$spellEffectStrings[$effId]; + + if ($this->subject->getField('effect'.$i.'RadiusMax') > 0) + $foo['radius'] = $this->subject->getField('effect'.$i.'RadiusMax'); + + if (!($itemIdx && $this->subject->relItems && !$this->subject->relItems->error) && (!in_array($i, $spellIdx) || in_array($effAura, [225, 227]))) + $foo['value'] = ($effDS && $effDS != 1 ? ($effBP + 1).Lang::$game['valueDelim'] : null).($effBP + $effDS); + + if ($effRPPL != 0) + $foo['value'] = (isset($foo['value']) ? $foo['value'] : '0').sprintf(Lang::$spell['costPerLevel'], $effRPPL); + + if ($this->subject->getField('effect'.$i.'Periode') > 0) + $foo['interval'] = Util::formatTime($this->subject->getField('effect'.$i.'Periode')); + + if ($_ = $this->subject->getField('effect'.$i.'Mechanic')) + $foo['mechanic'] = Lang::$game['me'][$_]; + + if ($procData['chance'] && $procData['chance'] < 100) + if (in_array($i, $this->subject->canTriggerSpell())) + $foo['procData'] = array( + $procData['chance'], + $procData['cooldown'] ? Util::formatTime($procData['cooldown'] * 1000, true) : null + ); + + // parse masks and indizes + switch ($effId) + { + case 8: // Power Drain + case 30: // Energize + case 137: // Energize Pct + $_ = @Lang::$spell['powerTypes'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else if (!$_) + $_ = $effMV; + + if ($effMV == POWER_RAGE || $effMV == POWER_RUNIC_POWER) + $foo['value'] = ($effDS && $effDS != 1 ? (($effBP + 1) / 10).Lang::$game['valueDelim'] : null).(($effBP + $effDS) / 10); + + $foo['name'] .= ' ('.$_.')'; + break; + case 16: // QuestComplete + if ($_ = QuestList::getName($effMV)) + $foo['name'] .= Lang::$main['colon'].'('.$_.')'; + else + $foo['name'] .= Lang::$main['colon'].Util::ucFirst(Lang::$game['quest']).' #'.$effMV;; + break; + case 28: // Summon + case 90: // Kill Credit + $_ = Lang::$game['npc'].' #'.$effMV; + if ($summon = $this->subject->getModelInfo($this->typeId)) { - case 17: // Mod Stealth Detection - if ($_ = @Lang::$spell['stealthType'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 19: // Mod Invisibility Detection - if ($_ = @Lang::$spell['invisibilityType'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 24: // Periodic Energize - case 21: // Obsolete Mod Power - case 35: // Mod Increase Power - case 85: // Mod Power Regeneration - case 110: // Mod Power Regeneration Pct - if ($_ = @Lang::$spell['powerTypes'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 29: // Mod Stat - case 80: // Mod Stat % - case 137: // Mod Total Stat % - case 175: // Mod Spell Healing Of Stat Percent - case 212: // Mod Ranged Attack Power Of Stat Percent - case 219: // Mod Mana Regeneration from Stat - case 268: // Mod Attack Power Of Stat Percent - $mask = $effMV == -1 ? 0x1F : 1 << $effMV; - $_ = []; - for ($j = 0; $j < 5; $j++) - if ($mask & (1 << $j)) - $_[] = Lang::$game['stats'][$j]; - - if ($_ = implode(', ', $_)); - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 36: // Shapeshift - if ($st = $spell->getModelInfo($_id)) - { - $pageData['page']['redButtons'][BUTTON_VIEW3D] = array( - 'type' => TYPE_NPC, - 'displayId' => $st['displayId'][1] ? $st['displayId'][rand(0, 1)] : $st['displayId'][0] - ); - - if ($st['creatureType'] > 0) - $pageData['page']['infobox'][] = '[li]'.Lang::$game['type'].Lang::$colon.Lang::$game['ct'][$st['creatureType']].'[/li]'; - - if ($_ = $st['displayName']) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - } - break; - case 37: // Effect immunity - if ($_ = @Util::$spellEffectStrings[$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 38: // Aura immunity - if ($_ = @Util::$spellAuraStrings[$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 41: // Dispel Immunity - case 178: // Mod Debuff Resistance - case 245: // Mod Aura Duration By Dispel - if ($_ = @Lang::$game['dt'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 44: // Track Creature - if ($_ = @Lang::$game['ct'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 45: // Track Resource - if ($_ = @Lang::$spell['lockType'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 75: // Language - if ($_ = @Lang::$game['languages'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 77: // Mechanic Immunity - case 117: // Mod Mechanic Resistance - case 232: // Mod Mechanic Duration - case 234: // Mod Mechanic Duration (no stack) - case 255: // Mod Mechanic Damage Taken Pct - case 276: // Mod Mechanic Damage Done Percent - if ($_ = @Lang::$game['me'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - - break; - case 147: // Mechanic Immunity Mask - $_ = []; - foreach (Lang::$game['me'] as $k => $str) - if ($effMV & (1 << $k - 1)) - $_[] = $str; - - if ($_ = implode(', ', $_)) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - - break; - case 10: // Mod Threat - case 13: // Mod Damage Done - case 14: // Mod Damage Taken - case 22: // Mod Resistance - case 39: // School Immunity - case 40: // Damage Immunity - case 57: // Mod Spell Crit Chance - case 69: // School Absorb - case 71: // Mod Spell Crit Chance School - case 72: // Mod Power Cost School Percent - case 73: // Mod Power Cost School Flat - case 74: // Reflect Spell School - case 79: // Mod Damage Done Pct - case 81: // Split Damage Pct - case 83: // Mod Base Resistance - case 87: // Mod Damage Taken Pct - case 97: // Mana Shield - case 101: // Mod Resistance Pct - case 115: // Mod Healing Taken - case 118: // Mod Healing Taken Pct - case 123: // Mod Target Resistance - case 135: // Mod Healing Done - case 136: // Mod Healing Done Pct - case 142: // Mod Base Resistance Pct - case 143: // Mod Resistance Exclusive - case 149: // Reduce Pushback - case 163: // Mod Crit Damage Bonus - case 174: // Mod Spell Damage Of Stat Percent - case 182: // Mod Resistance Of Stat Percent - case 186: // Mod Attacker Spell Hit Chance - case 194: // Mod Target Absorb School - case 195: // Mod Target Ability Absorb School - case 199: // Mod Increases Spell Percent to Hit - case 229: // Mod AoE Damage Avoidance - case 271: // Mod Damage Percent Taken Form Caster - case 310: // Mod Creature AoE Damage Avoidance - if ($_ = Lang::getMagicSchools($effMV)) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - - break; - case 30: // Mod Skill - case 98: // Mod Skill Value - if ($_ = SkillList::getName($effMV)) - $bar = ' ('.SkillList::getName($effMV).')'; - else - $bar = Lang::$colon.Util::ucFirst(Lang::$game['skill']).' #'.$effMV;; - - break; - case 107: // Flat Modifier - case 108: // Pct Modifier - if ($_ = @Lang::$spell['spellModOp'][$effMV]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$effMV, $_) : $_; - - break; - case 189: // Mod Rating - case 220: // Combat Rating From Stat - $_ = []; - foreach (Lang::$spell['combatRating'] as $k => $str) - if ((1 << $k) & $effMV) - $_[] = $str; - - if ($_ = implode(', ', $_)) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - - break; - case 168: // Mod Damage Done Versus - case 59: // Mod Damage Done Versus Creature - $_ = []; - foreach (Lang::$game['ct'] as $k => $str) - if ($effMV & (1 << $k - 1)) - $_[] = $str; - - if ($_ = implode(', ', $_)) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.Util::asHex($effMV), $_) : $_; - - break; - case 249: // Convert Rune - $x = $spell->getField('effect'.$i.'MiscValueB'); - if ($_ = @Lang::$spell['powerRunes'][$x]) - $bar = User::isInGroup(U_GROUP_STAFF) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$colon.$x, $_) : $_; - - break; - case 78: // Mounted - case 56: // Transform - { - if ($transform = $spell->getModelInfo($_id)) - { - $pageData['page']['redButtons'][BUTTON_VIEW3D] = ['type' => TYPE_NPC, 'displayId' => $transform['displayId']]; - $bar = ' ('.$transform['displayName'].')'; - } - else - $bar = Lang::$colon.Lang::$game['npc'].' #'.$effMV;; - - break; - } - case 139: // Force Reaction - { - $bar = ' ('.FactionList::getName($effMV).')'; - $foo['value'] = sprintf(Util::$dfnString, $foo['value'], Lang::$game['rep'][$foo['value']]); - } - } - $foo['name'] .= strstr($bar, 'href') || strstr($bar, '#') ? $bar : ($bar ? ' ('.$bar.')' : null); - - if (in_array($effAura, [174, 220, 182])) - $foo['name'] .= ' ['.sprintf(Util::$dfnString, Lang::$game['stats'][$spell->getField('effect'.$i.'MiscValueB')], $spell->getField('effect'.$i.'MiscValueB')).']'; - else if ($spell->getField('effect'.$i.'MiscValueB') > 0) - $foo['name'] .= ' ['.$spell->getField('effect'.$i.'MiscValueB').']'; - - } - else if ($effAura > 0) - $foo['name'] .= Lang::$colon.'Unknown Aura ('.$effAura.')'; - - break; - } - } - - // cases where we dont want 'Value' to be displayed - if (in_array($effAura, [11, 12, 36, 77]) || in_array($effId, []) || empty($foo['value'])) - unset($foo['value']); - } - - $pageData['page']['infobox'] = !empty($pageData['page']['infobox']) ? '[ul]'.implode('', $pageData['page']['infobox']).'[/ul]' : null; - - unset($foo); // clear reference - - // factionchange-equivalent -/* nyi - $pendant = DB::Aowow()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_items WHERE alliance_id = ?d OR horde_id = ?d', $_id, $_id, $_id); - if ($pendant) - { - $altiSpell = new SpellList(array(['id', abs($pendant)])); - if (!$altSpell->error) - { - $pageData['page']['transfer'] = array( - 'id' => $altItem->id, - 'icon' => $altItem->getField('iconString'), - 'name' => $altItem->getField('name', true), - 'facInt' => $pendant > 0 ? 'alliance' : 'horde', - 'facName' => $pendant > 0 ? Lang::$game['si'][1] : Lang::$game['si'][2] - ); - ) - } -*/ - - /**************/ - /* Extra Tabs */ - /**************/ - - // tab: modifies $this - $sub = ['OR']; - $conditions = [ - ['s.typeCat', [0, -9 /*, -8*/], '!'], // uncategorized (0), GM (-9), NPC-Spell (-8); NPC includes totems, lightwell and others :/ - ['s.spellFamilyId', $spell->getField('spellFamilyId')], - &$sub - ]; - - for ($i = 1; $i < 4; $i++) - { - // Flat Mods (107), Pct Mods (108), No Reagent Use (256) .. include dummy..? (4) - if (!in_array($spell->getField('effect'.$i.'AuraId'), [107, 108, 256 /*, 4*/])) - continue; - - $m1 = $spell->getField('effect1SpellClassMask'.$l[$i]); - $m2 = $spell->getField('effect2SpellClassMask'.$l[$i]); - $m3 = $spell->getField('effect3SpellClassMask'.$l[$i]); - - if (!$m1 && !$m2 && !$m3) - continue; - - $sub[] = ['s.spellFamilyFlags1', $m1, '&']; - $sub[] = ['s.spellFamilyFlags2', $m2, '&']; - $sub[] = ['s.spellFamilyFlags3', $m3, '&']; - } - - if (count($sub) > 1) - { - $modSpells = new SpellList($conditions); - - if (!$modSpells->error) - { - - if (!$modSpells->hasSetFields(['skillLines'])) - $msH = "$['skill']"; - - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $modSpells->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'modifies', - 'name' => '$LANG.tab_modifies', - 'visibleCols' => "$['level']", - 'hiddenCols' => isset($msH) ? $msH : null - ] - ); - - $modSpells->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - } - - // tab: modified by $this - $sub = ['OR']; - $conditions = [ - ['s.spellFamilyId', $spell->getField('spellFamilyId')], - &$sub - ]; - - for ($i = 1; $i < 4; $i++) - { - $m1 = $spell->getField('spellFamilyFlags1'); - $m2 = $spell->getField('spellFamilyFlags2'); - $m3 = $spell->getField('spellFamilyFlags3'); - - if (!$m1 && !$m2 && !$m3) - continue; - - $sub[] = array( - 'AND', - ['s.effect'.$i.'AuraId', [107, 108, 256 /*, 4*/]], - [ - 'OR', - ['s.effect1SpellClassMask'.$l[$i], $m1, '&'], - ['s.effect2SpellClassMask'.$l[$i], $m2, '&'], - ['s.effect3SpellClassMask'.$l[$i], $m3, '&'] - ] - ); - } - - if (count($sub) > 1) - { - $modsSpell = new SpellList($conditions); - if (!$modsSpell->error) - { - if (!$modsSpell->hasSetFields(['skillLines'])) - $mbH = "$['skill']"; - - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $modsSpell->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'modified-by', - 'name' => '$LANG.tab_modifiedby', - 'visibleCols' => "$['level']", - 'hiddenCols' => isset($mbH) ? $mbH : null - ] - ); - - $modsSpell->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - } - - // tab: see also - $conditions = array( - ['s.schoolMask', $spell->getField('schoolMask')], - ['s.effect1Id', $spell->getField('effect1Id')], - ['s.effect2Id', $spell->getField('effect2Id')], - ['s.effect3Id', $spell->getField('effect3Id')], - ['s.id', $spell->id, '!'], - ['s.name_loc'.User::$localeId, $spell->getField('name', true)] - ); - - $saSpells = new SpellList($conditions); - if (!$saSpells->error) - { - $data = $saSpells->getListviewData(); - if ($difficulties) // needs a way to distinguish between dungeon and raid :x; creature using this -> map -> areaType - { - $saE = '$[Listview.extraCols.mode]'; - - foreach ($data as $id => $dat) - { - $data[$id]['modes'] = ['mode' => 0]; - - if ($difficulties[0] == $id) // b0001000 - { - if (!$difficulties[2] && !$difficulties[3]) - $data[$id]['modes']['mode'] |= 0x2; - else - $data[$id]['modes']['mode'] |= 0x8; - } - - if ($difficulties[1] == $id) // b0010000 - { - if (!$difficulties[2] && !$difficulties[3]) - $data[$id]['modes']['mode'] |= 0x1; - else - $data[$id]['modes']['mode'] |= 0x10; - } - - if ($difficulties[2] == $id) // b0100000 - $data[$id]['modes']['mode'] |= 0x20; - - if ($difficulties[3] == $id) // b1000000 - $data[$id]['modes']['mode'] |= 0x40; - } - } - - if (!$saSpells->hasSetFields(['skillLines'])) - $saH = "$['skill']"; - - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $data, - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'see-also', - 'name' => '$LANG.tab_seealso', - 'visibleCols' => "$['level']", - 'extraCols' => isset($saE) ? $saE : null, - 'hiddenCols' => isset($saH) ? $saH : null - ] - ); - - $saSpells->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - - // tab: used by - itemset - $conditions = array( - 'OR', - ['spell1', $spell->id], ['spell2', $spell->id], ['spell3', $spell->id], ['spell4', $spell->id], - ['spell5', $spell->id], ['spell6', $spell->id], ['spell7', $spell->id], ['spell8', $spell->id] - ); - - $ubSets = new ItemsetList($conditions); - if (!$ubSets->error) - { - $pageData['relTabs'][] = array( - 'file' => 'itemset', - 'data' => $ubSets->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'used-by-itemset', - 'name' => '$LANG.tab_usedby' - ] - ); - - $ubSets->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - - // tab: used by - item - $conditions = array( - 'OR', // 6: learn spell - ['AND', ['spellTrigger1', 6, '!'], ['spellId1', $spell->id]], - ['AND', ['spellTrigger2', 6, '!'], ['spellId2', $spell->id]], - ['AND', ['spellTrigger3', 6, '!'], ['spellId3', $spell->id]], - ['AND', ['spellTrigger4', 6, '!'], ['spellId4', $spell->id]], - ['AND', ['spellTrigger5', 6, '!'], ['spellId5', $spell->id]] - ); - - $ubItems = new ItemList($conditions); - if (!$ubItems->error) - { - $pageData['relTabs'][] = array( - 'file' => 'item', - 'data' => $ubItems->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'used-by-item', - 'name' => '$LANG.tab_usedby' - ] - ); - - $ubItems->addGlobalsToJScript(GLOBALINFO_SELF); - } - - // tab: used by - object - $conditions = array( - 'OR', - ['onUseSpell', $spell->id], ['onSuccessSpell', $spell->id], - ['auraSpell', $spell->id], ['triggeredSpell', $spell->id] - ); - - $ubObjects = new GameObjectList($conditions); - if (!$ubObjects->error) - { - $pageData['relTabs'][] = array( - 'file' => 'object', - 'data' => $ubObjects->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'used-by-object', - 'name' => '$LANG.tab_usedby' - ] - ); - - $ubObjects->addGlobalsToJScript(); - } - - // tab: criteria of - $conditions = array( - ['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, - ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL] - ], - ['ac.value1', $_id] - ); - $coAchievemnts = new AchievementList($conditions); - if (!$coAchievemnts->error) - { - $pageData['relTabs'][] = array( - 'file' => 'achievement', - 'data' => $coAchievemnts->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'criteria-of', - 'name' => '$LANG.tab_criteriaof' - ] - ); - - $coAchievemnts->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - - // tab: contains - // spell_loot_template & skill_extra_item_template - $extraItem = DB::Aowow()->selectRow('SELECT * FROM skill_extra_item_template WHERE spellid = ?d', $spell->id); - $spellLoot = Util::handleLoot(LOOT_SPELL, $spell->id, User::isInGroup(U_GROUP_STAFF), $extraCols); - - if ($extraItem || $spellLoot) - { - $extraCols[] = 'Listview.extraCols.percent'; - $lv = $spellLoot; - - if ($extraItem && $spell->canCreateItem()) - { - $foo = $spell->relItems->getListviewData(); - - for ($i = 1; $i < 4; $i++) - { - if (($bar = $spell->getField('effect'.$i.'CreateItemId')) && isset($foo[$bar])) - { - $lv[$bar] = $foo[$bar]; - $lv[$bar]['percent'] = $extraItem['additionalCreateChance']; - $lv[$bar]['condition'][] = ['type' => TYPE_SPELL, 'typeId' => $extraItem['requiredSpecialization'], 'status' => 2]; - $smarty->extendGlobalIds(TYPE_SPELL, $extraItem['requiredSpecialization']); - - $extraCols[] = 'Listview.extraCols.condition'; - if ($max = $extraItem['additionalMaxNum']) - { - $lv[$bar]['mincount'] = 1; - $lv[$bar]['maxcount'] = $max; + $_ = '('.$summon['displayName'].')'; + $redButtons[BUTTON_VIEW3D] = ['type' => TYPE_NPC, 'displayId' => $summon['displayId']]; } - break; // skill_extra_item_template can only contain 1 item - } - } - } + $foo['name'] .= Lang::$main['colon'].$_; + break; + case 33: // Open Lock + $_ = @Lang::$spell['lockType'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else if (!$_) + $_ = $effMV; - $pageData['relTabs'][] = array( - 'file' => 'item', - 'data' => $lv, - 'params' => [ - 'tabs' => '$tabsRelated', - 'name' => '$LANG.tab_contains', - 'id' => 'contains', - 'hiddenCols' => "$['side', 'slot', 'source', 'reqlevel']", - 'extraCols' => "$[".implode(', ', $extraCols)."]" - ] - ); - } + $foo['name'] .= ' ('.$_.')'; + break; + case 53: // Enchant Item Perm + case 54: // Enchant Item Temp + case 156: // Enchant Item Prismatic + if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemEnchantment WHERE id = ?d', $effMV)) + $foo['name'] .= ' '.Util::localizedString($_, 'text').' ('.$effMV.')'; + else + $foo['name'] .= ' #'.$effMV; + break; + case 38: // Dispel [miscValue => Types] + case 126: // Steal Aura + $_ = @Lang::$game['dt'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else if (!$_) + $_ = $effMV; - // tab: exclusive with - if ($firstRank) { - $linkedSpells = DB::Aowow()->selectCol( // dont look too closely ..... please..? - 'SELECT IF(sg2.spell_id < 0, sg2.id, sg2.spell_id) AS ARRAY_KEY, IF(sg2.spell_id < 0, sg2.spell_id, sr.stack_rule) - FROM spell_group sg1 - JOIN spell_group sg2 - ON (sg1.id = sg2.id OR sg1.id = -sg2.spell_id) AND sg1.spell_id != sg2.spell_id - LEFT JOIN spell_group_stack_rules sr - ON sg1.id = sr.group_id - WHERE sg1.spell_id = ?d', - $firstRank - ); + $foo['name'] .= ' ('.$_.')'; + break; + case 39: // Learn Language + $_ = @Lang::$game['languages'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else if (!$_) + $_ = $effMV; - if ($linkedSpells) - { - $extraSpells = []; - foreach ($linkedSpells as $k => $v) - { - if ($v > 0) - continue; + $foo['name'] .= ' ('.$_.')'; + break; + case 50: // Trans Door + case 76: // Summon Object (Wild) + // case 86: // Activate Object + case 104: // Summon Object (slot 1) + case 105: // Summon Object (slot 2) + case 106: // Summon Object (slot 3) + case 107: // Summon Object (slot 4) + $_ = Util::ucFirst(Lang::$game['gameObject']).' #'.$effMV; + if ($summon = $this->subject->getModelInfo($this->typeId)) + { + $_ = '('.$summon['displayName'].')'; + $redButtons[BUTTON_VIEW3D] = ['type' => TYPE_OBJECT, 'displayId' => $summon['displayId']]; + } - $extraSpells += DB::Aowow()->selectCol( // recursive case (recursive and regular ids are not mixed in a group) - 'SELECT sg2.spell_id AS ARRAY_KEY, sr.stack_rule - FROM spell_group sg1 - JOIN spell_group sg2 - ON sg2.id = -sg1.spell_id AND sg2.spell_id != ?d - LEFT JOIN spell_group_stack_rules sr - ON sg1.id = sr.group_id - WHERE sg1.id = ?d', - $firstRank, - $k - ); - unset($linkedSpells[$k]); - } + $foo['name'] .= Lang::$main['colon'].$_; + break; + case 74: // Apply Glyph + if ($_ = DB::Aowow()->selectCell('SELECT spellId FROM ?_glyphProperties WHERE id = ?d', $effMV)) + { + if ($n = SpellList::getName($_)) + $foo['name'] .= Lang::$main['colon'].'('.$n.')'; + else + $foo['name'] .= Lang::$main['colon'].Util::ucFirst(Lang::$game['spell']).' #'.$effMV; + } + else + $foo['name'] .= ' #'.$effMV;; + break; + case 95: // Skinning + switch ($effMV) + { + case 0: $_ = Lang::$game['ct'][1].', '.Lang::$game['ct'][2]; break; // Beast, Dragonkin + case 1: + case 2: $_ = Lang::$game['ct'][4]; break; // Elemental (nature based, earth based) + case 3: $_ = Lang::$game['ct'][9]; break; // Mechanic + default; $_ = ''; + } + if (User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else + $_ = $effMV; - $groups = $linkedSpells + $extraSpells; - $stacks = new SpellList(array(['s.id', array_keys($groups)])); + $foo['name'] .= ' ('.$_.')'; + break; + case 108: // Dispel Mechanic + $_ = @Lang::$game['me'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else if (!$_) + $_ = $effMV; - if (!$stacks->error) - { - $data = $stacks->getListviewData(); - foreach ($data as $k => $d) - $data[$k]['stackRule'] = $groups[$k]; + $foo['name'] .= ' ('.$_.')'; + break; + case 118: // Require Skill + if ($_ = SkillList::getName($effMV)) + $foo['name'] .= Lang::$main['colon'].'('.$_.')'; + else + $foo['name'] .= Lang::$main['colon'].Util::ucFirst(Lang::$game['skill']).' #'.$effMV;; + break; + case 146: // Activate Rune + $_ = @Lang::$spell['powerRunes'][$effMV]; + if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) + $_ = sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_); + else if (!$_) + $_ = $effMV; - if (!$stacks->hasSetFields(['skillLines'])) - $sH = "$['skill']"; - - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $data, - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'spell-group-stack', - 'name' => 'Stack Group', // todo (med): localize - 'visibleCols' => "$['stackRules']", - 'hiddenCols' => isset($sH) ? $sH : null - ] - ); - - $stacks->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - } - } - } - - // tab: linked with - $rows = DB::Aowow()->select(' - SELECT spell_trigger AS `trigger`, - spell_effect AS effect, - type, - IF(ABS(spell_effect) = ?d, ABS(spell_trigger), ABS(spell_effect)) AS related - FROM spell_linked_spell - WHERE ABS(spell_effect) = ?d OR ABS(spell_trigger) = ?d', - $_id, $_id, $_id - ); - - $related = []; - foreach ($rows as $row) - $related[] = $row['related']; - - if ($related) - $linked = new SpellList(array(['s.id', $related])); - - if (isset($linked) && !$linked->error) - { - $lv = $linked->getListviewData(); - $data = []; - - foreach ($rows as $r) - { - foreach ($lv as $dk => $d) - { - if ($r['related'] == $dk) + $foo['name'] .= ' ('.$_.')'; + break; + case 123: // Send Taxi - effMV is taxiPathId. We only use paths for flightmasters for now, so spell-triggered paths are not in the table + default: { - $lv[$dk]['linked'] = [$r['trigger'], $r['effect'], $r['type']]; - $data[] = $lv[$dk]; + if (($effMV || $effId == 97) && $effId != 155) + $foo['name'] .= ' ('.$effMV.')'; + } + // Aura + case 6: // Simple + case 27: // AA Persistent + case 35: // AA Party + case 65: // AA Raid + case 119: // AA Pet + case 128: // AA Friend + case 129: // AA Enemy + case 143: // AA Owner + { + if ($effAura > 0 && isset(Util::$spellAuraStrings[$effAura])) + { + $foo['name'] .= User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'AuraId: '.$effAura, Lang::$main['colon'].Util::$spellAuraStrings[$effAura]) : Lang::$main['colon'].Util::$spellAuraStrings[$effAura]; + + $bar = $effMV; + switch ($effAura) + { + case 17: // Mod Stealth Detection + if ($_ = @Lang::$spell['stealthType'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 19: // Mod Invisibility Detection + if ($_ = @Lang::$spell['invisibilityType'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 24: // Periodic Energize + case 21: // Obsolete Mod Power + case 35: // Mod Increase Power + case 85: // Mod Power Regeneration + case 110: // Mod Power Regeneration Pct + if ($_ = @Lang::$spell['powerTypes'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 29: // Mod Stat + case 80: // Mod Stat % + case 137: // Mod Total Stat % + case 175: // Mod Spell Healing Of Stat Percent + case 212: // Mod Ranged Attack Power Of Stat Percent + case 219: // Mod Mana Regeneration from Stat + case 268: // Mod Attack Power Of Stat Percent + $mask = $effMV == -1 ? 0x1F : 1 << $effMV; + $_ = []; + for ($j = 0; $j < 5; $j++) + if ($mask & (1 << $j)) + $_[] = Lang::$game['stats'][$j]; + + if ($_ = implode(', ', $_)); + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 36: // Shapeshift + if ($st = $this->subject->getModelInfo($this->typeId)) + { + $redButtons[BUTTON_VIEW3D] = array( + 'type' => TYPE_NPC, + 'displayId' => $st['displayId'][1] ? $st['displayId'][rand(0, 1)] : $st['displayId'][0] + ); + + if ($st['creatureType'] > 0) + $infobox[] = '[li]'.Lang::$game['type'].Lang::$main['colon'].Lang::$game['ct'][$st['creatureType']].'[/li]'; + + if ($_ = $st['displayName']) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + } + break; + case 37: // Effect immunity + if ($_ = @Util::$spellEffectStrings[$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 38: // Aura immunity + if ($_ = @Util::$spellAuraStrings[$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 41: // Dispel Immunity + case 178: // Mod Debuff Resistance + case 245: // Mod Aura Duration By Dispel + if ($_ = @Lang::$game['dt'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 44: // Track Creature + if ($_ = @Lang::$game['ct'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 45: // Track Resource + if ($_ = @Lang::$spell['lockType'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 75: // Language + if ($_ = @Lang::$game['languages'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 77: // Mechanic Immunity + case 117: // Mod Mechanic Resistance + case 232: // Mod Mechanic Duration + case 234: // Mod Mechanic Duration (no stack) + case 255: // Mod Mechanic Damage Taken Pct + case 276: // Mod Mechanic Damage Done Percent + if ($_ = @Lang::$game['me'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].Util::asHex($effMV), $_) : $_; + + break; + case 147: // Mechanic Immunity Mask + $_ = []; + foreach (Lang::$game['me'] as $k => $str) + if ($effMV & (1 << $k - 1)) + $_[] = $str; + + if ($_ = implode(', ', $_)) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].Util::asHex($effMV), $_) : $_; + + break; + case 10: // Mod Threat + case 13: // Mod Damage Done + case 14: // Mod Damage Taken + case 22: // Mod Resistance + case 39: // School Immunity + case 40: // Damage Immunity + case 57: // Mod Spell Crit Chance + case 69: // School Absorb + case 71: // Mod Spell Crit Chance School + case 72: // Mod Power Cost School Percent + case 73: // Mod Power Cost School Flat + case 74: // Reflect Spell School + case 79: // Mod Damage Done Pct + case 81: // Split Damage Pct + case 83: // Mod Base Resistance + case 87: // Mod Damage Taken Pct + case 97: // Mana Shield + case 101: // Mod Resistance Pct + case 115: // Mod Healing Taken + case 118: // Mod Healing Taken Pct + case 123: // Mod Target Resistance + case 135: // Mod Healing Done + case 136: // Mod Healing Done Pct + case 142: // Mod Base Resistance Pct + case 143: // Mod Resistance Exclusive + case 149: // Reduce Pushback + case 163: // Mod Crit Damage Bonus + case 174: // Mod Spell Damage Of Stat Percent + case 182: // Mod Resistance Of Stat Percent + case 186: // Mod Attacker Spell Hit Chance + case 194: // Mod Target Absorb School + case 195: // Mod Target Ability Absorb School + case 199: // Mod Increases Spell Percent to Hit + case 229: // Mod AoE Damage Avoidance + case 271: // Mod Damage Percent Taken Form Caster + case 310: // Mod Creature AoE Damage Avoidance + if ($_ = Lang::getMagicSchools($effMV)) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].Util::asHex($effMV), $_) : $_; + + break; + case 30: // Mod Skill + case 98: // Mod Skill Value + if ($_ = SkillList::getName($effMV)) + $bar = ' ('.SkillList::getName($effMV).')'; + else + $bar = Lang::$main['colon'].Util::ucFirst(Lang::$game['skill']).' #'.$effMV;; + + break; + case 107: // Flat Modifier + case 108: // Pct Modifier + if ($_ = @Lang::$spell['spellModOp'][$effMV]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$effMV, $_) : $_; + + break; + case 189: // Mod Rating + case 220: // Combat Rating From Stat + $_ = []; + foreach (Lang::$spell['combatRating'] as $k => $str) + if ((1 << $k) & $effMV) + $_[] = $str; + + if ($_ = implode(', ', $_)) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].Util::asHex($effMV), $_) : $_; + + break; + case 168: // Mod Damage Done Versus + case 59: // Mod Damage Done Versus Creature + $_ = []; + foreach (Lang::$game['ct'] as $k => $str) + if ($effMV & (1 << $k - 1)) + $_[] = $str; + + if ($_ = implode(', ', $_)) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].Util::asHex($effMV), $_) : $_; + + break; + case 249: // Convert Rune + $x = $this->subject->getField('effect'.$i.'MiscValueB'); + if ($_ = @Lang::$spell['powerRunes'][$x]) + $bar = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, Lang::$spell['_value'].Lang::$main['colon'].$x, $_) : $_; + + break; + case 78: // Mounted + case 56: // Transform + { + if ($transform = $this->subject->getModelInfo($this->typeId)) + { + $redButtons[BUTTON_VIEW3D] = ['type' => TYPE_NPC, 'displayId' => $transform['displayId']]; + $bar = ' ('.$transform['displayName'].')'; + } + else + $bar = Lang::$main['colon'].Lang::$game['npc'].' #'.$effMV;; + + break; + } + case 139: // Force Reaction + { + $bar = ' ('.FactionList::getName($effMV).')'; + $foo['value'] = sprintf(Util::$dfnString, $foo['value'], Lang::$game['rep'][$foo['value']]); + } + } + $foo['name'] .= strstr($bar, 'href') || strstr($bar, '#') ? $bar : ($bar ? ' ('.$bar.')' : null); + + if (in_array($effAura, [174, 220, 182])) + $foo['name'] .= ' ['.sprintf(Util::$dfnString, Lang::$game['stats'][$this->subject->getField('effect'.$i.'MiscValueB')], $this->subject->getField('effect'.$i.'MiscValueB')).']'; + else if ($this->subject->getField('effect'.$i.'MiscValueB') > 0) + $foo['name'] .= ' ['.$this->subject->getField('effect'.$i.'MiscValueB').']'; + + } + else if ($effAura > 0) + $foo['name'] .= Lang::$main['colon'].'Unknown Aura ('.$effAura.')'; + break; } } + + // cases where we dont want 'Value' to be displayed + if (in_array($effAura, [11, 12, 36, 77]) || in_array($effId, []) || empty($foo['value'])) + unset($foo['value']); } - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $data, - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'spell-link', - 'name' => 'Linked with', // todo (med): localize - 'hiddenCols' => "$['skill', 'name']", - 'visibleCols' => "$['linkedTrigger', 'linkedEffect']" - ] - ); + unset($foo); // clear reference - $linked->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); + return $effects; } - - - // tab: triggered by - $conditions = array( - 'OR', - ['AND', ['OR', ['effect1Id', SpellList::$effects['trigger']], ['effect1AuraId', SpellList::$auras['trigger']]], ['effect1TriggerSpell', $spell->id]], - ['AND', ['OR', ['effect2Id', SpellList::$effects['trigger']], ['effect2AuraId', SpellList::$auras['trigger']]], ['effect2TriggerSpell', $spell->id]], - ['AND', ['OR', ['effect3Id', SpellList::$effects['trigger']], ['effect3AuraId', SpellList::$auras['trigger']]], ['effect3TriggerSpell', $spell->id]], - ); - - $trigger = new SpellList($conditions); - if (!$trigger->error) - { - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $trigger->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'triggered-by', - 'name' => '$LANG.tab_triggeredby' - ] - ); - - $trigger->addGlobalsToJScript(GLOBALINFO_SELF); - } - - // tab: used by - creature - // SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86 - $conditions = array( - 'OR', - ['spell1', $_id], ['spell2', $_id], ['spell3', $_id], ['spell4', $_id], - ['spell5', $_id], ['spell6', $_id], ['spell7', $_id], ['spell8', $_id] - ); - if ($_ = DB::Aowow()->selectCol('SELECT entryOrGUID FROM smart_scripts WHERE entryorguid > 0 AND source_type = 0 AND action_type IN (11, 75, 85, 86) AND action_param1 = ?d', $_id)) - $conditions[] = ['id', $_]; - - $ubCreature = new CreatureList($conditions); - if (!$ubCreature->error) - { - $pageData['relTabs'][] = array( - 'file' => 'creature', - 'data' => $ubCreature->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'used-by-npc', - 'name' => '$LANG.tab_usedby' - ] - ); - - $ubCreature->addGlobalsToJScript(GLOBALINFO_SELF); - } - - // tab: zone - if ($areas = DB::Aowow()->select('SELECT * FROM spell_area WHERE spell = ?d', $_id)) - { - $zones = new ZoneList(array(['id', array_column($areas, 'area')])); - if (!$zones->error) - { - $lvZones = $zones->getListviewData(); - $zones->addGlobalsToJscript(); - - $lv = []; - $parents = []; - foreach ($areas as $a) - { - if (empty($lvZones[$a['area']])) - continue; - - $_ = ['condition' => []]; - $extra = false; - if ($a['aura_spell']) - { - Util::$pageTemplate->extendGlobalIds(TYPE_SPELL, $a['aura_spell']); - $_['condition'][] = array( - 'type' => TYPE_SPELL, - 'typeId' => abs($a['aura_spell']), - 'status' => $a['aura_spell'] > 0 ? 1 : 0 - ); - } - - if ($a['quest_start']) // status for quests needs work - { - Util::$pageTemplate->extendGlobalIds(TYPE_QUEST, $a['quest_start']); - $_['condition'][] = array( - 'type' => TYPE_QUEST, - 'typeId' => $a['quest_start'], - 'status' => $a['quest_start_status'] & 0x8 ? 1 : 2 - ); - } - - if ($a['quest_end'] && $a['quest_end'] != $a['quest_start']) - { - Util::$pageTemplate->extendGlobalIds(TYPE_QUEST, $a['quest_end']); - $_['condition'][] = array( - 'type' => TYPE_QUEST, - 'typeId' => $a['quest_end'], - 'status' => $a['quest_start_status'] & 0x8 ? 1 : 0 - ); - } - - if ($a['racemask']) - { - $foo = []; - for ($i = 0; $i < 10; $i++) - if ($a['racemask'] & $i) - $foo[] = $i + 1; - - Util::$pageTemplate->extendGlobalIds(TYPE_RACE, $foo); - $_['condition'][] = array( - 'type' => TYPE_RACE, - 'typeId' => $a['racemask'], - 'status' => 1 - ); - } - - if ($a['gender'] != 2) // 2: both - $_['condition'][] = ['gender' => $a['gender'] + 1]; - - if ($_['condition']) - $extra = true; - - $row = array_merge($_, $lvZones[$a['area']]); - - // merge subzones, into one row, if: conditions match && parentZone is shared - if ($p = $zones->getEntry($a['area'])['parentArea']) - { - $parents[] = $p; - $row['parentArea'] = $p; - $row['subzones'] = [$a['area']]; - } - else - $row['parentArea'] = 0; - - $set = false; - foreach ($lv as &$v) - { - if ($v['condition'] != $row['condition'] || ($v['parentArea'] != $row['parentArea'] && $v['id'] != $row['parentArea'])) - continue; - - if (!$row['parentArea'] && $v['id'] != $row['parentArea']) - continue; - - $set = true; - $v['subzones'][] = $row['id']; - break; - } - - // add self as potential subzone; IF we are a parentZone without added children, we get filtered in JScript - if (!$set) - { - $row['subzones'] = [$row['id']]; - $lv[] = $row; - } - } - - // overwrite lvData with parent-lvData (condition and subzones are kept) - if ($parents) - { - $parents = (new ZoneList(array(['id', $parents])))->getListviewData(); - foreach ($lv as &$_) - if (isset($parents[$_['parentArea']])) - $_ = array_merge($_, $parents[$_['parentArea']]); - } - - $pageData['relTabs'][] = array( - 'file' => 'zone', - 'data' => $lv, - 'params' => [ - 'tabs' => '$tabsRelated', - 'extraCols' => $extra ? '$[Listview.extraCols.condition]' : null, - 'hiddenCols' => $extra ? "$['instancetype']" : null - ] - ); - } - } - - // tab: teaches - if ($ids = Util::getTaughtSpells($spell)) - { - $teaches = new SpellList(array(['id', $ids])); - if (!$teaches->error) - { - $teaches->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - $vis = ['level', 'schools']; - $hid = []; - if (!$teaches->hasSetFields(['skillLines'])) - $hid[] = 'skill'; - - foreach ($teaches->iterate() as $__) - { - if (!$teaches->canCreateItem()) - continue; - - $vis[] = 'reagents'; - break; - } - - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $teaches->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'teaches-spell', - 'name' => '$LANG.tab_teaches', - 'visibleCols' => '$'.json_encode($vis), - 'hiddenCols' => $hid ? '$'.json_encode($hid) : null - ] - ); - } - } - - // tab: taught by npc (source:6 => trainer) - if (!empty($spell->sources[$_id]) && in_array(6, array_keys($spell->sources[$_id]))) - { - $list = []; - if (count($spell->sources[$_id][6]) == 1 && $spell->sources[$_id][6][0] == 0) // multiple trainer - { - $tt = null; - if (in_array($_cat, [9, 11])) // Professions - $tt = @Util::$trainerTemplates[TYPE_SKILL][$spell->getField('skillLines')[0]]; - else if ($_cat == 7 && $spell->getField('reqClassMask')) // Class Spells - { - $clId = log($spell->getField('reqClassMask'), 2) + 1 ; - if (intVal($clId) == $clId) // only one class was set, so float == int - $tt = @Util::$trainerTemplates[TYPE_CLASS][$clId]; - } - - if ($tt) - $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 - LEFT JOIN npc_trainer t2 ON t2.spell = -t1.entry - WHERE t1.spell = ?d', - $_id - ); - } - } - - if ($list) - { - $tbTrainer = new CreatureList(array(0, ['ct.id', $list], ['ct.spawns', 0, '>'], ['ct.npcflag', 0x10, '&'])); - if (!$tbTrainer->error) - { - $tbTrainer->addGlobalsToJscript(); - $pageData['relTabs'][] = array( - 'file' => 'creature', - 'data' => $tbTrainer->getListviewData(), - 'params' => array( - 'tabs' => '$tabsRelated', - 'id' => 'taught-by-npc', - 'name' => '$LANG.tab_taughtby', - ) - ); - } - } - } - - // tab: taught by spell - $conditions = array( - 'OR', - ['AND', ['effect1Id', SpellList::$effects['teach']], ['effect1TriggerSpell', $spell->id]], - ['AND', ['effect2Id', SpellList::$effects['teach']], ['effect2TriggerSpell', $spell->id]], - ['AND', ['effect3Id', SpellList::$effects['teach']], ['effect3TriggerSpell', $spell->id]], - ); - - $tbSpell = new SpellList($conditions); - $tbsData = []; - if (!$tbSpell->error) - { - $tbsData = $tbSpell->getListviewData(); - $pageData['relTabs'][] = array( - 'file' => 'spell', - 'data' => $tbsData, - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'taught-by-spell', - 'name' => '$LANG.tab_taughtby' - ] - ); - - $tbSpell->addGlobalsToJScript(GLOBALINFO_SELF); - } - - // tab: taught by quest - $conditions = ['OR', ['sourceSpellId', $_id], ['rewardSpell', $_id]]; - if ($tbsData) - { - $conditions[] = ['rewardSpell', array_keys($tbsData)]; - if (User::isInGroup(U_GROUP_STAFF)) - $conditions[] = ['rewardSpellCast', array_keys($tbsData)]; - } - if (User::isInGroup(U_GROUP_STAFF)) - $conditions[] = ['rewardSpellCast', $_id]; - - $tbQuest = new QuestList($conditions); - if (!$tbQuest->error) - { - $pageData['relTabs'][] = array( - 'file' => 'quest', - 'data' => $tbQuest->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'reward-from-quest', - 'name' => '$LANG.tab_rewardfrom' - ] - ); - - $tbQuest->addGlobalsToJScript(); - } - - // tab: taught by item (i'd like to precheck $spell->sources, but there is no source:item only complicated crap like "drop" and "vendor") - $conditions = array( - 'OR', - ['AND', ['spellTrigger1', 6], ['spellId1', $spell->id]], - ['AND', ['spellTrigger2', 6], ['spellId2', $spell->id]], - ['AND', ['spellTrigger3', 6], ['spellId3', $spell->id]], - ['AND', ['spellTrigger4', 6], ['spellId4', $spell->id]], - ['AND', ['spellTrigger5', 6], ['spellId5', $spell->id]], - ); - - $tbItem = new ItemList($conditions); - if (!$tbItem->error) - { - $pageData['relTabs'][] = array( - 'file' => 'item', - 'data' => $tbItem->getListviewData(), - 'params' => [ - 'tabs' => '$tabsRelated', - 'id' => 'taught-by-item', - 'name' => '$LANG.tab_taughtby' - ] - ); - - $tbItem->addGlobalsToJScript(GLOBALINFO_SELF); - } - - // find associated NPC, Item and merge results - // taughtbypets (unused..?) - // taughtbyquest (usually the spell casted as quest reward teaches something; exclude those seplls from taughtBySpell) - // taughtbytrainers - // taughtbyitem - - - /* NEW - conditions - */ - - $smarty->saveCache($cacheKeyPage, $pageData); } -$smarty->updatePageVars($pageData['page']); -$smarty->assign('community', CommunityContent::getAll(TYPE_SPELL, $_id)); // comments, screenshots, videos -$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$spell, ['colon' => Lang::$colon])); -$smarty->assign('lvData', $pageData['relTabs']); - -// load the page -$smarty->display('spell.tpl'); ?> diff --git a/pages/spells.php b/pages/spells.php index 66693562..a4c8dc92 100644 --- a/pages/spells.php +++ b/pages/spells.php @@ -4,374 +4,347 @@ if (!defined('AOWOW_REVISION')) die('illegal access'); -$cats = Util::extractURLParams($pageParam); -$path = [0, 1]; -$title = [Lang::$game['spells']]; // display max 2 cats, remove this base if nesecary -$filter = ['classPanel' => false, 'glyphPanel' => false]; -$filterHash = !empty($_GET['filter']) ? '#'.sha1(serialize($_GET['filter'])) : null; -$cacheKey = implode('_', [CACHETYPE_PAGE, TYPE_SPELL, -1, implode('.', $cats).$filterHash, User::$localeId]); -$validCats = array( - -2 => array( // Talents: Class => Skill - 1 => [ 26, 256, 257], - 2 => [594, 267, 184], - 3 => [ 50, 163, 51], - 4 => [253, 38, 39], - 5 => [613, 56, 78], - 6 => [770, 771, 772], - 7 => [375, 373, 374], - 8 => [237, 8, 6], - 9 => [355, 354, 593], - 11 => [574, 134, 573] - ), - -3 => [782, 270, 653, 210, 655, 211, 213, 209, 780, 787, 214, 212, 781, 763, 215, 654, 775, 764, 217, 767, 786, 236, 768, 783, 203, 788, 765, 218, 251, 766, 785, 656, 208, 784, 761, 189, 188, 205, 204], // Pet Spells => Skill - -4 => true, // Racial Traits - -5 => true, // Mounts - -6 => true, // Companions - -7 => [409, 410, 411], // PetTalents => TalentTabId - -8 => true, // NPC Abilities - -9 => true, // GM Abilities - -11 => [6, 8, 10], // Proficiencies [Weapon, Armor, Language] - -13 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 11], // Glyphs => Class (GlyphType via filter) - 0 => true, // Uncategorized - 7 => array( // Abilities: Class => Skill - 1 => [ 26, 256, 257], - 2 => [594, 267, 184], - 3 => [ 50, 163, 51], - 4 => [253, 38, 39], - 5 => [613, 56, 78], - 6 => [770, 771, 772, 776], - 7 => [375, 373, 374], - 8 => [237, 8, 6], - 9 => [355, 354, 593], - 11 => [574, 134, 573] - ), - 9 => [129, 185, 356, 762], // Secondary Skills - 11 => array( // Professions: Skill => Spell - 171 => true, - 164 => [9788, 9787, 17041, 17040, 17039], - 333 => true, - 202 => [20219, 20222], - 182 => true, - 773 => true, - 755 => true, - 165 => [10656, 10658, 10660], - 186 => true, - 393 => true, - 197 => [26798, 26801, 26797], - ) -); -$shortFilter = array( - 129 => [ 6, 7], // First Aid - 164 => [ 2, 4], // Blacksmithing - 165 => [ 8, 1], // Leatherworking - 171 => [ 1, 6], // Alchemy - 185 => [ 3, 5], // Cooking - 186 => [ 9, 0], // Mining - 197 => [10, 2], // Tailoring - 202 => [ 5, 3], // Engineering - 333 => [ 4, 8], // Enchanting - 356 => [ 0, 9], // Fishing - 755 => [ 7, 10], // Jewelcrafting - 773 => [15, 0], // Inscription -); - -if (!Util::isValidPage($validCats, $cats)) - $smarty->error(); - -if (!$smarty->loadCache($cacheKey, $pageData, $filter)) +// menuId 1: Spell g_initPath() +// tabId 0: Database g_initHeader() +class SpellsPage extends GenericPage { - $conditions = []; - $visibleCols = []; - $hiddenCols = []; - $lv = array( - 'file' => 'spell', - 'data' => [], - 'params' => [] + use ListPage; + + protected $type = TYPE_SPELL; + protected $tpl = 'spells'; + protected $path = [0, 1]; + protected $tabId = 0; + protected $mode = CACHETYPE_PAGE; + protected $js = ['filters.js']; + protected $validCats = array( + -2 => array( // Talents: Class => Skill + 1 => [ 26, 256, 257], + 2 => [594, 267, 184], + 3 => [ 50, 163, 51], + 4 => [253, 38, 39], + 5 => [613, 56, 78], + 6 => [770, 771, 772], + 7 => [375, 373, 374], + 8 => [237, 8, 6], + 9 => [355, 354, 593], + 11 => [574, 134, 573] + ), + -3 => [782, 270, 653, 210, 655, 211, 213, 209, 780, 787, 214, 212, 781, 763, 215, 654, 775, 764, 217, 767, 786, 236, 768, 783, 203, 788, 765, 218, 251, 766, 785, 656, 208, 784, 761, 189, 188, 205, 204], // Pet Spells => Skill + -4 => true, // Racial Traits + -5 => true, // Mounts + -6 => true, // Companions + -7 => [409, 410, 411], // PetTalents => TalentTabId + -8 => true, // NPC Abilities + -9 => true, // GM Abilities + -11 => [6, 8, 10], // Proficiencies [Weapon, Armor, Language] + -13 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 11], // Glyphs => Class (GlyphType via filter) + 0 => true, // Uncategorized + 7 => array( // Abilities: Class => Skill + 1 => [ 26, 256, 257], + 2 => [594, 267, 184], + 3 => [ 50, 163, 51], + 4 => [253, 38, 39], + 5 => [613, 56, 78], + 6 => [770, 771, 772, 776], + 7 => [375, 373, 374], + 8 => [237, 8, 6], + 9 => [355, 354, 593], + 11 => [574, 134, 573] + ), + 9 => [129, 185, 356, 762], // Secondary Skills + 11 => array( // Professions: Skill => Spell + 171 => true, + 164 => [9788, 9787, 17041, 17040, 17039], + 333 => true, + 202 => [20219, 20222], + 182 => true, + 773 => true, + 755 => true, + 165 => [10656, 10658, 10660], + 186 => true, + 393 => true, + 197 => [26798, 26801, 26797], + ) ); - // reconstruct path & title - $path = array_merge($path, $cats); + private $shortFilter = array( + 129 => [ 6, 7], // First Aid + 164 => [ 2, 4], // Blacksmithing + 165 => [ 8, 1], // Leatherworking + 171 => [ 1, 6], // Alchemy + 185 => [ 3, 5], // Cooking + 186 => [ 9, 0], // Mining + 197 => [10, 2], // Tailoring + 202 => [ 5, 3], // Engineering + 333 => [ 4, 8], // Enchanting + 356 => [ 0, 9], // Fishing + 755 => [ 7, 10], // Jewelcrafting + 773 => [15, 0], // Inscription + ); - if ($cats) + + public function __construct($pageCall, $pageParam) { - if (isset($cats[1])) - array_pop($title); + $this->getCategoryFromUrl($pageParam);; - $x = @Lang::$spell['cat'][$cats[0]]; - if (is_array($x)) + parent::__construct(); + + $this->name = Util::ucFirst(Lang::$game['spells']); + $this->subCat = $pageParam ? '='.$pageParam : ''; + $this->filter = ['classPanel' => false, 'glyphPanel' => false]; + } + + protected function generateContent() + { + $conditions = []; + $visibleCols = []; + $hiddenCols = []; + $this->lvData = array( + 'file' => 'spell', + 'data' => [], + 'params' => [] + ); + + // the next lengthy ~250 lines determine $conditions and lvParams + if ($this->category) { - if (is_array($x[0])) - array_unshift($title, $x[0][0]); - else - array_unshift($title, $x[0]); - } - else if ($x !== null) - array_unshift($title, $x); + switch ($this->category[0]) + { + case -2: // Character Talents + $this->filter['classPanel'] = true; - switch($cats[0]) - { - case -2: // Character Talents - $filter['classPanel'] = true; + array_push($visibleCols, 'singleclass', 'level', 'schools', 'tier'); - array_push($visibleCols, 'singleclass', 'level', 'schools', 'tier'); + $conditions[] = ['s.typeCat', -2]; - $conditions[] = ['s.typeCat', -2]; + // i will NOT redefine those class2skillId ... reusing + if (isset($this->category[2])) + $conditions[] = ['s.skillLine1', $this->category[2]]; + else if (isset($this->category[1])) + $conditions[] = ['s.skillLine1', $this->validCats[-2][$this->category[1]]]; - if (isset($cats[1])) - array_unshift($title, Lang::$game['cl'][$cats[1]]); + break; + case -3: // Pet Spells + array_push($visibleCols, 'level', 'schools'); - if (isset($cats[1]) && empty($cats[2])) // i will NOT redefine those class2skillId ... reusing - $conditions[] = ['s.skillLine1', $validCats[-2][$cats[1]]]; - else if (isset($cats[1])) - $conditions[] = ['s.skillLine1', $cats[2]]; + $conditions[] = ['s.typeCat', -3]; - break; - case -3: // Pet Spells - array_push($visibleCols, 'level', 'schools'); - - $conditions[] = ['s.typeCat', -3]; - - if (isset($cats[1])) - { - $xCond = null; - for ($i = -2; $i < 0; $i++) + if (isset($this->category[1])) { - foreach (Util::$skillLineMask[$i] as $idx => $pair) + $xCond = null; + for ($i = -2; $i < 0; $i++) { - if ($pair[1] == $cats[1]) + foreach (Util::$skillLineMask[$i] as $idx => $pair) { - $xCond = ['AND', ['s.skillLine1', $i], ['s.skillLine2OrMask', 1 << $idx, '&']]; - break; + if ($pair[1] == $this->category[1]) + { + $xCond = ['AND', ['s.skillLine1', $i], ['s.skillLine2OrMask', 1 << $idx, '&']]; + break; + } } } + + $conditions[] = [ + 'OR', + $xCond, + ['s.skillLine1', $this->category[1]], + ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->category[1]]] + ]; + } + else + { + $conditions[] = [ + 'OR', + ['s.skillLine1', [-1, -2]], + ['s.skillLine1', $this->validCats[-3]], + ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->validCats[-3]]] + ]; + } + + break; + case -4: // Racials + array_push($visibleCols, 'classes'); + + $conditions[] = ['s.typeCat', -4]; + + break; + case -8: // NPC-Spells + case -9: // GM Spells + array_push($visibleCols, 'level'); + case -5: // Mounts + case -6: // Companions + $conditions[] = ['s.typeCat', $this->category[0]]; + + break; + case -7: // Pet Talents + array_push($visibleCols, 'level', 'tier'); + + $conditions[] = ['s.typeCat', -7]; + + if (isset($this->category[1])) + { + switch ($this->category[1]) // Spells can be used by multiple specs + { + case 409: // Tenacity + $conditions[] = ['s.cuFlags', SPELL_CU_PET_TALENT_TYPE1, '&']; + $url = '?pets=1'; + break; + case 410: // Cunning + $conditions[] = ['s.cuFlags', SPELL_CU_PET_TALENT_TYPE2, '&']; + $url = '?pets=2'; + break; + case 411: // Ferocity + $conditions[] = ['s.cuFlags', SPELL_CU_PET_TALENT_TYPE0, '&']; + $url = '?pets=0'; + break; + } + + $this->lvData['params']['note'] = '$$WH.sprintf(LANG.lvnote_pettalents, "'.$url.'")'; + } + + $this->lvData['params']['_petTalents'] = 1; // not conviced, this is correct, but .. it works + + break; + case -11: // Proficiencies ... the subIds are actually SkillLineCategories + if (!isset($this->category[1]) || $this->category[1] != 10) + array_push($visibleCols, 'classes'); + + $conditions[] = ['s.typeCat', -11]; + + if (isset($this->category[1])) + { + if ($this->category[1] == 6) // todo (med): we know Weapon(6) includes spell Shoot(3018), that has a mask; but really, ANY proficiency or petSkill should be in that mask so there is no need to differenciate + $conditions[] = ['OR', ['s.skillLine1', SpellList::$skillLines[$this->category[1]]], ['s.skillLine1', -3]]; + else + $conditions[] = ['s.skillLine1', SpellList::$skillLines[$this->category[1]]]; + } + + break; + case -13: // Glyphs + $this->filter['classPanel'] = true; + $this->filter['glyphPanel'] = true; + + array_push($visibleCols, 'singleclass', 'glyphtype'); + + $conditions[] = ['s.typeCat', -13]; + + if (isset($this->category[1])) + $conditions[] = ['s.reqClassMask', 1 << ($this->category[1] - 1), '&']; + + break; + case 7: // Abilities + $this->filter['classPanel'] = true; + + array_push($visibleCols, 'level', 'singleclass', 'schools'); + + $conditions[] = ['s.typeCat', [7, -2]]; + $conditions[] = [['s.cuFlags', (SPELL_CU_TRIGGERED | SPELL_CU_TALENT | CUSTOM_EXCLUDE_FOR_LISTVIEW), '&'], 0]; + + // Runeforging listed multiple times, exclude from explicit skill-listing + // if (isset($this->category[1]) && $this->category[1] == 6 && isset($this->category[2]) && $this->category[2] != 776) + // $conditions[] = [['s.attributes0', 0x80, '&'], 0]; + // else + // $conditions[] = [ + // [['s.attributes0', 0x80, '&'], 0], // ~SPELL_ATTR0_HIDDEN_CLIENTSIDE + // ['s.attributes0', 0x20, '&'], // SPELL_ATTR0_TRADESPELL (DK: Runeforging) + // 'OR' + // ]; + + if (isset($this->category[2])) + { + $conditions[] = [ + 'OR', + ['s.skillLine1', $this->category[2]], + ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->category[2]]] + ]; + + } + else if (isset($this->category[1])) + { + $conditions[] = [ + 'OR', + ['s.skillLine1', $this->validCats[7][$this->category[1]]], + ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->validCats[7][$this->category[1]]]] + ]; + + } + + break; + case 9: // Secondary Skills + array_push($visibleCols, 'source'); + + $conditions[] = ['s.typeCat', 9]; + + if (isset($this->category[1])) + { + $conditions[] = [ + 'OR', + ['s.skillLine1', $this->category[1]], + ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->category[1]]] + ]; + + if ($sf = @$this->shortFilter[$this->category[1]]) + { + $txt = ''; + if ($sf[0] && $sf[1]) + $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]) . Lang::$spell['relItems']['link'] . sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); + else if ($sf[0]) + $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]); + else if ($sf[1]) + $txt = sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); + + $note = Lang::$spell['cat'][$this->category[0]][$this->category[1]]; + if (is_array($note)) + $note = $note[0]; + + $this->lvData['params']['note'] = sprintf(Lang::$spell['relItems']['base'], $txt, $note); + $this->lvData['params']['sort'] = "$['skill', 'name']"; + } } - $conditions[] = [ - 'OR', - $xCond, - ['s.skillLine1', $cats[1]], - ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $cats[1]]] - ]; + break; + case 11: // Professions + array_push($visibleCols, 'source'); - array_unshift($title, Lang::$spell['cat'][-3][$cats[1]]); - } - else - { - $conditions[] = [ - 'OR', - ['s.skillLine1', [-1, -2]], - ['s.skillLine1', $validCats[-3]], - ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $validCats[-3]]] - ]; - } + $conditions[] = ['s.typeCat', 11]; - break; - case -4: // Racials - array_push($visibleCols, 'classes'); - - $conditions[] = ['s.typeCat', -4]; - - break; - case -8: // NPC-Spells - case -9: // GM Spells - array_push($visibleCols, 'level'); - case -5: // Mounts - case -6: // Companions - $conditions[] = ['s.typeCat', $cats[0]]; - - break; - case -7: // Pet Talents - array_push($visibleCols, 'level', 'tier'); - - $conditions[] = ['s.typeCat', -7]; - - if (isset($cats[1])) - { - array_unshift($title, Lang::$spell['cat'][-7][$cats[1]]); - - switch($cats[1]) // Spells can be used by multiple specs + if (isset($this->category[2])) { - case 409: // Tenacity - $conditions[] = ['s.cuFlags', SPELL_CU_PET_TALENT_TYPE1, '&']; - $url = '?pets=1'; - break; - case 410: // Cunning - $conditions[] = ['s.cuFlags', SPELL_CU_PET_TALENT_TYPE2, '&']; - $url = '?pets=2'; - break; - case 411: // Ferocity - $conditions[] = ['s.cuFlags', SPELL_CU_PET_TALENT_TYPE0, '&']; - $url = '?pets=0'; - break; + if ($this->category[2] == 9787) // general weaponsmithing + $conditions[] = ['s.reqSpellId', [9787, 17039, 17040, 17041]]; + else + $conditions[] = ['s.reqSpellId', $this->category[2]]; + } + else if (isset($this->category[1])) + $conditions[] = ['s.skillLine1', $this->category[1]]; + + if (isset($this->category[1])) + { + $conditions[] = ['s.skillLine1', $this->category[1]]; + + if ($sf = @$this->shortFilter[$this->category[1]]) + { + $txt = ''; + if ($sf[0] && $sf[1]) + $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]) . Lang::$spell['relItems']['link'] . sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); + else if ($sf[0]) + $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]); + else if ($sf[1]) + $txt = sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); + + $note = Lang::$spell['cat'][$this->category[0]][$this->category[1]]; + if (is_array($note)) + $note = $note[0]; + + $this->lvData['params']['note'] = sprintf(Lang::$spell['relItems']['base'], $txt, $note); + $this->lvData['params']['sort'] = "$['skill', 'name']"; + } } - $lv['params']['note'] = '$$WH.sprintf(LANG.lvnote_pettalents, "'.$url.'")'; - } + break; + case 0: // misc. Spells + array_push($visibleCols, 'level'); - $lv['params']['_petTalents'] = 1; // not conviced, this is correct, but .. it works - - break; - case -11: // Proficiencies ... the subIds are actually SkillLineCategories - if (!isset($cats[1]) || $cats[1] != 10) - array_push($visibleCols, 'classes'); - - $conditions[] = ['s.typeCat', -11]; - - if (isset($cats[1])) - { - if ($cats[1] == 6) // todo (med): we know Weapon(6) includes spell Shoot(3018), that has a mask; but really, ANY proficiency or petSkill should be in that mask so there is no need to differenciate - $conditions[] = ['OR', ['s.skillLine1', SpellList::$skillLines[$cats[1]]], ['s.skillLine1', -3]]; - else - $conditions[] = ['s.skillLine1', SpellList::$skillLines[$cats[1]]]; - - array_unshift($title, Lang::$spell['cat'][-11][$cats[1]]); - } - - break; - case -13: // Glyphs - $filter['classPanel'] = true; - $filter['glyphPanel'] = true; - - array_push($visibleCols, 'singleclass', 'glyphtype'); - - $conditions[] = ['s.typeCat', -13]; - - if (isset($cats[1])) - { - array_unshift($title, Lang::$game['cl'][$cats[1]]); - $conditions[] = ['s.reqClassMask', 1 << ($cats[1] - 1), '&']; - } - - break; - case 7: // Abilities - $filter['classPanel'] = true; - - array_push($visibleCols, 'level', 'singleclass', 'schools'); - - if (isset($cats[1])) - array_unshift($title, Lang::$game['cl'][$cats[1]]); - - $conditions[] = ['s.typeCat', [7, -2]]; - $conditions[] = [['s.cuFlags', (SPELL_CU_TRIGGERED | SPELL_CU_TALENT | CUSTOM_EXCLUDE_FOR_LISTVIEW), '&'], 0]; - - // Runeforging listed multiple times, exclude from explicit skill-listing - // if (isset($cats[1]) && $cats[1] == 6 && isset($cats[2]) && $cats[2] != 776) - // $conditions[] = [['s.attributes0', 0x80, '&'], 0]; - // else - // $conditions[] = [ - // [['s.attributes0', 0x80, '&'], 0], // ~SPELL_ATTR0_HIDDEN_CLIENTSIDE - // ['s.attributes0', 0x20, '&'], // SPELL_ATTR0_TRADESPELL (DK: Runeforging) - // 'OR' - // ]; - - if (isset($cats[2])) - { - $conditions[] = [ - 'OR', - ['s.skillLine1', $cats[2]], - ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $cats[2]]] - ]; - - } - else if (isset($cats[1])) - { - $conditions[] = [ - 'OR', - ['s.skillLine1', $validCats[7][$cats[1]]], - ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $validCats[7][$cats[1]]]] - ]; - - } - - break; - case 9: // Secondary Skills - array_push($visibleCols, 'source'); - - $conditions[] = ['s.typeCat', 9]; - - if (isset($cats[1])) - { - array_unshift($title, Lang::$spell['cat'][9][$cats[1]]); - - $conditions[] = [ - 'OR', - ['s.skillLine1', $cats[1]], - ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $cats[1]]] - ]; - - if ($sf = @$shortFilter[$cats[1]]) - { - $txt = ''; - if ($sf[0] && $sf[1]) - $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]) . Lang::$spell['relItems']['link'] . sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); - else if ($sf[0]) - $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]); - else if ($sf[1]) - $txt = sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); - - $note = Lang::$spell['cat'][$cats[0]][$cats[1]]; - if (is_array($note)) - $note = $note[0]; - - $lv['params']['note'] = sprintf(Lang::$spell['relItems']['base'], $txt, $note); - $lv['params']['sort'] = "$['skill', 'name']"; - } - } - - break; - case 11: // Professions - array_push($visibleCols, 'source'); - - $conditions[] = ['s.typeCat', 11]; - - if (isset($cats[2])) - { - array_unshift($title, Lang::$spell['cat'][11][$cats[1]][$cats[2]]); - - if ($cats[2] == 9787) // general weaponsmithing - $conditions[] = ['s.reqSpellId', [9787, 17039, 17040, 17041]]; - else - $conditions[] = ['s.reqSpellId', $cats[2]]; - } - else if (isset($cats[1])) - { - $x = Lang::$spell['cat'][11][$cats[1]]; - if (is_array($x)) - array_unshift($title, $x[0]); - else - array_unshift($title, $x); - $conditions[] = ['s.skillLine1', $cats[1]]; - } - - if (isset($cats[1])) - { - $conditions[] = ['s.skillLine1', $cats[1]]; - - if ($sf = @$shortFilter[$cats[1]]) - { - $txt = ''; - if ($sf[0] && $sf[1]) - $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]) . Lang::$spell['relItems']['link'] . sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); - else if ($sf[0]) - $txt = sprintf(Lang::$spell['relItems']['crafted'], $sf[0]); - else if ($sf[1]) - $txt = sprintf(Lang::$spell['relItems']['recipes'], $sf[1]); - - $note = Lang::$spell['cat'][$cats[0]][$cats[1]]; - if (is_array($note)) - $note = $note[0]; - - $lv['params']['note'] = sprintf(Lang::$spell['relItems']['base'], $txt, $note); - $lv['params']['sort'] = "$['skill', 'name']"; - } - } - - break; - case 0: // misc. Spells - array_push($visibleCols, 'level'); - - if ($cats[0] !== null) // !any Spell (php loose comparison: (null == 0) is true) - { $conditions[] = array( 'OR', ['s.typeCat', 0], @@ -379,91 +352,91 @@ if (!$smarty->loadCache($cacheKey, $pageData, $filter)) ); break; - } + } } + + $spellFilter = new SpellListFilter(); + if ($_ = $spellFilter->getConditions()) + $conditions[] = $_; + + $spells = new SpellList($conditions); + + $this->extendGlobalData($spells->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); + $this->lvData['data'] = $spells->getListviewData(); + + // recreate form selection + $this->filter = array_merge($spellFilter->getForm('form'), $this->filter); + $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL; + $this->filter['fi'] = $spellFilter->getForm(); + + if (!empty($this->filter['fi']['extraCols'])) + $this->lvData['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)'; + + // create note if search limit was exceeded; overwriting 'note' is intentional + if ($spells->getMatches() > CFG_SQL_LIMIT_DEFAULT) + { + $this->lvData['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_spellsfound', $spells->getMatches(), CFG_SQL_LIMIT_DEFAULT); + $this->lvData['params']['_truncated'] = 1; + } + + if ($spellFilter->error) + $this->lvData['params']['_errors'] = '$1'; + + $mask = $spells->hasSetFields(['reagent1', 'skillLines', 'trainingCost']); + if ($mask & 0x1) + $visibleCols[] = 'reagents'; + if (!($mask & 0x2) && $this->category && !in_array($this->category[0], [9, 11])) + $hiddenCols[] = 'skill'; + if (($mask & 0x4)) + $visibleCols[] = 'trainingcost'; + + if ($visibleCols) + $this->lvData['params']['visibleCols'] = '$'.json_encode($visibleCols); + + if ($hiddenCols) + $this->lvData['params']['hiddenCols'] = '$'.json_encode($hiddenCols); + + // sort for dropdown-menus + asort(Lang::$game['ra']); + asort(Lang::$game['cl']); + asort(Lang::$game['sc']); + asort(Lang::$game['me']); } - $spellFilter = new SpellListFilter(); - if ($_ = $spellFilter->getConditions()) - $conditions[] = $_; - - $spells = new SpellList($conditions); - - $spells->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED); - $lv['data'] = $spells->getListviewData(); - - // recreate form selection - $filter = array_merge($spellFilter->getForm('form'), $filter); - $filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL; - $filter['fi'] = $spellFilter->getForm(); - - if (isset($filter['gl']) && !is_array($filter['gl'])) + protected function generateTitle() { - while (count($path) < 4) - $path[] = 0; + $foo = []; + $c = $this->category; // shothand + if (isset($c[2]) && $c[0] == 11) + array_unshift($foo, Lang::$spell['cat'][$c[0]][$c[1]][$c[2]]); + else if (isset($c[1])) + { + $_ = in_array($c[0], [-2, -13, 7]) ? Lang::$game['cl'] : Lang::$spell['cat'][$c[0]]; + array_unshift($foo, is_array($_[$c[1]]) ? $_[$c[1]][0] : $_[$c[1]]); + } - $path[] = $filter['gl']; + if (isset($c[0]) && count($foo) < 2) + { + $_ = Lang::$spell['cat'][$c[0]]; + array_unshift($foo, is_array($_) ? $_[0] : $_); + } + + if(count($foo) < 2) + array_unshift($foo, $this->name); + + foreach ($foo as $bar) + array_unshift($this->title, $bar); } - if (!empty($filter['fi']['extraCols'])) - $lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)'; - - // create note if search limit was exceeded; overwriting 'note' is intentional - if ($spells->getMatches() > CFG_SQL_LIMIT_DEFAULT) + protected function generatePath() { - $lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_spellsfound', $spells->getMatches(), CFG_SQL_LIMIT_DEFAULT); - $lv['params']['_truncated'] = 1; + foreach ($this->category as $c) + $this->path[] = $c; + + $form = (new SpellListFilter())->getForm('form'); + if (count($this->path) == 4 && $this->category[0] == -13 && isset($form['gl']) && !is_array($form['gl'])) + $this->path[] = $form['gl']; } - - if ($spellFilter->error) - $lv['params']['_errors'] = '$1'; - - $mask = $spells->hasSetFields(['reagent1', 'skillLines', 'trainingCost']); - - if ($mask & 0x1) - $visibleCols[] = 'reagents'; - if (!($mask & 0x2) && $cats && $cats[0] != 9 && $cats[0] != 11) - $hiddenCols[] = 'skill'; - if (($mask & 0x4) || $spells->getField('trainingCost')) - $visibleCols[] = 'trainingcost'; - - if ($visibleCols) - $lv['params']['visibleCols'] = '$'.json_encode($visibleCols); - - if ($hiddenCols) - $lv['params']['hiddenCols'] = '$'.json_encode($hiddenCols); - - // menuId 1: Spell g_initPath() - // tabId 0: Database g_initHeader() - $pageData = array( - 'page' => array( - 'title' => implode(" - ", $title), - 'path' => json_encode($path, JSON_NUMERIC_CHECK), - 'tab' => 0, - 'subCat' => $pageParam !== null ? '='.$pageParam : '', - 'reqJS' => array( - STATIC_URL.'/js/filters.js' - ) - ), - 'lv' => $lv - ); - - $smarty->saveCache($cacheKey, $pageData, $filter); } - -// sort for dropdown-menus -asort(Lang::$game['ra']); -asort(Lang::$game['cl']); -asort(Lang::$game['sc']); -asort(Lang::$game['me']); - -$smarty->updatePageVars($pageData['page']); -$smarty->assign('filter', $filter); -$smarty->assign('lang', array_merge(Lang::$main, Lang::$game, Lang::$achievement, ['colon' => Lang::$colon])); -$smarty->assign('lvData', $pageData['lv']); - -// load the page -$smarty->display('spells.tpl'); - ?> diff --git a/template/bricks/footer.tpl.php b/template/bricks/footer.tpl.php index 48d94704..01b77f9d 100644 --- a/template/bricks/footer.tpl.php +++ b/template/bricks/footer.tpl.php @@ -1,22 +1,22 @@ diff --git a/template/bricks/reagentList.tpl.php b/template/bricks/reagentList.tpl.php index 575ac899..fc0ef46e 100644 --- a/template/bricks/reagentList.tpl.php +++ b/template/bricks/reagentList.tpl.php @@ -1,7 +1,7 @@ -

+

reagents['enhanced']): +if ($enhanced): ?>