protected function generateContent() { $conditions = []; if (!User::isInGroup(U_GROUP_EMPLOYEE)) { $conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0]; } if ($_ = $this->filterObj->getConditions()) { $conditions[] = $_; } $itemsets = new ItemsetList($conditions); $this->extendGlobalData($itemsets->getJSGlobals()); // recreate form selection $this->filter = array_merge($this->filterObj->getForm('form'), $this->filter); $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL; $this->filter['fi'] = $this->filterObj->getForm(); $this->addJS('?data=weight-presets&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']); $lv = array('file' => 'itemset', 'data' => $itemsets->getListviewData(), 'params' => []); if (!empty($this->filter['fi']['extraCols'])) { $lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)'; } // create note if search limit was exceeded if ($itemsets->getMatches() > CFG_SQL_LIMIT_DEFAULT) { $lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsetsfound', $itemsets->getMatches(), CFG_SQL_LIMIT_DEFAULT); $lv['params']['_truncated'] = 1; } if ($this->filterObj->error) { $lv['params']['_errors'] = '$1'; } $this->lvTabs[] = $lv; // sort for dropdown-menus Lang::sort('itemset', 'notes', SORT_NATURAL); Lang::sort('game', 'si'); }
private function _searchItemset($cndBase, &$shared) { $result = []; $cnd = array_merge($cndBase, [is_int($this->query) ? ['id', $this->query] : $this->createLookup()]); $sets = new ItemsetList($cnd); if ($data = $sets->getListviewData()) { if ($this->searchMask & SEARCH_TYPE_REGULAR) { $this->extendGlobalData($sets->getJSGlobals(GLOBALINFO_SELF)); } if ($this->searchMask & SEARCH_TYPE_OPEN) { foreach ($sets->iterate() as $__) { $data[$sets->id]['param1'] = $sets->getField('quality'); } } $result = array('type' => TYPE_ITEMSET, 'appendix' => ' (Item Set)', 'matches' => $sets->getMatches(), 'file' => ItemsetList::$brickFile, 'data' => $data, 'params' => []); $shared['pcsToSet'] = $sets->pieceToSet; if ($sets->getMatches() > $this->maxResults) { $result['params']['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_itemsetsfound', $sets->getMatches(), $this->maxResults); $result['params']['_truncated'] = 1; } if (isset($result['params']['note'])) { $result['params']['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?itemsets&filter=na=' . urlencode($this->search) . '\')'; } else { $result['params']['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?itemsets&filter=na=' . urlencode($this->search) . '\')'; } } return $result; }
public function renderTooltip($interactive = false, $subOf = 0, $enhance = []) { if ($this->error) { return; } $_name = $this->getField('name', true); $_reqLvl = $this->curTpl['requiredLevel']; $_quality = $this->curTpl['quality']; $_flags = $this->curTpl['flags']; $_class = $this->curTpl['class']; $_subClass = $this->curTpl['subClass']; $_slot = $this->curTpl['slot']; $causesScaling = false; if (!empty($enhance['r'])) { if ($this->getRandEnchantForItem($enhance['r'])) { $_name .= ' ' . Util::localizedString($this->enhanceR, 'name'); $randEnchant = ''; for ($i = 1; $i < 6; $i++) { if ($this->enhanceR['enchantId' . $i] <= 0) { continue; } $enchant = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE Id = ?d', $this->enhanceR['enchantId' . $i]); if ($this->enhanceR['allocationPct' . $i] > 0) { $amount = intVal($this->enhanceR['allocationPct' . $i] * $this->generateEnchSuffixFactor()); $randEnchant .= '<span>' . str_replace('$i', $amount, Util::localizedString($enchant, 'name')) . '</span><br />'; } else { $randEnchant .= '<span>' . Util::localizedString($enchant, 'name') . '</span><br />'; } } } else { unset($enhance['r']); } } if (isset($enhance['s']) && !in_array($_slot, [INVTYPE_WRISTS, INVTYPE_WAIST, INVTYPE_HANDS])) { unset($enhance['s']); } // IMPORTAT: DO NOT REMOVE THE HTML-COMMENTS! THEY ARE REQUIRED TO UPDATE THE TOOLTIP CLIENTSIDE $x = ''; // upper table: stats if (!$subOf) { $x .= '<table><tr><td>'; } // name; quality if ($subOf) { $x .= '<span class="q' . $_quality . '"><a href="?item=' . $this->id . '">' . $_name . '</a></span>'; } else { $x .= '<b class="q' . $_quality . '">' . $_name . '</b>'; } // heroic tag if ($_flags & ITEM_FLAG_HEROIC && $_quality == ITEM_QUALITY_EPIC) { $x .= '<br /><span class="q2">' . Lang::item('heroic') . '</span>'; } // requires map (todo: reparse ?_zones for non-conflicting data; generate Link to zone) if ($_ = $this->curTpl['map']) { $map = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE mapId = ?d LIMIT 1', $_); $x .= '<br /><a href="?zone=' . $_ . '" class="q1">' . Util::localizedString($map, 'name') . '</a>'; } // requires area if ($this->curTpl['area']) { $area = DB::Aowow()->selectRow('SELECT * FROM ?_zones WHERE Id=?d LIMIT 1', $this->curTpl['area']); $x .= '<br />' . Util::localizedString($area, 'name'); } // conjured if ($_flags & ITEM_FLAG_CONJURED) { $x .= '<br />' . Lang::item('conjured'); } // bonding if ($_flags & ITEM_FLAG_ACCOUNTBOUND) { $x .= '<br /><!--bo-->' . Lang::item('bonding', 0); } else { if ($this->curTpl['bonding']) { $x .= '<br /><!--bo-->' . Lang::item('bonding', $this->curTpl['bonding']); } } // unique || unique-equipped || unique-limited if ($this->curTpl['maxCount'] > 0) { $x .= '<br />' . Lang::item('unique'); if ($this->curTpl['maxCount'] > 1) { $x .= ' (' . $this->curTpl['maxCount'] . ')'; } } else { if ($_flags & ITEM_FLAG_UNIQUEEQUIPPED) { $x .= '<br />' . Lang::item('uniqueEquipped'); } else { if ($this->curTpl['itemLimitCategory']) { $limit = DB::Aowow()->selectRow("SELECT * FROM ?_itemlimitcategory WHERE id = ?", $this->curTpl['itemLimitCategory']); $x .= '<br />' . ($limit['isGem'] ? Lang::item('uniqueEquipped') : Lang::item('unique')) . Lang::main('colon') . Util::localizedString($limit, 'name') . ' (' . $limit['count'] . ')'; } } } // max duration if ($dur = $this->curTpl['duration']) { $x .= "<br />" . Lang::game('duration') . Lang::main('colon') . Util::formatTime(abs($dur) * 1000) . ($this->curTpl['flagsCustom'] & 0x1 ? ' (' . Lang::item('realTime') . ')' : null); } // required holiday if ($eId = $this->curTpl['eventId']) { if ($hName = DB::Aowow()->selectRow('SELECT h.* FROM ?_holidays h JOIN ?_events e ON e.holidayId = h.id WHERE e.id = ?d', $eId)) { $x .= '<br />' . sprintf(Lang::game('requires'), '<a href="' . $eId . '" class="q1">' . Util::localizedString($hName, 'name') . '</a>'); } } // item begins a quest if ($this->curTpl['startQuest']) { $x .= '<br /><a class="q1" href="?quest=' . $this->curTpl['startQuest'] . '">' . Lang::item('startQuest') . '</a>'; } // containerType (slotCount) if ($this->curTpl['slots'] > 0) { $fam = $this->curTpl['bagFamily'] ? log($this->curTpl['bagFamily'], 2) + 1 : 0; // word order differs <_< if (in_array(User::$localeId, [LOCALE_FR, LOCALE_ES, LOCALE_RU])) { $x .= '<br />' . sprintf(Lang::item('bagSlotString'), Lang::item('bagFamily', $fam), $this->curTpl['slots']); } else { $x .= '<br />' . sprintf(Lang::item('bagSlotString'), $this->curTpl['slots'], Lang::item('bagFamily', $fam)); } } if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON, ITEM_CLASS_AMMUNITION])) { $x .= '<table width="100%"><tr>'; // Class if ($_slot) { $x .= '<td>' . Lang::item('inventoryType', $_slot) . '</td>'; } // Subclass if ($_class == ITEM_CLASS_ARMOR && $_subClass > 0) { $x .= '<th><!--asc' . $_subClass . '-->' . Lang::item('armorSubClass', $_subClass) . '</th>'; } else { if ($_class == ITEM_CLASS_WEAPON) { $x .= '<th>' . Lang::item('weaponSubClass', $_subClass) . '</th>'; } else { if ($_class == ITEM_CLASS_AMMUNITION) { $x .= '<th>' . Lang::item('projectileSubClass', $_subClass) . '</th>'; } } } $x .= '</tr></table>'; } else { if ($_slot && $_class != ITEM_CLASS_CONTAINER) { // yes, slot can occur on random items and is then also displayed <_< .. excluding Bags >_> $x .= '<br />' . Lang::item('inventoryType', $_slot) . '<br />'; } else { $x .= '<br />'; } } // Weapon/Ammunition Stats (not limited to weapons (see item:1700)) $speed = $this->curTpl['delay'] / 1000; $dmgmin1 = $this->curTpl['dmgMin1'] + $this->curTpl['dmgMin2']; $dmgmax1 = $this->curTpl['dmgMax1'] + $this->curTpl['dmgMax2']; $dps = $speed ? ($dmgmin1 + $dmgmax1) / (2 * $speed) : 0; if ($_class == ITEM_CLASS_AMMUNITION && $dmgmin1 && $dmgmax1) { $x .= Lang::item('addsDps') . ' ' . number_format(($dmgmin1 + $dmgmax1) / 2, 1) . ' ' . Lang::item('dps2') . '<br />'; } else { if ($dps) { if ($_class == ITEM_CLASS_WEAPON) { $x .= '<table width="100%"><tr>'; $x .= '<td><!--dmg-->' . sprintf($this->curTpl['dmgType1'] ? Lang::item('damageMagic') : Lang::item('damagePhys'), $this->curTpl['dmgMin1'] . ' - ' . $this->curTpl['dmgMax1'], Lang::game('sc', $this->curTpl['dmgType1'])) . '</td>'; $x .= '<th>' . Lang::item('speed') . ' <!--spd-->' . number_format($speed, 2) . '</th>'; // do not use localized format here! $x .= '</tr></table>'; } else { $x .= '<!--dmg-->' . sprintf($this->curTpl['dmgType1'] ? Lang::item('damageMagic') : Lang::item('damagePhys'), $this->curTpl['dmgMin1'] . ' - ' . $this->curTpl['dmgMax1'], Lang::game('sc', $this->curTpl['dmgType1'])) . '<br />'; } // secondary damage is set if ($this->curTpl['dmgMin2']) { $x .= '+' . sprintf($this->curTpl['dmgType2'] ? Lang::item('damageMagic') : Lang::item('damagePhys'), $this->curTpl['dmgMin2'] . ' - ' . $this->curTpl['dmgMax2'], Lang::game('sc', $this->curTpl['dmgType2'])) . '<br />'; } if ($_class == ITEM_CLASS_WEAPON) { $x .= '<!--dps-->(' . number_format($dps, 1) . ' ' . Lang::item('dps') . ')<br />'; } // do not use localized format here! // display FeralAttackPower if set if ($fap = $this->getFeralAP()) { $x .= '<span class="c11"><!--fap-->(' . $fap . ' ' . Lang::item('fap') . ')</span><br />'; } } } // Armor if ($_class == ITEM_CLASS_ARMOR && $this->curTpl['armorDamageModifier'] > 0) { $spanI = 'class="q2"'; if ($interactive) { $spanI = 'class="q2 tip" onmouseover="$WH.Tooltip.showAtCursor(event, $WH.sprintf(LANG.tooltip_armorbonus, ' . $this->curTpl['armorDamageModifier'] . '), 0, 0, \'q\')" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()"'; } $x .= '<span ' . $spanI . '><!--addamr' . $this->curTpl['armorDamageModifier'] . '--><span>' . sprintf(Lang::item('armor'), intVal($this->curTpl['armor'] + $this->curTpl['armorDamageModifier'])) . '</span></span><br />'; } else { if ($this->curTpl['armor'] + $this->curTpl['armorDamageModifier'] > 0) { $x .= '<span><!--amr-->' . sprintf(Lang::item('armor'), intVal($this->curTpl['armor'] + $this->curTpl['armorDamageModifier'])) . '</span><br />'; } } // Block if ($this->curTpl['block']) { $x .= '<span>' . sprintf(Lang::item('block'), $this->curTpl['block']) . '</span><br />'; } // Item is a gem (don't mix with sockets) if ($geId = $this->curTpl['gemEnchantmentId']) { $gemEnch = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?d', $geId); $x .= '<span class="q1"><a href="?enchantment=' . $geId . '">' . Util::localizedString($gemEnch, 'name') . '</a></span><br />'; // activation conditions for meta gems if (!empty($gemEnch['conditionId'])) { if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE id = ?d', $gemEnch['conditionId'])) { for ($i = 1; $i < 6; $i++) { if (!$gemCnd['color' . $i]) { continue; } switch ($gemCnd['comparator' . $i]) { case 2: // requires less <color> than (<value> || <comparecolor>) gems // requires less <color> than (<value> || <comparecolor>) gems case 5: // requires at least <color> than (<value> || <comparecolor>) gems $sp = (int) $gemCnd['value' . $i] > 1; $x .= '<span class="q0">' . Lang::achievement('reqNumCrt') . ' ' . sprintf(Lang::item('gemConditions', $gemCnd['comparator' . $i], $sp), $gemCnd['value' . $i], Lang::item('gemColors', $gemCnd['color' . $i] - 1)) . '</span><br />'; break; case 3: // requires more <color> than (<value> || <comparecolor>) gems $x .= '<span class="q0">' . Lang::achievement('reqNumCrt') . ' ' . sprintf(Lang::item('gemConditions', 3), Lang::item('gemColors', $gemCnd['color' . $i] - 1), Lang::item('gemColors', $gemCnd['cmpColor' . $i] - 1)) . '</span><br />'; break; } } } } } // Random Enchantment - if random enchantment is set, prepend stats from it if ($this->curTpl['randomEnchant'] && !isset($enhance['r'])) { $x .= '<span class="q2">' . Lang::item('randEnchant') . '</span><br />'; } else { if (isset($enhance['r'])) { $x .= $randEnchant; } } // itemMods (display stats and save ratings for later use) for ($j = 1; $j <= 10; $j++) { $type = $this->curTpl['statType' . $j]; $qty = $this->curTpl['statValue' . $j]; if (!$qty || $type <= 0) { continue; } // base stat if ($type >= ITEM_MOD_AGILITY && $type <= ITEM_MOD_STAMINA) { $x .= '<span><!--stat' . $type . '-->' . ($qty > 0 ? '+' : '-') . abs($qty) . ' ' . Lang::item('statType', $type) . '</span><br />'; } else { // rating with % for reqLevel $green[] = $this->parseRating($type, $qty, $interactive, $causesScaling); } } // magic resistances foreach (Util::$resistanceFields as $j => $rowName) { if ($rowName && $this->curTpl[$rowName] != 0) { $x .= '+' . $this->curTpl[$rowName] . ' ' . Lang::game('resistances', $j) . '<br />'; } } // Enchantment if (isset($enhance['e'])) { if ($enchText = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE Id = ?', $enhance['e'])) { $x .= '<span class="q2"><!--e-->' . Util::localizedString($enchText, 'name') . '</span><br />'; } else { unset($enhance['e']); $x .= '<!--e-->'; } } else { // enchantment placeholder $x .= '<!--e-->'; } // Sockets w/ Gems if (!empty($enhance['g'])) { $gems = DB::Aowow()->select(' SELECT it.id AS ARRAY_KEY, ic.iconString, ae.*, it.gemColorMask AS colorMask FROM ?_items it JOIN ?_itemenchantment ae ON ae.id = it.gemEnchantmentId JOIN ?_icons ic ON ic.id = -it.displayId WHERE it.id IN (?a)', $enhance['g']); foreach ($enhance['g'] as $k => $v) { if ($v && !in_array($v, array_keys($gems))) { // 0 is valid unset($enhance['g'][$k]); } } } else { $enhance['g'] = []; } // zero fill empty sockets $sockCount = isset($enhance['s']) ? 1 : 0; if (!empty($this->json[$this->id]['nsockets'])) { $sockCount += $this->json[$this->id]['nsockets']; } while ($sockCount > count($enhance['g'])) { $enhance['g'][] = 0; } $enhance['g'] = array_reverse($enhance['g']); $hasMatch = 1; // fill native sockets for ($j = 1; $j <= 3; $j++) { if (!$this->curTpl['socketColor' . $j]) { continue; } for ($i = 0; $i < 4; $i++) { if ($this->curTpl['socketColor' . $j] & 1 << $i) { $colorId = $i; } } $pop = array_pop($enhance['g']); $col = $pop ? 1 : 0; $hasMatch &= $pop ? $gems[$pop]['colorMask'] & 1 << $colorId ? 1 : 0 : 0; $icon = $pop ? sprintf(Util::$bgImagePath['tiny'], STATIC_URL, strtolower($gems[$pop]['iconString'])) : null; $text = $pop ? Util::localizedString($gems[$pop], 'name') : Lang::item('socket', $colorId); if ($interactive) { $x .= '<a href="?items=3&filter=cr=81;crs=' . ($colorId + 1) . ';crv=0" class="socket-' . Util::$sockets[$colorId] . ' q' . $col . '" ' . $icon . '>' . $text . '</a><br />'; } else { $x .= '<span class="socket-' . Util::$sockets[$colorId] . ' q' . $col . '" ' . $icon . '>' . $text . '</span><br />'; } } // fill extra socket if (isset($enhance['s'])) { $pop = array_pop($enhance['g']); $col = $pop ? 1 : 0; $icon = $pop ? sprintf(Util::$bgImagePath['tiny'], STATIC_URL, strtolower($gems[$pop]['iconString'])) : null; $text = $pop ? Util::localizedString($gems[$pop], 'name') : Lang::item('socket', -1); if ($interactive) { $x .= '<a href="?items=3&filter=cr=81;crs=5;crv=0" class="socket-prismatic q' . $col . '" ' . $icon . '>' . $text . '</a><br />'; } else { $x .= '<span class="socket-prismatic q' . $col . '" ' . $icon . '>' . $text . '</span><br />'; } } else { // prismatic socket placeholder $x .= '<!--ps-->'; } if ($_ = $this->curTpl['socketBonus']) { $sbonus = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE Id = ?d', $_); $x .= '<span class="q' . ($hasMatch ? '2' : '0') . '">' . Lang::item('socketBonus') . Lang::main('colon') . '<a href="?enchantment=' . $_ . '">' . Util::localizedString($sbonus, 'name') . '</a></span><br />'; } // durability if ($dur = $this->curTpl['durability']) { $x .= Lang::item('durability') . ' ' . $dur . ' / ' . $dur . '<br />'; } // required classes if ($classes = Lang::getClassString($this->curTpl['requiredClass'], $jsg, $__)) { 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 . '<br />'; } // required races if ($races = Lang::getRaceString($this->curTpl['requiredRace'], $__, $jsg, $__)) { 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 . '<br />'; } } // required honorRank (not used anymore) if ($rhr = $this->curTpl['requiredHonorRank']) { $x .= sprintf(Lang::game('requires'), Lang::game('pvpRank', $rhr)) . '<br />'; } // required CityRank..? // what the f.. // required level if ($_flags & ITEM_FLAG_ACCOUNTBOUND && $_quality == ITEM_QUALITY_HEIRLOOM) { $x .= sprintf(Lang::game('reqLevelHlm'), ' 1' . Lang::game('valueDelim') . MAX_LEVEL . ' (' . ($interactive ? sprintf(Util::$changeLevelString, MAX_LEVEL) : '<!--lvl-->' . MAX_LEVEL) . ')') . '<br />'; } else { if ($_reqLvl > 1) { $x .= sprintf(Lang::game('reqLevel'), $_reqLvl) . '<br />'; } } // required arena team rating / personal rating / todo (low): sort out what kind of rating if (!empty($this->getExtendedCost([], $reqRating)[$this->id]) && $reqRating) { $x .= sprintf(Lang::item('reqRating', $reqRating[1]), $reqRating[0]) . '<br />'; } // item level if (in_array($_class, [ITEM_CLASS_ARMOR, ITEM_CLASS_WEAPON])) { $x .= Lang::item('itemLevel') . ' ' . $this->curTpl['itemLevel'] . '<br />'; } // required skill if ($reqSkill = $this->curTpl['requiredSkill']) { $_ = '<a class="q1" href="?skill=' . $reqSkill . '">' . SkillList::getName($reqSkill) . '</a>'; if ($this->curTpl['requiredSkillRank'] > 0) { $_ .= ' (' . $this->curTpl['requiredSkillRank'] . ')'; } $x .= sprintf(Lang::game('requires'), $_) . '<br />'; } // required spell if ($reqSpell = $this->curTpl['requiredSpell']) { $x .= Lang::game('requires2') . ' <a class="q1" href="?spell=' . $reqSpell . '">' . SpellList::getName($reqSpell) . '</a><br />'; } // required reputation w/ faction if ($reqFac = $this->curTpl['requiredFaction']) { $x .= sprintf(Lang::game('requires'), '<a class="q1" href=?faction="' . $reqFac . '">' . FactionList::getName($reqFac) . '</a> - ' . Lang::game('rep', $this->curTpl['requiredFactionRank'])) . '<br />'; } // locked or openable if ($locks = Lang::getLocks($this->curTpl['lockId'], true)) { $x .= '<span class="q0">' . Lang::item('locked') . '<br />' . implode('<br />', $locks) . '</span><br />'; } else { if ($this->curTpl['flags'] & ITEM_FLAG_OPENABLE) { $x .= '<span class="q2">' . Lang::item('openClick') . '</span><br />'; } } // upper table: done if (!$subOf) { $x .= '</td></tr></table>'; } // spells on item if (!$this->canTeachSpell()) { $itemSpellsAndTrigger = []; for ($j = 1; $j <= 5; $j++) { if ($this->curTpl['spellId' . $j] > 0) { $cd = $this->curTpl['spellCooldown' . $j]; if ($cd < $this->curTpl['spellCategoryCooldown' . $j]) { $cd = $this->curTpl['spellCategoryCooldown' . $j]; } $cd = $cd < 5000 ? null : ' (' . sprintf(Lang::game('cooldown'), Util::formatTime($cd)) . ')'; $itemSpellsAndTrigger[$this->curTpl['spellId' . $j]] = [$this->curTpl['spellTrigger' . $j], $cd]; } } if ($itemSpellsAndTrigger) { $cooldown = ''; $itemSpells = new SpellList(array(['s.id', array_keys($itemSpellsAndTrigger)])); foreach ($itemSpells->iterate() as $__) { if ($parsed = $itemSpells->parseText('description', $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL, false, $causesScaling)[0]) { if ($interactive) { $link = '<a href="?spell=' . $itemSpells->id . '">%s</a>'; $parsed = preg_replace_callback('/([^;]*)( <small>.*?<\\/small>)([^&]*)/i', function ($m) use($link) { $m[1] = $m[1] ? sprintf($link, $m[1]) : ''; $m[3] = $m[3] ? sprintf($link, $m[3]) : ''; return $m[1] . $m[2] . $m[3]; }, $parsed, -1, $nMatches); if (!$nMatches) { $parsed = sprintf($link, $parsed); } } $green[] = Lang::item('trigger', $itemSpellsAndTrigger[$itemSpells->id][0]) . $parsed . $itemSpellsAndTrigger[$itemSpells->id][1]; } } } } // lower table (ratings, spells, ect) if (!$subOf) { $x .= '<table><tr><td>'; } if (isset($green)) { foreach ($green as $j => $bonus) { if ($bonus) { $x .= '<span class="q2">' . $bonus . '</span><br />'; } } } // Item Set $pieces = []; if ($setId = $this->getField('itemset')) { // while Ids can technically be used multiple times the only difference in data are the items used. So it doesn't matter what we get $itemset = new ItemsetList(array(['id', $setId])); if (!$itemset->error && $itemset->pieceToSet) { $pieces = DB::Aowow()->select(' SELECT b.id AS ARRAY_KEY, b.name_loc0, b.name_loc2, b.name_loc3, b.name_loc6, b.name_loc8, GROUP_CONCAT(a.id SEPARATOR \':\') AS equiv FROM ?_items a, ?_items b WHERE a.slotBak = b.slotBak AND a.itemset = b.itemset AND b.id IN (?a) GROUP BY b.id;', array_keys($itemset->pieceToSet)); foreach ($pieces as $k => &$p) { $p = '<span><!--si' . $p['equiv'] . '--><a href="?item=' . $k . '">' . Util::localizedString($p, 'name') . '</a></span>'; } $xSet = '<br /><span class="q"><a href="?itemset=' . $itemset->id . '" class="q">' . $itemset->getField('name', true) . '</a> (0/' . count($pieces) . ')</span>'; if ($skId = $itemset->getField('skillId')) { $xSet .= '<br />' . sprintf(Lang::game('requires'), '<a href="?skills=' . $skId . '" class="q1">' . SkillList::getName($skId) . '</a>'); if ($_ = $itemset->getField('skillLevel')) { $xSet .= ' (' . $_ . ')'; } $xSet .= '<br />'; } // list pieces $xSet .= '<div class="q0 indent">' . implode('<br />', $pieces) . '</div><br />'; // get bonuses $setSpellsAndIdx = []; for ($j = 1; $j <= 8; $j++) { if ($_ = $itemset->getField('spell' . $j)) { $setSpellsAndIdx[$_] = $j; } } $setSpells = []; if ($setSpellsAndIdx) { $boni = new SpellList(array(['s.id', array_keys($setSpellsAndIdx)])); foreach ($boni->iterate() as $__) { $setSpells[] = array('tooltip' => $boni->parseText('description', $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL, false, $causesScaling)[0], 'entry' => $itemset->getField('spell' . $setSpellsAndIdx[$boni->id]), 'bonus' => $itemset->getField('bonus' . $setSpellsAndIdx[$boni->id])); } } // sort and list bonuses $xSet .= '<span class="q0">'; for ($i = 0; $i < count($setSpells); $i++) { for ($j = $i; $j < count($setSpells); $j++) { if ($setSpells[$j]['bonus'] >= $setSpells[$i]['bonus']) { continue; } $tmp = $setSpells[$i]; $setSpells[$i] = $setSpells[$j]; $setSpells[$j] = $tmp; } $xSet .= '<span>(' . $setSpells[$i]['bonus'] . ') ' . Lang::item('set') . ': <a href="?spell=' . $setSpells[$i]['entry'] . '">' . $setSpells[$i]['tooltip'] . '</a></span>'; if ($i < count($setSpells) - 1) { $xSet .= '<br />'; } } $xSet .= '</span>'; } } // recipes, vanity pets, mounts if ($this->canTeachSpell()) { $craftSpell = new SpellList(array(['s.id', intVal($this->curTpl['spellId2'])])); if (!$craftSpell->error) { $xCraft = ''; if ($desc = $this->getField('description', true)) { $x .= '<span class="q2">' . Lang::item('trigger', 0) . ' <a href="?spell=' . $this->curTpl['spellId2'] . '">' . $desc . '</a></span><br />'; } // recipe handling (some stray Techniques have subclass == 0), place at bottom of tooltipp if ($_class == ITEM_CLASS_RECIPE || $this->curTpl['bagFamily'] == 16) { $craftItem = new ItemList(array(['i.id', (int) $craftSpell->curTpl['effect1CreateItemId']])); if (!$craftItem->error) { if ($itemTT = $craftItem->renderTooltip($interactive, $this->id)) { $xCraft .= '<div><br />' . $itemTT . '</div>'; } $reagentItems = []; for ($i = 1; $i <= 8; $i++) { if ($rId = $craftSpell->getField('reagent' . $i)) { $reagentItems[$rId] = $craftSpell->getField('reagentCount' . $i); } } if (isset($xCraft) && $reagentItems) { $reagents = new ItemList(array(['i.id', array_keys($reagentItems)])); $reqReag = []; foreach ($reagents->iterate() as $__) { $reqReag[] = '<a href="?item=' . $reagents->id . '">' . $reagents->getField('name', true) . '</a> (' . $reagentItems[$reagents->id] . ')'; } $xCraft .= '<div class="q1 whtt-reagents"><br />' . Lang::game('requires2') . ' ' . implode(', ', $reqReag) . '</div>'; } } } } } // misc (no idea, how to organize the <br /> better) $xMisc = []; // itemset: pieces and boni if (isset($xSet)) { $xMisc[] = $xSet; } // funny, yellow text at the bottom, omit if we have a recipe if ($this->curTpl['description_loc0'] && !$this->canTeachSpell()) { $xMisc[] = '<span class="q">"' . $this->getField('description', true) . '"</span>'; } // readable if ($this->curTpl['pageTextId']) { $xMisc[] = '<span class="q2">' . Lang::item('readClick') . '</span>'; } // charges (i guess checking first spell is enough (single charges not shown)) if ($this->curTpl['spellCharges1'] > 1 || $this->curTpl['spellCharges1'] < -1) { $xMisc[] = '<span class="q1">' . abs($this->curTpl['spellCharges1']) . ' ' . Lang::item('charges') . '</span>'; } // list required reagents if (isset($xCraft)) { $xMisc[] = $xCraft; } if ($xMisc) { $x .= implode('<br />', $xMisc); } if ($sp = $this->curTpl['sellPrice']) { $x .= '<div class="q1 whtt-sellprice">' . Lang::item('sellPrice') . Lang::main('colon') . Util::formatMoney($sp) . '</div>'; } if (!$subOf) { $x .= '</td></tr></table>'; } // tooltip scaling if (!isset($xCraft)) { $link = [$subOf ? $subOf : $this->id, 1]; // itemId, scaleMinLevel if (isset($this->ssd[$this->id])) { array_push($link, $this->ssd[$this->id]['maxLevel'], $this->ssd[$this->id]['maxLevel'], $this->curTpl['scalingStatDistribution'], $this->curTpl['scalingStatValue']); } else { array_push($link, $causesScaling ? MAX_LEVEL : 1, $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL); } $x .= '<!--?' . implode(':', $link) . '-->'; } return $x; }
protected function generateContent() { $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']); $_cat = $this->subject->getField('typeCat'); $redButtons = array(BUTTON_LINKS => ['color' => 'ff71d5ff', 'linkId' => Util::$typeStrings[TYPE_SPELL] . ':' . $this->typeId], BUTTON_VIEW3D => false, BUTTON_WOWHEAD => true); /***********/ /* Infobox */ /***********/ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); // level if (!in_array($_cat, [-5, -6])) { if ($_ = $this->subject->getField('talentLevel')) { $infobox[] = in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::game('reqLevel'), $_) : Lang::game('level') . Lang::main('colon') . $_; } else { if ($_ = $this->subject->getField('spellLevel')) { $infobox[] = in_array($_cat, [-2, 7, -13]) ? sprintf(Lang::game('reqLevel'), $_) : Lang::game('level') . Lang::main('colon') . $_; } } } // races if ($_ = Lang::getRaceString($this->subject->getField('reqRaceMask'), $__, $jsg, $n, false)) { if ($_ != Lang::game('ra', 0)) { $this->extendGlobalIds(TYPE_RACE, $jsg); $t = $n == 1 ? Lang::game('race') : Lang::game('races'); $infobox[] = Util::ucFirst($t) . Lang::main('colon') . $_; } } // 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[] = Util::ucFirst($t) . Lang::main('colon') . $_; } // spell focus if ($_ = $this->subject->getField('spellFocusObject')) { $bar = DB::Aowow()->selectRow('SELECT * FROM ?_spellfocusobject WHERE id = ?d', $_); $focus = new GameObjectList(array(['spellFocusId', $_], 1)); $infobox[] = Lang::game('requires2') . ' ' . ($focus->error ? Util::localizedString($bar, 'name') : '[url=?object=' . $focus->id . ']' . Util::localizedString($bar, 'name') . '[/url]'); } // 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[] = $bar; } } // specialization if ($_ = $this->subject->getField('reqSpellId')) { $rSpell = new SpellList(array(['id', $_])); if (!$rSpell->error) { $this->extendGlobalData($rSpell->getJSGlobals()); $infobox[] = 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[] = Lang::game('difficulty') . Lang::main('colon') . implode(' ', $bar); } } // accquisition.. 10: starter spell; 7: discovery if (isset($this->subject->sources[$this->subject->id][10])) { $infobox[] = Lang::spell('starter'); } else { if (isset($this->subject->sources[$this->subject->id][7])) { $infobox[] = Lang::spell('discovered'); } } // training cost if ($cost = $this->subject->getField('trainingCost')) { $infobox[] = 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[] = 'Mode' . Lang::main('colon') . Lang::game('modes', $n); } } $effects = $this->createEffects($infobox, $redButtons); // spell script if (User::isInGroup(U_GROUP_STAFF)) { if ($_ = DB::World()->selectCell('SELECT ScriptName FROM spell_script_names WHERE ABS(spell_id) = ?d', $this->firstRank)) { $infobox[] = 'Script' . Lang::main('colon') . $_; } } $infobox = $infobox ? '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]' : ''; // append glyph symbol if available $glyphId = 0; for ($i = 1; $i < 4; $i++) { if ($this->subject->getField('effect' . $i . 'Id') == 74) { $glyphId = $this->subject->getField('effect' . $i . 'MiscValue'); } } if ($_ = DB::Aowow()->selectCell('SELECT si.iconString FROM ?_glyphproperties gp JOIN ?_icons si ON gp.iconId = si.id WHERE gp.spellId = ?d { OR gp.id = ?d }', $this->typeId, $glyphId ?: DBSIMPLE_SKIP)) { if (file_exists('static/images/wow/Interface/Spellbook/' . $_ . '.png')) { $infobox .= '[img src=' . STATIC_URL . '/images/wow/Interface/Spellbook/' . $_ . '.png border=0 float=center margin=15]'; } } /****************/ /* Main Content */ /****************/ $this->reagents = $this->createReagentList(); $this->scaling = $this->createScalingData(); $this->items = $this->createRequiredItems(); $this->tools = $this->createTools(); $this->effects = $effects; $this->infobox = $infobox; $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 = $this->subject->getField('dispelType') ? Lang::game('dt', $this->subject->getField('dispelType')) : null; $this->mechanic = $this->subject->getField('mechanic') ? Lang::game('me', $this->subject->getField('mechanic')) : null; $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 if ($pendant = DB::World()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_spells WHERE alliance_id = ?d OR horde_id = ?d', $this->typeId, $this->typeId, $this->typeId)) { $altSpell = new SpellList(array(['id', abs($pendant)])); if (!$altSpell->error) { $this->transfer = sprintf(Lang::spell('_transfer'), $altSpell->id, 1, $altSpell->getField('iconString'), $altSpell->getField('name', true), $pendant > 0 ? 'alliance' : 'horde', $pendant > 0 ? Lang::game('si', 1) : Lang::game('si', 2)); } } /**************/ /* Extra Tabs */ /**************/ $j = [null, 'A', 'B', 'C']; // tab: abilities [of shapeshift form] for ($i = 1; $i < 4; $i++) { if ($this->subject->getField('effect' . $i . 'AuraId') != 36) { continue; } $formSpells = DB::Aowow()->selectRow('SELECT spellId1, spellId2, spellId3, spellId4, spellId5, spellId6, spellId7, spellId8 FROM ?_shapeshiftforms WHERE id = ?d', $this->subject->getField('effect' . $i . 'MiscValue')); if (!$formSpells) { continue; } $abilities = new SpellList(array(['id', $formSpells])); if (!$abilities->error) { if (!$abilities->hasSetFields(['skillLines'])) { $abH = "\$['skill']"; } $this->lvTabs[] = array('file' => 'spell', 'data' => $abilities->getListviewData(), 'params' => array('id' => 'controlledabilities', 'name' => '$LANG.tab_controlledabilities', 'visibleCols' => "\$['level']", 'hiddenCols' => isset($abH) ? $abH : null)); $this->extendGlobalData($abilities->getJSGlobals(GLOBALINFO_SELF)); } } // tab: modifies $this $sub = ['OR']; $conditions = [['s.typeCat', [0, -9, -8], '!'], ['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, 286])) { 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->lvTabs[] = array('file' => 'spell', 'data' => $modSpells->getListviewData(), 'params' => array('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, 286]], ['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->lvTabs[] = array('file' => 'spell', 'data' => $modsSpell->getListviewData(), 'params' => array('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) { $saE = '$[Listview.extraCols.mode]'; foreach ($data as $id => &$d) { $d['modes'] = ['mode' => 0]; if ($this->difficulties[0] == $id) { if (!$this->difficulties[2] && !$this->difficulties[3]) { $d['modes']['mode'] |= 0x2; } else { $d['modes']['mode'] |= 0x8; } } if ($this->difficulties[1] == $id) { 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->lvTabs[] = array('file' => 'spell', 'data' => $data, 'params' => array('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->lvTabs[] = array('file' => 'itemset', 'data' => $ubSets->getListviewData(), 'params' => array('id' => 'used-by-itemset', 'name' => '$LANG.tab_usedby')); $this->extendGlobalData($ubSets->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); } // tab: used by - item $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]]); $ubItems = new ItemList($conditions); if (!$ubItems->error) { $this->lvTabs[] = array('file' => 'item', 'data' => $ubItems->getListviewData(), 'params' => array('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->lvTabs[] = array('file' => 'object', 'data' => $ubObjects->getListviewData(), 'params' => array('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->lvTabs[] = array('file' => 'achievement', 'data' => $coAchievemnts->getListviewData(), 'params' => array('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::World()->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) { $this->extendGlobalData($spellLoot->jsGlobals); $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'][0][$this->typeId][] = [[CND_SPELL, $extraItem['requiredSpecialization']]]; $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->lvTabs[] = array('file' => 'item', 'data' => $lv, 'params' => array('name' => '$LANG.tab_contains', 'id' => 'contains', 'hiddenCols' => "\$['side', 'slot', 'source', 'reqlevel']", 'extraCols' => '$[' . implode(', ', $extraCols) . ']')); } // tab: exclusive with if ($this->firstRank) { $linkedSpells = DB::World()->selectCol('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::World()->selectCol('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->lvTabs[] = array('file' => 'spell', 'data' => $data, 'params' => array('id' => 'spell-group-stack', 'name' => 'Stack Group', 'visibleCols' => "\$['stackRules']", 'hiddenCols' => isset($sH) ? $sH : null)); $this->extendGlobalData($stacks->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); } } } // tab: linked with $rows = DB::World()->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->lvTabs[] = array('file' => 'spell', 'data' => $data, 'params' => array('id' => 'spell-link', 'name' => 'Linked with', '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->lvTabs[] = array('file' => 'spell', 'data' => $trigger->getListviewData(), 'params' => array('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::World()->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->lvTabs[] = array('file' => 'creature', 'data' => $ubCreature->getListviewData(), 'params' => array('id' => 'used-by-npc', 'name' => '$LANG.tab_usedby')); $this->extendGlobalData($ubCreature->getJSGlobals(GLOBALINFO_SELF)); } // tab: zone if ($areas = DB::World()->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 = []; $extra = false; foreach ($areas as $a) { if (empty($lvZones[$a['area']])) { continue; } $condition = []; if ($a['aura_spell']) { $this->extendGlobalIds(TYPE_SPELL, abs($a['aura_spell'])); $condition[0][$this->typeId][] = [[$a['aura_spell'] > 0 ? CND_AURA : -CND_AURA, abs($a['aura_spell'])]]; } if ($a['quest_start']) { $this->extendGlobalIds(TYPE_QUEST, $a['quest_start']); $group = []; for ($i = 0; $i < 7; $i++) { if (!($a['quest_start_status'] & 1 << $i)) { continue; } if ($i == 0) { $group[] = [CND_QUEST_NONE, $a['quest_start']]; } else { if ($i == 1) { $group[] = [CND_QUEST_COMPLETE, $a['quest_start']]; } else { if ($i == 3) { $group[] = [CND_QUESTTAKEN, $a['quest_start']]; } else { if ($i == 6) { $group[] = [CND_QUESTREWARDED, $a['quest_start']]; } } } } } if ($group) { $condition[0][$this->typeId][] = $group; } } if ($a['quest_end'] && $a['quest_end'] != $a['quest_start']) { $this->extendGlobalIds(TYPE_QUEST, $a['quest_end']); $group = []; for ($i = 0; $i < 7; $i++) { if (!($a['quest_end_status'] & 1 << $i)) { continue; } if ($i == 0) { $group[] = [-CND_QUEST_NONE, $a['quest_end']]; } else { if ($i == 1) { $group[] = [-CND_QUEST_COMPLETE, $a['quest_end']]; } else { if ($i == 3) { $group[] = [-CND_QUESTTAKEN, $a['quest_end']]; } else { if ($i == 6) { $group[] = [-CND_QUESTREWARDED, $a['quest_end']]; } } } } } if ($group) { $condition[0][$this->typeId][] = $group; } } if ($a['racemask']) { $foo = []; for ($i = 0; $i < 11; $i++) { if ($a['racemask'] & 1 << $i) { $foo[] = $i + 1; } } $this->extendGlobalIds(TYPE_RACE, $foo); $condition[0][$this->typeId][] = [[CND_RACE, $a['racemask']]]; } if ($a['gender'] != 2) { // 2: both $condition[0][$this->typeId][] = [[CND_GENDER, $a['gender'] + 1]]; } $row = $lvZones[$a['area']]; if ($condition) { $extra = true; $row = array_merge($row, ['condition' => $condition]); } // 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['parentArea'] != $row['parentArea'] && $v['id'] != $row['parentArea']) { continue; } if (empty($v['condition']) xor empty($row['condition'])) { continue; } if (!empty($row['condition']) && !empty($v['condition']) && $v['condition'] != $row['condition']) { 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->lvTabs[] = array('file' => 'zone', 'data' => $lv, 'params' => array('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->lvTabs[] = array('file' => 'spell', 'data' => $teaches->getListviewData(), 'params' => array('id' => 'teaches-spell', 'name' => '$LANG.tab_teaches', 'visibleCols' => '$' . Util::toJSON($vis), 'hiddenCols' => $hid ? '$' . Util::toJSON($hid) : null)); } } // tab: taught by npc (source:6 => trainer) if (!empty($this->subject->sources[$this->typeId][6])) { $src = $this->subject->sources[$this->typeId][6]; $list = []; if (count($src) == 1 && $src[0] == 1) { $tt = null; // Professions if (in_array($_cat, [9, 11]) && isset(Util::$trainerTemplates[TYPE_SKILL][$this->subject->getField('skillLines')[0]])) { $tt = Util::$trainerTemplates[TYPE_SKILL][$this->subject->getField('skillLines')[0]]; } 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 if (isset(Util::$trainerTemplates[TYPE_CLASS][$clId])) { $tt = Util::$trainerTemplates[TYPE_CLASS][$clId]; } } } } if ($tt) { $list = DB::World()->selectCol('SELECT DISTINCT ID FROM npc_trainer WHERE SpellID IN (?a) AND ID < 200000', $tt); } else { $mask = 0; foreach (Util::$skillLineMask[-3] as $idx => $pair) { if ($pair[1] == $this->typeId) { $mask |= 1 << $idx; } } $list = DB::World()->selectCol(' SELECT IF(t1.ID > 200000, t2.ID, t1.ID) FROM npc_trainer t1 LEFT JOIN npc_trainer t2 ON t2.SpellID = -t1.ID WHERE t1.SpellID = ?d', $this->typeId); } } else { if ($src) { $list = array_values($src); } } if ($list) { $tbTrainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['s.guid', NULL, '!'], ['ct.npcflag', 0x10, '&'])); if (!$tbTrainer->error) { $this->extendGlobalData($tbTrainer->getJSGlobals()); $this->lvTabs[] = array('file' => 'creature', 'data' => $tbTrainer->getListviewData(), 'params' => array('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->lvTabs[] = array('file' => 'spell', 'data' => $tbsData, 'params' => array('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->lvTabs[] = array('file' => 'quest', 'data' => $tbQuest->getListviewData(), 'params' => array('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->lvTabs[] = array('file' => 'item', 'data' => $tbItem->getListviewData(), 'params' => array('id' => 'taught-by-item', 'name' => '$LANG.tab_taughtby')); $this->extendGlobalData($tbItem->getJSGlobals(GLOBALINFO_SELF)); } // tab: enchantments $conditions = array('OR', ['AND', ['type1', [1, 3, 7]], ['object1', $this->typeId]], ['AND', ['type2', [1, 3, 7]], ['object2', $this->typeId]], ['AND', ['type3', [1, 3, 7]], ['object3', $this->typeId]]); $enchList = new EnchantmentList($conditions); if (!$enchList->error) { $this->lvTabs[] = array('file' => 'enchantment', 'data' => $enchList->getListviewData(), 'params' => []); $this->extendGlobalData($enchList->getJSGlobals()); } // 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 // tab: conditions $sc = Util::getServerConditions([CND_SRC_SPELL_LOOT_TEMPLATE, CND_SRC_SPELL_IMPLICIT_TARGET, CND_SRC_SPELL, CND_SRC_SPELL_CLICK_EVENT, CND_SRC_VEHICLE_SPELL, CND_SRC_SPELL_PROC], null, $this->typeId); if (!empty($sc[0])) { $this->extendGlobalData($sc[1]); $tab = "<script type=\"text/javascript\">\n" . "var markup = ConditionList.createTab(" . Util::toJSON($sc[0]) . ");\n" . "Markup.printHtml(markup, 'tab-conditions', { allow: Markup.CLASS_STAFF })" . "</script>"; $this->lvTabs[] = array('file' => null, 'data' => $tab, 'params' => array('id' => 'conditions', 'name' => '$LANG.requires')); } }
protected function generateContent() { /****************/ /* Main Content */ /****************/ $this->headIcons = [$this->subject->getField('iconString')]; $this->redButtons = array(BUTTON_WOWHEAD => true, BUTTON_LINKS => true); if ($_ = $this->subject->getField('description', true)) { $this->extraText = $_; } /**************/ /* Extra Tabs */ /**************/ if (in_array($this->cat, [-5, 9, 11])) { // tab: recipes [spells] (crafted) $condition = array(['OR', ['s.reagent1', 0, '>'], ['s.reagent2', 0, '>'], ['s.reagent3', 0, '>'], ['s.reagent4', 0, '>'], ['s.reagent5', 0, '>'], ['s.reagent6', 0, '>'], ['s.reagent7', 0, '>'], ['s.reagent8', 0, '>']], ['OR', ['s.skillLine1', $this->typeId], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->typeId]]], CFG_SQL_LIMIT_NONE); $recipes = new SpellList($condition); // also relevant for 3 if (!$recipes->error) { $this->extendGlobalData($recipes->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); $this->lvTabs[] = array('file' => 'spell', 'data' => $recipes->getListviewData(), 'params' => array('id' => 'recipes', 'name' => '$LANG.tab_recipes', 'visibleCols' => "\$['reagents', 'source']", 'note' => sprintf(Util::$filterResultString, '?spells=' . $this->cat . '.' . $this->typeId . '&filter=cr=20;crs=1;crv=0'))); } // tab: recipe Items [items] (Books) $filterRecipe = [null, 165, 197, 202, 164, 185, 171, 129, 333, 356, 755, 773, 186, 182]; $conditions = array(['requiredSkill', $this->typeId], ['class', ITEM_CLASS_RECIPE], CFG_SQL_LIMIT_NONE); $recipeItems = new ItemList($conditions); if (!$recipeItems->error) { $this->extendGlobalData($recipeItems->getJSGlobals(GLOBALINFO_SELF)); if ($_ = array_search($this->typeId, $filterRecipe)) { $_ = sprintf(Util::$filterResultString, "?items=9." . $_); } $this->lvTabs[] = array('file' => 'item', 'data' => $recipeItems->getListviewData(), 'params' => array('id' => 'recipe-items', 'name' => '$LANG.tab_recipeitems', 'note' => $_)); } // tab: crafted items [items] $filterItem = [null, 171, 164, 185, 333, 202, 129, 755, 165, 186, 197, null, null, 356, 182, 773]; $created = []; foreach ($recipes->iterate() as $__) { if ($idx = $recipes->canCreateItem()) { foreach ($idx as $i) { $created[] = $recipes->getField('effect' . $i . 'CreateItemId'); } } } if ($created) { $created = new ItemList(array(['i.id', $created], CFG_SQL_LIMIT_NONE)); if (!$created->error) { $this->extendGlobalData($created->getJSGlobals(GLOBALINFO_SELF)); if ($_ = array_search($this->typeId, $filterItem)) { $_ = sprintf(Util::$filterResultString, "?items&filter=cr=86;crs=" . $_ . ";crv=0"); } $this->lvTabs[] = array('file' => 'item', 'data' => $created->getListviewData(), 'params' => array('id' => 'crafted-items', 'name' => '$LANG.tab_crafteditems', 'note' => $_)); } } // tab: required by [item] $conditions = array(['requiredSkill', $this->typeId], ['class', ITEM_CLASS_RECIPE, '!'], CFG_SQL_LIMIT_NONE); $reqBy = new ItemList($conditions); if (!$reqBy->error) { $this->extendGlobalData($reqBy->getJSGlobals(GLOBALINFO_SELF)); if ($_ = array_search($this->typeId, $filterItem)) { $_ = sprintf(Util::$filterResultString, "?items&filter=cr=99:168;crs=" . $_ . ":2;crv=0:0"); } $this->lvTabs[] = array('file' => 'item', 'data' => $reqBy->getListviewData(), 'params' => array('id' => 'required-by', 'name' => '$LANG.tab_requiredby', 'note' => $_)); } // tab: required by [itemset] $conditions = array(['skillId', $this->typeId], CFG_SQL_LIMIT_NONE); $reqBy = new ItemsetList($conditions); if (!$reqBy->error) { $this->extendGlobalData($reqBy->getJSGlobals(GLOBALINFO_SELF)); $this->lvTabs[] = array('file' => 'itemset', 'data' => $reqBy->getListviewData(), 'params' => array('id' => 'required-by-set', 'name' => '$LANG.tab_requiredby')); } } // tab: spells [spells] (exclude first tab) $reqClass = 0x0; $reqRace = 0x0; $condition = array(['AND', ['s.reagent1', 0], ['s.reagent2', 0], ['s.reagent3', 0], ['s.reagent4', 0], ['s.reagent5', 0], ['s.reagent6', 0], ['s.reagent7', 0], ['s.reagent8', 0]], ['OR', ['s.skillLine1', $this->typeId], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->typeId]]], CFG_SQL_LIMIT_NONE); foreach (Util::$skillLineMask as $line1 => $sets) { foreach ($sets as $idx => $set) { if ($set[1] == $this->typeId) { $condition[1][] = array('AND', ['s.skillLine1', $line1], ['s.skillLine2OrMask', 1 << $idx, '&']); break 2; } } } $spells = new SpellList($condition); if (!$spells->error) { foreach ($spells->iterate() as $__) { $reqClass |= $spells->getField('reqClassMask'); $reqRace |= $spells->getField('reqRaceMask'); } $this->extendGlobalData($spells->getJSGlobals(GLOBALINFO_SELF)); $lv = array('file' => 'spell', 'data' => $spells->getListviewData(), 'params' => ['visibleCols' => "\$['source']"]); switch ($this->cat) { case -4: $lv['params']['note'] = sprintf(Util::$filterResultString, '?spells=-4'); break; case 7: if ($this->typeId != 769) { // Internal $lv['params']['note'] = sprintf(Util::$filterResultString, '?spells=' . $this->cat . '.' . (log($reqClass, 2) + 1) . '.' . $this->typeId); } // doesn't matter what spell; reqClass should be identical for all Class Spells break; case 9: case 11: $lv['params']['note'] = sprintf(Util::$filterResultString, '?spells=' . $this->cat . '.' . $this->typeId); break; } $this->lvTabs[] = $lv; } // tab: trainers [npcs] if (in_array($this->cat, [-5, 6, 7, 8, 9, 11])) { $list = []; if (!empty(Util::$trainerTemplates[TYPE_SKILL][$this->typeId])) { $list = DB::World()->selectCol('SELECT DISTINCT entry FROM npc_trainer WHERE spell IN (?a) AND entry < 200000', Util::$trainerTemplates[TYPE_SKILL][$this->typeId]); } else { $mask = 0; foreach (Util::$skillLineMask[-3] as $idx => $pair) { if ($pair[1] == $this->typeId) { $mask |= 1 << $idx; } } $spellIds = DB::Aowow()->selectCol('SELECT id FROM ?_spell WHERE typeCat IN (-11, 9) AND (skillLine1 = ?d OR (skillLine1 > 0 AND skillLine2OrMask = ?d) {OR (skillLine1 = -3 AND skillLine2OrMask = ?d)})', $this->typeId, $this->typeId, $mask ?: DBSIMPLE_SKIP); $list = $spellIds ? DB::World()->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 IN (?a)', $spellIds) : []; } if ($list) { $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']); $trainer = new CreatureList(array(CFG_SQL_LIMIT_NONE, ['ct.id', $list], ['s.guid', NULL, '!'], ['ct.npcflag', 0x10, '&'])); if (!$trainer->error) { $this->extendGlobalData($trainer->getJSGlobals()); $this->lvTabs[] = array('file' => 'creature', 'data' => $trainer->getListviewData(), 'params' => array('id' => 'trainer', 'name' => '$LANG.tab_trainers')); } } } // tab: quests [quests] if (in_array($this->cat, [9, 11])) { $sort = 0; switch ($this->typeId) { case 182: $sort = 24; break; // Herbalism // Herbalism case 356: $sort = 101; break; // Fishing // Fishing case 164: $sort = 121; break; // Blacksmithing // Blacksmithing case 171: $sort = 181; break; // Alchemy // Alchemy case 165: $sort = 182; break; // Leatherworking // Leatherworking case 202: $sort = 201; break; // Engineering // Engineering case 197: $sort = 264; break; // Tailoring // Tailoring case 185: $sort = 304; break; // Cooking // Cooking case 129: $sort = 324; break; // First Aid // First Aid case 773: $sort = 371; break; // Inscription // Inscription case 755: $sort = 373; break; // Jewelcrafting } if ($sort) { $quests = new QuestList(array(['zoneOrSort', -$sort], CFG_SQL_LIMIT_NONE)); if (!$quests->error) { $this->extendGlobalData($quests->getJSGlobals()); $this->lvTabs[] = array('file' => 'quest', 'data' => $quests->getListviewData(), 'params' => []); } } } // tab: related classes (apply classes from [spells]) $class = []; for ($i = 0; $i < 11; $i++) { if ($reqClass & 1 << $i) { $class[] = $i + 1; } } if ($class) { $classes = new CharClassList(array(['id', $class])); if (!$classes->error) { $this->lvTabs[] = array('file' => 'class', 'data' => $classes->getListviewData(), 'params' => []); } } // tab: related races (apply races from [spells]) $race = []; for ($i = 0; $i < 12; $i++) { if ($reqRace & 1 << $i) { $race[] = $i + 1; } } if ($race) { $races = new CharRaceList(array(['id', $race])); if (!$races->error) { $this->lvTabs[] = array('file' => 'race', 'data' => $races->getListviewData(), 'params' => []); } } }
protected function generateContent() { $_ta = $this->subject->getField('contentGroup'); $_ty = $this->subject->getField('type'); $_cnt = count($this->subject->getField('pieces')); /***********/ /* Infobox */ /***********/ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); // unavailable (todo (low): set data) if ($this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE) { $infobox[] = Lang::main('unavailable'); } // worldevent if ($e = $this->subject->getField('eventId')) { $infobox[] = Lang::game('eventShort') . Lang::main('colon') . '[event=' . $e . ']'; $this->extendGlobalIds(TYPE_WORLDEVENT, $e); } // itemLevel if ($min = $this->subject->getField('minLevel')) { $foo = Lang::game('level') . Lang::main('colon') . $min; $max = $this->subject->getField('maxLevel'); if ($min < $max) { $foo .= ' - ' . $max; } $infobox[] = $foo; } // class if ($cl = Lang::getClassString($this->subject->getField('classMask'), $jsg, $qty, false)) { $this->extendGlobalIds(TYPE_CLASS, $jsg); $t = $qty == 1 ? Lang::game('class') : Lang::game('classes'); $infobox[] = Util::ucFirst($t) . Lang::main('colon') . $cl; } // required level if ($lvl = $this->subject->getField('reqLevel')) { $infobox[] = sprintf(Lang::game('reqLevel'), $lvl); } // type if ($_ty) { $infobox[] = Lang::game('type') . Lang::main('colon') . Lang::itemset('types', $_ty); } // tag if ($_ta) { $infobox[] = Lang::itemset('_tag') . Lang::main('colon') . '[url=?itemsets&filter=ta=' . $_ta . ']' . Lang::itemset('notes', $_ta) . '[/url]'; } /****************/ /* Main Content */ /****************/ // pieces + Summary $pieces = []; $eqList = []; $compare = []; if (!$this->subject->pieceToSet) { $cnd = [0]; } else { $cnd = ['i.id', array_keys($this->subject->pieceToSet)]; } $iList = new ItemList(array($cnd)); $data = $iList->getListviewData(ITEMINFO_SUBITEMS | ITEMINFO_JSON); foreach ($iList->iterate() as $itemId => $__) { if (empty($data[$itemId])) { continue; } $slot = $iList->getField('slot'); $disp = $iList->getField('displayId'); if ($slot && $disp) { $eqList[] = [$slot, $disp]; } $compare[] = $itemId; $pieces[] = array('id' => $itemId, 'name' => $iList->getField('name', true), 'quality' => $iList->getField('quality'), 'icon' => $iList->getField('iconString'), 'json' => $data[$itemId]); } $skill = ''; if ($_sk = $this->subject->getField('skillId')) { $spellLink = sprintf('<a href="?spells=11.%s">%s</a> (%s)', $_sk, Lang::spell('cat', 11, $_sk, 0), $this->subject->getField('skillLevel')); $skill = ' – <small><b>' . sprintf(Lang::game('requires'), $spellLink) . '</b></small>'; } $this->bonusExt = $skill; $this->description = $_ta ? sprintf(Lang::itemset('_desc'), $this->name, Lang::itemset('notes', $_ta), $_cnt) : sprintf(Lang::itemset('_descTagless'), $this->name, $_cnt); $this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE; $this->infobox = $infobox ? '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]' : null; $this->pieces = $pieces; $this->spells = $this->subject->getBonuses(); $this->expansion = 0; $this->redButtons = array(BUTTON_WOWHEAD => $this->typeId > 0, BUTTON_LINKS => ['color' => '', 'linkId' => ''], BUTTON_VIEW3D => ['type' => TYPE_ITEMSET, 'typeId' => $this->typeId, 'equipList' => $eqList], BUTTON_COMPARE => ['eqList' => implode(':', $compare), 'qty' => $_cnt]); $this->compare = array('level' => $this->subject->getField('reqLevel'), 'items' => array_map(function ($v) { return [[$v]]; }, $compare)); /**************/ /* Extra Tabs */ /**************/ // related sets (priority: 1: similar tag + class; 2: has event; 3: no tag + similar type, 4: similar type + profession) $rel = []; if ($_ta && count($this->path) == 3) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['classMask', 1 << end($this->path) - 1, '&']; $rel[] = ['contentGroup', (int) $_ta]; } else { if ($this->subject->getField('eventId')) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['eventId', 0, '!']; } else { if ($this->subject->getField('skillId')) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['contentGroup', 0]; $rel[] = ['skillId', 0, '!']; $rel[] = ['type', $_ty]; } else { if (!$_ta && $_ty) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['contentGroup', 0]; $rel[] = ['type', $_ty]; $rel[] = ['skillId', 0]; } } } } if ($rel) { $relSets = new ItemsetList($rel); if (!$relSets->error) { $lv = array('file' => 'itemset', 'data' => $relSets->getListviewData(), 'params' => array('id' => 'see-also', 'name' => '$LANG.tab_seealso')); if (!$relSets->hasDiffFields(['classMask'])) { $lv['params']['hiddenCols'] = "\$['classes']"; } $this->lvTabs[] = $lv; $this->extendGlobalData($relSets->getJSGlobals()); } } }
protected function generateContent() { $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']); $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); $_mask = 1 << $this->typeId - 1; $tcClassId = [null, 8, 3, 1, 5, 4, 9, 6, 2, 7, null, 0]; // see TalentCalc.js /***********/ /* Infobox */ /***********/ // hero class if ($this->subject->getField('flags') & 0x40) { $infobox[] = '[tooltip=tooltip_heroclass]' . Lang::game('heroClass') . '[/tooltip]'; } // resource if ($this->typeId == 11) { // special Druid case $infobox[] = Lang::game('resources') . Lang::main('colon') . '[tooltip name=powertype1]' . Lang::game('st', 0) . ', ' . Lang::game('st', 31) . ', ' . Lang::game('st', 2) . '[/tooltip][span class=tip tooltip=powertype1]' . Util::ucFirst(Lang::spell('powerTypes', 0)) . '[/span], ' . '[tooltip name=powertype2]' . Lang::game('st', 5) . ', ' . Lang::game('st', 8) . '[/tooltip][span class=tip tooltip=powertype2]' . Util::ucFirst(Lang::spell('powerTypes', 1)) . '[/span], ' . '[tooltip name=powertype8]' . Lang::game('st', 1) . '[/tooltip][span class=tip tooltip=powertype8]' . Util::ucFirst(Lang::spell('powerTypes', 3)) . '[/span]'; } else { if ($this->typeId == 6) { // special DK case $infobox[] = Lang::game('resources') . Lang::main('colon') . '[span]' . Util::ucFirst(Lang::spell('powerTypes', 5)) . ', ' . Util::ucFirst(Lang::spell('powerTypes', $this->subject->getField('powerType'))) . '[/span]'; } else { // regular case $infobox[] = Lang::game('resource') . Lang::main('colon') . '[span]' . Util::ucFirst(Lang::spell('powerTypes', $this->subject->getField('powerType'))) . '[/span]'; } } // roles $roles = []; for ($i = 0; $i < 4; $i++) { if ($this->subject->getField('roles') & 1 << $i) { $roles[] = (count($roles) == 2 ? "\n" : '') . Lang::game('_roles', $i); } } if ($roles) { $infobox[] = (count($roles) > 1 ? Lang::game('roles') : Lang::game('role')) . Lang::main('colon') . implode(', ', $roles); } // specs $specList = []; $skills = new SkillList(array(['id', $this->subject->getField('skills')])); foreach ($skills->iterate() as $k => $__) { $specList[$k] = '[icon name=' . $skills->getField('iconString') . '][url=?spells=7.' . $this->typeId . '.' . $k . ']' . $skills->getField('name', true) . '[/url][/icon]'; } if ($specList) { $infobox[] = Lang::game('specs') . Lang::main('colon') . '[ul][li]' . implode('[/li][li]', $specList) . '[/li][/ul]'; } /****************/ /* Main Content */ /****************/ $this->infobox = '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]'; $this->expansion = Util::$expansionString[$this->subject->getField('expansion')]; $this->headIcons = ['class_' . strtolower($this->subject->getField('fileString'))]; $this->redButtons = array(BUTTON_LINKS => ['color' => '', 'linkId' => ''], BUTTON_WOWHEAD => true, BUTTON_TALENT => ['href' => '?talent#' . Util::$tcEncoding[$tcClassId[$this->typeId] * 3], 'pet' => false], BUTTON_FORUM => false); /**************/ /* Extra Tabs */ /**************/ // Tab: Spells (grouped) // '$LANG.tab_armorproficiencies', // '$LANG.tab_weaponskills', // '$LANG.tab_glyphs', // '$LANG.tab_abilities', // '$LANG.tab_talents', $conditions = array(['s.typeCat', [-13, -11, -2, 7]], [['s.cuFlags', SPELL_CU_TRIGGERED | CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], ['OR', ['s.reqClassMask', $_mask, '&'], ['s.skillLine1', $this->subject->getField('skills')], ['AND', ['s.skillLine1', 0, '>'], ['s.skillLine2OrMask', $this->subject->getField('skills')]]], ['OR', ['s.cuFlags', SPELL_CU_LAST_RANK, '&'], ['s.rankNo', 0]]); $genSpells = new SpellList($conditions); if (!$genSpells->error) { $this->extendGlobalData($genSpells->getJSGlobals(GLOBALINFO_SELF)); $this->lvTabs[] = array('file' => 'spell', 'data' => $genSpells->getListviewData(), 'params' => array('id' => 'spells', 'name' => '$LANG.tab_spells', 'visibleCols' => "\$['level', 'schools', 'type', 'classes']", 'hiddenCols' => "\$['reagents', 'skill']", 'sort' => "\$['-level', 'type', 'name']", 'computeDataFunc' => '$Listview.funcBox.initSpellFilter', 'onAfterCreate' => '$Listview.funcBox.addSpellIndicator')); } // Tab: Items (grouped) $conditions = array(['requiredClass', 0, '>'], ['requiredClass', $_mask, '&'], [['requiredClass', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!'], ['itemset', 0], 0); $items = new ItemList($conditions); if (!$items->error) { $this->extendGlobalData($items->getJSGlobals()); if (!$items->hasDiffFields(['requiredRace'])) { $hidden = "\$['side']"; } $this->lvTabs[] = array('file' => 'item', 'data' => $items->getListviewData(), 'params' => array('id' => 'items', 'name' => '$LANG.tab_items', 'visibleCols' => "\$['dps', 'armor', 'slot']", 'hiddenCols' => isset($hidden) ? $hidden : null, 'computeDataFunc' => '$Listview.funcBox.initSubclassFilter', 'onAfterCreate' => '$Listview.funcBox.addSubclassIndicator', 'note' => sprintf(Util::$filterResultString, '?items&filter=cr=152;crs=' . $this->typeId . ';crv=0'), '_truncated' => 1)); } // Tab: Quests $conditions = array(['reqClassMask', $_mask, '&'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']); $quests = new QuestList($conditions); if (!$quests->error) { $this->extendGlobalData($quests->getJSGlobals()); $this->lvTabs[] = array('file' => 'quest', 'data' => $quests->getListviewData(), 'params' => ['sort' => "\$['reqlevel', 'name']"]); } // Tab: Itemsets $sets = new ItemsetList(array(['classMask', $_mask, '&'])); if (!$sets->error) { $this->extendGlobalData($sets->getJSGlobals(GLOBALINFO_SELF)); $this->lvTabs[] = array('file' => 'itemset', 'data' => $sets->getListviewData(), 'params' => array('note' => sprintf(Util::$filterResultString, '?itemsets&filter=cl=' . $this->typeId), 'hiddenCols' => "\$['classes']", 'sort' => "\$['-level', 'name']")); } // Tab: Trainer $conditions = array(['npcflag', 0x30, '&'], ['trainerType', 0], ['trainerClass', $this->typeId]); $trainer = new CreatureList($conditions); if (!$trainer->error) { $this->lvTabs[] = array('file' => 'creature', 'data' => $trainer->getListviewData(), 'params' => array('id' => 'trainers', 'name' => '$LANG.tab_trainers')); } // Tab: Races $races = new CharRaceList(array(['classMask', $_mask, '&'])); if (!$races->error) { $this->lvTabs[] = array('file' => 'race', 'data' => $races->getListviewData(), 'params' => []); } }
private function _searchItemset($cndBase, &$shared) { $cnd = array_merge($cndBase, [is_int($this->query) ? ['id', $this->query] : $this->createLookup()]); $sets = new ItemsetList($cnd); if ($data = $sets->getListviewData()) { if ($this->searchMask & SEARCH_TYPE_REGULAR) { $this->extendGlobalData($sets->getJSGlobals(GLOBALINFO_SELF)); } $result['data'] = array_values($data); $osInfo = [TYPE_ITEMSET, ' (Item Set)', $sets->getMatches()]; if ($this->searchMask & SEARCH_TYPE_OPEN) { foreach ($sets->iterate() as $id => $__) { $osInfo[3][$id] = $sets->getField('quality'); } } $shared['pcsToSet'] = $sets->pieceToSet; if ($sets->getMatches() > $this->maxResults) { $result['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_itemsetsfound', $sets->getMatches(), $this->maxResults); $result['_truncated'] = 1; } if (isset($result['note'])) { $result['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?itemsets&filter=na=' . urlencode($this->search) . '\')'; } else { $result['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?itemsets&filter=na=' . urlencode($this->search) . '\')'; } return ['itemset', $result, null, $osInfo]; } return false; }