function glyphs() { $success = true; $glyphList = DB::Aowow()->Select('SELECT i.id AS itemId, i.*, IF (g.typeFlags & 0x1, 2, 1) AS type, i.subclass AS classs, i.requiredLevel AS level, s1.Id AS glyphSpell, ic.iconString AS icon, s1.skillLine1 AS skillId, s2.Id AS glyphEffect, s2.Id AS ARRAY_KEY FROM ?_items i JOIN ?_spell s1 ON s1.Id = i.spellid1 JOIN ?_glyphproperties g ON g.Id = s1.effect1MiscValue JOIN ?_spell s2 ON s2.Id = g.spellId JOIN ?_icons ic ON ic.Id = s1.iconIdAlt WHERE i.classBak = 16'); // check directory-structure foreach (Util::$localeStrings as $dir) { if (!CLISetup::writeDir('datasets/' . $dir)) { $success = false; } } $glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE)); foreach (CLISetup::$localeIds as $lId) { set_time_limit(30); User::useLocale($lId); Lang::load(Util::$localeStrings[$lId]); $glyphsOut = []; foreach ($glyphSpells->iterate() as $__) { $pop = $glyphList[$glyphSpells->id]; if (!$pop['glyphEffect']) { continue; } if ($glyphSpells->getField('effect1Id') != 6 && $glyphSpells->getField('effect2Id') != 6 && $glyphSpells->getField('effect3Id') != 6) { continue; } $glyphsOut[$pop['itemId']] = array('name' => Util::localizedString($pop, 'name'), 'description' => $glyphSpells->parseText()[0], 'icon' => $pop['icon'], 'type' => $pop['type'], 'classs' => $pop['classs'], 'skill' => $pop['skillId'], 'level' => $pop['level']); } $toFile = "var g_glyphs = " . Util::toJSON($glyphsOut) . ";"; $file = 'datasets/' . User::$localeString . '/glyphs'; if (!CLISetup::writeFile($file, $toFile)) { $success = false; } } return $success; }
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; }
function itemset() { $locales = [LOCALE_EN, LOCALE_FR, LOCALE_DE, LOCALE_ES, LOCALE_RU]; $setToHoliday = array(761 => 141, 762 => 372, 785 => 341, 812 => 181); // find events associated with holidayIds if ($pairs = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($setToHoliday))) { foreach ($setToHoliday as &$hId) { $hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0; } } // tags where refId == virtualId // in pve sets are not recycled beyond the contentGroup $tagsById = array(1 => [181, 182, 183, 184, 185, 186, 187, 188, 189], 2 => [511, 512, 513, 514, 515, 516, 517, 518, 519], 3 => [201, 202, 203, 204, 205, 206, 207, 208, 209], 4 => [210, 211, 212, 213, 214, 215, 216, 217, 218], 5 => [521, 523, 524, 525, 526, 527, 528, 529, 530], 6 => [522, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 697, 718], 7 => [281, 282, 301, 341, 342, 343, 344, 345, 346, 347, 348, 361, 362, 381, 382, 401], 8 => [383, 384, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 402, 717, 698], 9 => [494, 495, 498, 500, 502, 504, 506, 508, 510], 10 => [493, 496, 497, 499, 501, 503, 505, 507, 509], 11 => [477, 480, 474, 475, 476, 478, 479, 481, 482], 12 => [621, 624, 625, 626, 631, 632, 633, 638, 639, 640, 645, 648, 651, 654, 655, 663, 664], 13 => [622, 627, 628, 629, 634, 635, 636, 641, 642, 643, 646, 649, 652, 656, 657, 665, 666], 14 => [620, 623, 630, 637, 644, 647, 650, 653, 658, 659, 660, 661, 662], 15 => [467, 468, 469, 470, 471, 472, 473, 483, 484, 485, 486, 487, 488, 908], 16 => [587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 688, 689, 691, 692, 693, 694, 695, 696], 18 => [668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684], 21 => [738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752], 23 => [795, 805, 804, 803, 802, 801, 800, 799, 798, 797, 796, 794, 793, 792, 791, 790, 789, 788, 787], 25 => [838, 837, 836, 835, 834, 833, 832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820], 27 => [880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844, 843], 29 => [901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883]); // well .. f**k $tagsByNamePart = array(17 => ['gladiator'], 19 => ['merciless'], 20 => ['vengeful'], 22 => ['brutal'], 24 => ['deadly', 'hateful', 'savage'], 26 => ['furious'], 28 => ['relentless'], 30 => ['wrathful']); DB::Aowow()->query('TRUNCATE TABLE ?_itemset'); $vIdx = 0; $virtualId = 0; $sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset'); foreach ($sets as $setId => $setData) { $spells = $items = $mods = $descText = $name = $gains = []; $max = $reqLvl = $min = $quality = $heroic = $nPieces = []; $classMask = $type = 0; $hasRing = false; $holiday = isset($setToHoliday[$setId]) ? $setToHoliday[$setId] : 0; $canReuse = !$holiday; // can't reuse holiday-sets $slotList = []; $pieces = DB::World()->select('SELECT *, IF(InventoryType = 15, 26, IF(InventoryType = 5, 20, InventoryType)) AS slot, entry AS ARRAY_KEY FROM item_template WHERE itemset = ?d AND (class <> 4 OR subclass NOT IN (1, 2, 3, 4) OR armor > 0 OR Quality = 1) ORDER BY itemLevel, subclass, slot ASC', $setId); /****************************************/ /* determine type and reuse from pieces */ /****************************************/ // make the first vId always same as setId $firstPiece = reset($pieces); $tmp = [$firstPiece['Quality'] . $firstPiece['ItemLevel'] => $setId]; // walk through all items associated with the set foreach ($pieces as $itemId => $piece) { $classMask |= $piece['AllowableClass'] & CLASS_MASK_ALL; $key = $piece['Quality'] . str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT); if (!isset($tmp[$key])) { $tmp[$key] = --$vIdx; } $vId = $tmp[$key]; // check only actual armor in rare quality or higher (or inherits holiday) if ($piece['class'] != ITEM_CLASS_ARMOR || $piece['subclass'] == 0) { $canReuse = false; } /* gather relevant stats for use */ if (!isset($quality[$vId]) || $piece['Quality'] > $quality[$vId]) { $quality[$vId] = $piece['Quality']; } if ($piece['Flags'] & ITEM_FLAG_HEROIC) { $heroic[$vId] = true; } if (!isset($reqLvl[$vId]) || $piece['RequiredLevel'] > $reqLvl[$vId]) { $reqLvl[$vId] = $piece['RequiredLevel']; } if (!isset($min[$vId]) || $piece['ItemLevel'] < $min[$vId]) { $min[$vId] = $piece['ItemLevel']; } if (!isset($max[$vId]) || $piece['ItemLevel'] > $max[$vId]) { $max[$vId] = $piece['ItemLevel']; } if (!isset($items[$vId][$piece['slot']]) || !$canReuse) { if (!isset($nPieces[$vId])) { $nPieces[$vId] = 1; } else { $nPieces[$vId]++; } } if (isset($items[$vId][$piece['slot']])) { // not reusable -> insert anyway on unique keys if (!$canReuse) { $items[$vId][$piece['slot'] . $itemId] = $itemId; } else { CLISetup::log("set: " . $setId . " ilvl: " . $piece['ItemLevel'] . " - conflict between item: " . $items[$vId][$piece['slot']] . " and item: " . $itemId . " choosing lower itemId", CLISetup::LOG_WARN); if ($items[$vId][$piece['slot']] > $itemId) { $items[$vId][$piece['slot']] = $itemId; } } } else { $items[$vId][$piece['slot']] = $itemId; } /* check for type */ // skip cloaks, they mess with armor classes if ($piece['slot'] == 16) { continue; } // skip event-sets if ($piece['Quality'] == 1) { continue; } if ($piece['class'] == 2 && $piece['subclass'] == 0) { $type = 8; } else { if ($piece['class'] == 2 && $piece['subclass'] == 4) { $type = 9; } else { if ($piece['class'] == 2 && $piece['subclass'] == 7) { $type = 10; } else { if ($piece['class'] == 2 && $piece['subclass'] == 13) { $type = 7; } else { if ($piece['class'] == 2 && $piece['subclass'] == 15) { $type = 5; } } } } } // Dagger if (!$type) { if ($piece['class'] == 4 && $piece['slot'] == 12) { $type = 11; } else { if ($piece['class'] == 4 && $piece['slot'] == 2) { $type = 12; } else { if ($piece['class'] == 4 && $piece['subclass'] != 0) { $type = $piece['subclass']; } } } // 'armor' set if ($piece['class'] == 4 && $piece['slot'] == 11) { $hasRing = true; } // contains ring } } if ($hasRing && !$type) { $type = 6; } // pure ring-set $isMultiSet = false; $oldSlotMask = 0x0; foreach ($items as $subset) { $curSlotMask = 0x0; foreach ($subset as $slot => $item) { $curSlotMask |= 1 << $slot; } if ($oldSlotMask && $oldSlotMask == $curSlotMask) { $isMultiSet = true; break; } $oldSlotMask = $curSlotMask; } if (!$isMultiSet || !$canReuse || $setId == 555) { $temp = []; foreach ($items as $subset) { foreach ($subset as $slot => $item) { if (isset($temp[$slot]) && $temp[$slot] < $item) { CLISetup::log("set: " . $setId . " - conflict between item: " . $item . " and item: " . $temp[$slot] . " choosing lower itemId", CLISetup::LOG_WARN); } else { if ($slot == 13 || ($slot = 11)) { // special case $temp[] = $item; } else { $temp[$slot] = $item; } } } } $items = [$temp]; $heroic = [reset($heroic)]; $nPieces = [count($temp)]; $quality = [reset($quality)]; $reqLvl = [reset($reqLvl)]; $max = $max ? [max($max)] : [0]; $min = $min ? [min($min)] : [0]; } foreach ($items as &$subsets) { $subsets = array_pad($subsets, 10, 0); } /********************/ /* calc statbonuses */ /********************/ for ($i = 1; $i < 9; $i++) { if ($setData['spellId' . $i] > 0 && $setData['itemCount' . $i] > 0) { $spells[] = [$setData['spellId' . $i], $setData['itemCount' . $i]]; } } $bonusSpells = new SpellList(array(['s.id', array_column($spells, 0)])); $mods = $bonusSpells->getStatGain(); $spells = array_pad($spells, 8, [0, 0]); for ($i = 1; $i < 9; $i++) { if ($setData['itemCount' . $i] > 0 && !empty($mods[$setData['spellId' . $i]])) { $gains[$setData['itemCount' . $i]] = $mods[$setData['spellId' . $i]]; } } /**************************/ /* get name & description */ /**************************/ foreach ($locales as $loc) { User::useLocale($loc); $name[$loc] = Util::localizedString($setData, 'name'); foreach ($bonusSpells->iterate() as $__) { if (!isset($descText[$loc])) { $descText[$loc] = ''; } $descText[$loc] .= $bonusSpells->parseText()[0] . "\n"; } // strip rating blocks - e.g. <!--rtg19-->14 <small>(<!--rtg%19-->0.30% @ L<!--lvl-->80)</small> $descText[$loc] = preg_replace('/<!--rtg\\d+-->(\\d+) .*?<\\/small>/i', '\\1', $descText[$loc]); } /****************************/ /* finalaize data and write */ /****************************/ foreach ($items as $vId => $vSet) { $note = 0; foreach ($tagsById as $tag => $sets) { if (!in_array($setId, $sets)) { continue; } $note = $tag; } if (!$note && $min > 120 && $classMask && $classMask != CLASS_MASK_ALL) { foreach ($tagsByNamePart as $tag => $strings) { foreach ($strings as $str) { if (isset($pieces[reset($vSet)]) && stripos($pieces[reset($vSet)]['name'], $str) === 0) { $note = $tag; break 2; } } } } $row = []; $row[] = $vId < 0 ? --$virtualId : $setId; $row[] = $setId; // refSetId $row[] = 0; // cuFlags $row = array_merge($row, $name, $vSet); foreach (array_column($spells, 0) as $spellId) { $row[] = $spellId; } foreach (array_column($spells, 1) as $nItems) { $row[] = $nItems; } $row = array_merge($row, $descText); $row[] = serialize($gains); $row[] = $nPieces[$vId]; $row[] = $min[$vId]; $row[] = $max[$vId]; $row[] = $reqLvl[$vId]; $row[] = $classMask == CLASS_MASK_ALL ? 0 : $classMask; $row[] = !empty($heroic[$vId]) ? 1 : 0; $row[] = $quality[$vId]; $row[] = $type; $row[] = $note; // contentGroup $row[] = $holiday; $row[] = $setData['reqSkillId']; $row[] = $setData['reqSkillLevel']; DB::Aowow()->query('REPLACE INTO ?_itemset VALUES (?a)', array_values($row)); } } // hide empty sets DB::Aowow()->query('UPDATE ?_itemset SET cuFlags = cuFlags | ?d WHERE item1 = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW); return true; }
protected function generateContent() { $_ta = $this->subject->getField('contentGroup'); $_ty = $this->subject->getField('type'); $_cnt = count($this->subject->getField('pieces')); /***********/ /* Infobox */ /***********/ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); // unavailable (todo (low): set data) if ($this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE) { $infobox[] = Lang::main('unavailable'); } // holiday if ($h = $this->subject->getField('holidayId')) { $infobox[] = Lang::game('eventShort') . Lang::main('colon') . '[event=' . $h . ']'; $this->extendGlobalIds(TYPE_WORLDEVENT, $h); } // itemLevel if ($min = $this->subject->getField('minLevel')) { $foo = Lang::game('level') . Lang::main('colon') . $min; $max = $this->subject->getField('maxLevel'); if ($min < $max) { $foo .= ' - ' . $max; } $infobox[] = $foo; } // class if ($cl = Lang::getClassString($this->subject->getField('classMask'), $jsg, $qty, false)) { $this->extendGlobalIds(TYPE_CLASS, $jsg); $t = $qty == 1 ? Lang::game('class') : Lang::game('classes'); $infobox[] = Util::ucFirst($t) . Lang::main('colon') . $cl; } // required level if ($lvl = $this->subject->getField('reqLevel')) { $infobox[] = sprintf(Lang::game('reqLevel'), $lvl); } // type if ($_ty) { $infobox[] = Lang::game('type') . Lang::main('colon') . Lang::itemset('types', $_ty); } // tag if ($_ta) { $infobox[] = Lang::itemset('_tag') . Lang::main('colon') . '[url=?itemsets&filter=ta=' . $_ta . ']' . Lang::itemset('notes', $_ta) . '[/url]'; } /****************/ /* Main Content */ /****************/ // pieces + Summary $pieces = []; $eqList = []; $compare = []; if (!$this->subject->pieceToSet) { $cnd = [0]; } else { $cnd = ['i.id', array_keys($this->subject->pieceToSet)]; } $iList = new ItemList(array($cnd)); $data = $iList->getListviewData(ITEMINFO_SUBITEMS | ITEMINFO_JSON); foreach ($iList->iterate() as $itemId => $__) { if (empty($data[$itemId])) { continue; } $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]); } // spells $foo = []; $spells = []; for ($i = 1; $i < 9; $i++) { $spl = $this->subject->getField('spell' . $i); $qty = $this->subject->getField('bonus' . $i); if ($spl && $qty) { $foo[] = $spl; $spells[] = array('id' => $spl, 'bonus' => $qty, 'desc' => ''); } } // sort by required pieces ASC usort($spells, function ($a, $b) { if ($a['bonus'] == $b['bonus']) { return 0; } return $a['bonus'] > $b['bonus'] ? 1 : -1; }); $setSpells = new SpellList(array(['s.id', $foo])); foreach ($setSpells->iterate() as $spellId => $__) { foreach ($spells as &$s) { if ($spellId != $s['id']) { continue; } $s['desc'] = $setSpells->parseText('description')[0]; } } $skill = ''; if ($_sk = $this->subject->getField('skillId')) { $spellLink = sprintf('<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 = $spells; $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('holidayId')) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['holidayId', 0, '!']; } else { if ($this->subject->getField('skillId')) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['contentGroup', 0]; $rel[] = ['skillId', 0, '!']; $rel[] = ['type', $_ty]; } else { if (!$_ta && $_ty) { $rel[] = ['id', $this->typeId, '!']; $rel[] = ['contentGroup', 0]; $rel[] = ['type', $_ty]; $rel[] = ['skillId', 0]; } } } } if ($rel) { $relSets = new ItemsetList($rel); if (!$relSets->error) { $lv = array('file' => 'itemset', 'data' => $relSets->getListviewData(), 'params' => array('id' => 'see-also', 'name' => '$LANG.tab_seealso')); if (!$relSets->hasDiffFields(['classMask'])) { $lv['params']['hiddenCols'] = "\$['classes']"; } $this->lvTabs[] = $lv; $this->extendGlobalData($relSets->getJSGlobals()); } } }
public function getBonuses() { $spells = []; for ($i = 1; $i < 9; $i++) { $spl = $this->getField('spell' . $i); $qty = $this->getField('bonus' . $i); // cant use spell as index, would change order if ($spl && $qty) { $spells[] = ['id' => $spl, 'bonus' => $qty]; } } // sort by required pieces ASC usort($spells, function ($a, $b) { if ($a['bonus'] == $b['bonus']) { return 0; } return $a['bonus'] > $b['bonus'] ? 1 : -1; }); $setSpells = new SpellList(array(['s.id', array_column($spells, 'id')])); foreach ($setSpells->iterate() as $spellId => $__) { foreach ($spells as &$s) { if ($spellId != $s['id']) { continue; } $s['desc'] = $setSpells->parseText('description', $this->getField('reqLevel') ?: MAX_LEVEL)[0]; } } return $spells; }