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