public static function getRaceString($raceMask, &$side = 0, &$ids = [], &$n = 0, $asHTML = true) { $raceMask &= RACE_MASK_ALL; // clamp to available races.. if ($raceMask == RACE_MASK_ALL) { // available to all races (we don't display 'both factions') return false; } $tmp = []; $i = 1; $base = $asHTML ? '<a href="?race=%d" class="q1">%s</a>' : '[race=%d]'; $br = $asHTML ? '' : '[br]'; if (!$raceMask) { $side |= SIDE_BOTH; return self::game('ra', 0); } if ($raceMask & RACE_MASK_HORDE) { $side |= SIDE_HORDE; } if ($raceMask & RACE_MASK_ALLIANCE) { $side |= SIDE_ALLIANCE; } if ($raceMask == RACE_MASK_HORDE) { return self::game('ra', -2); } if ($raceMask == RACE_MASK_ALLIANCE) { return self::game('ra', -1); } while ($raceMask) { if ($raceMask & 1 << $i - 1) { $tmp[$i] = (!fMod(count($tmp) + 1, 3) ? $br : null) . sprintf($base, $i, self::game('ra', $i)); $raceMask &= ~(1 << $i - 1); } $i++; } $n = count($tmp); $ids = array_keys($tmp); return implode(', ', $tmp); }
protected function generateContent() { /***********/ /* Infobox */ /***********/ $infobox = $contrib = $groups = []; foreach (Lang::account('groups') as $idx => $key) { if ($idx >= 0 && $this->user['userGroups'] & 1 << $idx) { $groups[] = (!fMod(count($groups) + 1, 3) ? '[br]' : null) . Lang::account('groups', $idx); } } $infobox[] = Lang::user('joinDate') . Lang::main('colon') . '[tooltip name=joinDate]' . date('l, G:i:s', $this->user['joinDate']) . '[/tooltip][span class=tip tooltip=joinDate]' . date(Lang::main('dateFmtShort'), $this->user['joinDate']) . '[/span]'; $infobox[] = Lang::user('lastLogin') . Lang::main('colon') . '[tooltip name=lastLogin]' . date('l, G:i:s', $this->user['prevLogin']) . '[/tooltip][span class=tip tooltip=lastLogin]' . date(Lang::main('dateFmtShort'), $this->user['prevLogin']) . '[/span]'; $infobox[] = Lang::user('userGroups') . Lang::main('colon') . ($groups ? implode(', ', $groups) : Lang::account('groups', -1)); $infobox[] = Lang::user('consecVisits') . Lang::main('colon') . $this->user['consecutiveVisits']; $infobox[] = Util::ucFirst(Lang::main('siteRep')) . Lang::main('colon') . Lang::nf($this->user['sumRep']); // contrib -> [url=http://www.wowhead.com/client]Data uploads: n [small]([tooltip=tooltip_totaldatauploads]xx.y MB[/tooltip])[/small][/url] $co = DB::Aowow()->selectRow('SELECT COUNT(DISTINCT c.id) AS sum, SUM(IFNULL(cr.value, 0)) AS nRates FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id AND cr.userId <> 0 WHERE c.replyTo = 0 AND c.userId = ?d', $this->user['id']); if ($co['sum']) { $contrib[] = Lang::user('comments') . Lang::main('colon') . $co['sum'] . ($co['nRates'] ? ' [small]([tooltip=tooltip_totalratings]' . $co['nRates'] . '[/tooltip])[/small]' : null); } $ss = DB::Aowow()->selectRow('SELECT COUNT(*) AS sum, SUM(IF(status & ?d, 1, 0)) AS nSticky, SUM(IF(status & ?d, 0, 1)) AS nPending FROM ?_screenshots WHERE userIdOwner = ?d AND (status & ?d) = 0', CC_FLAG_STICKY, CC_FLAG_APPROVED, $this->user['id'], CC_FLAG_DELETED); if ($ss['sum']) { $buff = []; if ($ss['nSticky'] || $ss['nPending']) { if ($normal = $ss['sum'] - $ss['nSticky'] - $ss['nPending']) { $buff[] = '[tooltip=tooltip_normal]' . $normal . '[/tooltip]'; } if ($ss['nSticky']) { $buff[] = '[tooltip=tooltip_sticky]' . $ss['nSticky'] . '[/tooltip]'; } if ($ss['nPending']) { $buff[] = '[tooltip=tooltip_pending]' . $ss['nPending'] . '[/tooltip]'; } } $contrib[] = Lang::user('screenshots') . Lang::main('colon') . $ss['sum'] . ($buff ? ' [small](' . implode($buff, ' + ') . ')[/small]' : null); } $vi = DB::Aowow()->selectRow('SELECT COUNT(id) AS sum, SUM(IF(status & ?d, 1, 0)) AS nSticky, SUM(IF(status & ?d, 0, 1)) AS nPending FROM ?_videos WHERE userIdOwner = ?d AND (status & ?d) = 0', CC_FLAG_STICKY, CC_FLAG_APPROVED, $this->user['id'], CC_FLAG_DELETED); if ($vi['sum']) { $buff = []; if ($vi['nSticky'] || $vi['nPending']) { if ($normal = $vi['sum'] - $vi['nSticky'] - $vi['nPending']) { $buff[] = '[tooltip=tooltip_normal]' . $normal . '[/tooltip]'; } if ($vi['nSticky']) { $buff[] = '[tooltip=tooltip_sticky]' . $vi['nSticky'] . '[/tooltip]'; } if ($vi['nPending']) { $buff[] = '[tooltip=tooltip_pending]' . $vi['nPending'] . '[/tooltip]'; } } $contrib[] = Lang::user('videos') . Lang::main('colon') . $vi['sum'] . ($buff ? ' [small](' . implode($buff, ' + ') . ')[/small]' : null); } // contrib -> Forum posts: 5769 [small]([tooltip=topics]579[/tooltip] + [tooltip=replies]5190[/tooltip])[/small] $this->infobox = '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]'; if ($contrib) { $this->contributions = '[ul][li]' . implode('[/li][li]', $contrib) . '[/li][/ul]'; } /****************/ /* Main Content */ /****************/ $this->name = $this->user['title'] ? $this->user['displayName'] . ' <' . $this->user['title'] . '>' : sprintf(Lang::user('profileTitle'), $this->user['displayName']); /**************/ /* Extra Tabs */ /**************/ $this->lvTabs = []; $this->forceTabs = true; // [unused] Site Achievements // Reputation changelog (params only for comment-events) if ($repData = DB::Aowow()->select('SELECT action, amount, date AS \'when\', IF(action IN (3, 4, 5), sourceA, 0) AS param FROM ?_account_reputation WHERE userId = ?d', $this->user['id'])) { foreach ($repData as &$r) { $r['when'] = date(Util::$dateFormatInternal, $r['when']); } $this->lvTabs[] = ['reputationhistory', ['data' => $repData]]; } // Comments if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => false], $nFound)) { $tabData = array('data' => $_, 'hiddenCols' => ['author'], 'onBeforeCreate' => '$Listview.funcBox.beforeUserComments', '_totalCount' => $nFound); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $tabData['name'] = '$LANG.tab_latestcomments'; $tabData['note'] = '$$WH.sprintf(LANG.lvnote_usercomments, ' . $nFound . ')'; } $this->lvTabs[] = ['commentpreview', $tabData]; } // Comment Replies if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => true], $nFound)) { $tabData = array('data' => $_, 'hiddenCols' => ['author'], 'onBeforeCreate' => '$Listview.funcBox.beforeUserComments', '_totalCount' => $nFound); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $tabData['name'] = '$LANG.tab_latestreplies'; $tabData['note'] = '$$WH.sprintf(LANG.lvnote_userreplies, ' . $nFound . ')'; } $this->lvTabs[] = ['replypreview', $tabData]; } // Screenshots if ($_ = CommunityContent::getScreenshots(-$this->user['id'], 0, $nFound)) { $tabData = array('data' => $_, '_totalCount' => $nFound); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $tabData['name'] = '$LANG.tab_latestscreenshots'; $tabData['note'] = '$$WH.sprintf(LANG.lvnote_userscreenshots, ' . $nFound . ')'; } $this->lvTabs[] = ['screenshot', $tabData]; } // Videos if ($_ = CommunityContent::getVideos(-$this->user['id'], 0, $nFound)) { $tabData = array('data' => $_, '_totalCount' => $nFound); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $tabData['name'] = '$LANG.tab_latestvideos'; $tabData['note'] = '$$WH.sprintf(LANG.lvnote_uservideos, ' . $nFound . ')'; } $this->lvTabs[] = ['video', $tabData]; } // forum -> latest topics [unused] // forum -> latest replies [unused] // Characters [todo] $this->user['characterData'] = []; /* us_addCharactersTab([ { id:763, "name":"Lilywhite", "achievementpoints":"0", "guild":"whatever", "guildrank":"0", "realm":"draenor", "realmname":"Draenor", "battlegroup":"cyclone", "battlegroupname":"Cyclone", "region":"us", "level":"10", "race":"7", "gender":"0", "classs":"1", "faction":"0", "gearscore":"0", "talenttree1":"0", "talenttree2":"0", "talenttree3":"0", "talentspec":0, "published":1, "pinned":0 } ]); */ // Profiles [todo] $this->user['profileData'] = []; }
protected function generateContent() { $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']); $_typeFlags = $this->subject->getField('typeFlags'); $_altIds = []; $_altNPCs = null; $placeholder = null; $accessory = []; // difficulty entries of self if ($this->subject->getField('cuFlags') & NPC_CU_DIFFICULTY_DUMMY) { $placeholder = [$this->subject->getField('parentId'), $this->subject->getField('parent', true)]; } else { for ($i = 1; $i < 4; $i++) { if ($_ = $this->subject->getField('difficultyEntry' . $i)) { $_altIds[$_] = $i; } } if ($_altIds) { $_altNPCs = new CreatureList(array(['id', array_keys($_altIds)])); } } if ($_ = DB::World()->selectCol('SELECT DISTINCT entry FROM vehicle_template_accessory WHERE accessory_entry = ?d', $this->typeId)) { $vehicles = new CreatureList(array(['id', $_])); foreach ($vehicles->iterate() as $id => $__) { $accessory[] = [$id, $vehicles->getField('name', true)]; } } // try to determine, if it's spawned in a dungeon or raid (shaky at best, if spawned by script) $mapType = 0; if ($maps = DB::Aowow()->selectCol('SELECT DISTINCT areaId from ?_spawns WHERE type = ?d AND typeId = ?d', TYPE_NPC, $this->typeId)) { if (count($maps) == 1) { switch (DB::Aowow()->selectCell('SELECT `type` FROM ?_zones WHERE id = ?d', $maps[0])) { case 2: case 5: $mapType = 1; break; case 3: case 7: case 8: $mapType = 2; break; } } } else { if ($_altIds) { if (count($_altIds) > 1) { // 3 or more version -> definitly raid (10/25 + hc) $mapType = 2; } else { // 2 versions; may be Heroic (use this), but may also be 10/25-raid $mapType = 1; } } } /***********/ /* Infobox */ /***********/ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); // Event (ignore events, where the object only gets removed) if ($_ = DB::World()->selectCol('SELECT DISTINCT ge.eventEntry FROM game_event ge, game_event_creature gec, creature c WHERE ge.eventEntry = gec.eventEntry AND c.guid = gec.guid AND c.id = ?d', $this->typeId)) { $this->extendGlobalIds(TYPE_WORLDEVENT, $_); $ev = []; foreach ($_ as $i => $e) { $ev[] = ($i % 2 ? '[br]' : ' ') . '[event=' . $e . ']'; } $infobox[] = Util::ucFirst(Lang::game('eventShort')) . Lang::main('colon') . implode(',', $ev); } // Level if ($this->subject->getField('rank') != NPC_RANK_BOSS) { $level = $this->subject->getField('minLevel'); $maxLvl = $this->subject->getField('maxLevel'); if ($level < $maxLvl) { $level .= ' - ' . $maxLvl; } } else { // Boss Level $level = '??'; } $infobox[] = Lang::game('level') . Lang::main('colon') . $level; // Classification if ($_ = $this->subject->getField('rank')) { $str = $_typeFlags & 0x4 ? '[span class=icon-boss]' . Lang::npc('rank', $_) . '[/span]' : Lang::npc('rank', $_); $infobox[] = Lang::npc('classification') . Lang::main('colon') . $str; } // Reaction $_ = function ($r) { if ($r == 1) { return 2; } if ($r == -1) { return 10; } return; }; $infobox[] = Lang::npc('react') . Lang::main('colon') . '[color=q' . $_($this->subject->getField('A')) . ']A[/color] [color=q' . $_($this->subject->getField('H')) . ']H[/color]'; // Faction $this->extendGlobalIds(TYPE_FACTION, $this->subject->getField('factionId')); $infobox[] = Util::ucFirst(Lang::game('faction')) . Lang::main('colon') . '[faction=' . $this->subject->getField('factionId') . ']'; // Tameable if ($_typeFlags & 0x1) { if ($_ = $this->subject->getField('family')) { $infobox[] = sprintf(Lang::npc('tameable'), '[url=pet=' . $_ . ']' . Lang::game('fa', $_) . '[/url]'); } } // Wealth if ($_ = intVal(($this->subject->getField('minGold') + $this->subject->getField('maxGold')) / 2)) { $infobox[] = Lang::npc('worth') . Lang::main('colon') . '[tooltip=tooltip_avgmoneydropped][money=' . $_ . '][/tooltip]'; } // is Vehicle if ($this->subject->getField('vehicleId')) { $infobox[] = Lang::npc('vehicle'); } // AI if (User::isInGroup(U_GROUP_EMPLOYEE)) { if ($_ = $this->subject->getField('scriptName')) { $infobox[] = 'Script' . Lang::main('colon') . $_; } else { if ($_ = $this->subject->getField('aiName')) { $infobox[] = 'AI' . Lang::main('colon') . $_; } } } if (User::isInGroup(U_GROUP_STAFF)) { // Mechanic immune if ($immuneMask = $this->subject->getField('mechanicImmuneMask')) { $buff = []; for ($i = 0; $i < 31; $i++) { if ($immuneMask & 1 << $i) { $buff[] = (!fMod(count($buff), 3) ? "\n" : null) . '[url=?spells&filter=me=' . ($i + 1) . ']' . Lang::game('me', $i + 1) . '[/url]'; } } $infobox[] = 'Not affected by mechanic' . Lang::main('colon') . implode(', ', $buff); } // extra flags if ($flagsExtra = $this->subject->getField('flagsExtra')) { $buff = []; if ($flagsExtra & 0x1) { $buff[] = 'Binds attacker to instance on death'; } if ($flagsExtra & 0x2) { $buff[] = "[tooltip name=civilian]- does not aggro\n- death costs Honor[/tooltip][span class=tip tooltip=civilian]Civilian[/span]"; } if ($flagsExtra & 0x4) { $buff[] = 'Cannot parry'; } if ($flagsExtra & 0x8) { $buff[] = 'Has no parry haste'; } if ($flagsExtra & 0x10) { $buff[] = 'Cannot block'; } if ($flagsExtra & 0x20) { $buff[] = 'Cannot deal Crushing Blows'; } if ($flagsExtra & 0x40) { $buff[] = 'Rewards no experience'; } if ($flagsExtra & 0x80) { $buff[] = 'Trigger-Creature'; } if ($flagsExtra & 0x100) { $buff[] = 'Immune to Taunt'; } if ($flagsExtra & 0x8000) { $buff[] = "[tooltip name=guard]- engages PvP-Attacker\n- ignores enemy stealth, invisibility and Feign Death[/tooltip][span class=tip tooltip=guard]Guard[/span]"; } if ($flagsExtra & 0x20000) { $buff[] = 'Cannot deal Critical Hits'; } if ($flagsExtra & 0x40000) { $buff[] = 'Attacker does not gain weapon skill'; } if ($flagsExtra & 0x80000) { $buff[] = 'Taunt has diminishing returns'; } if ($flagsExtra & 0x100000) { $buff[] = 'Is subject to diminishing returns'; } if ($buff) { $infobox[] = 'Extra Flags' . Lang::main('colon') . '[ul][li]' . implode('[/li][li]', $buff) . '[/li][/ul]'; } } } // > Stats $stats = []; $modes = []; // get difficulty versions if set $hint = '[tooltip name=%3$s][table cellspacing=10][tr]%1s[/tr][/table][/tooltip][span class=tip tooltip=%3$s]%2s[/span]'; $modeRow = '[tr][td]%s [/td][td]%s[/td][/tr]'; // Health $health = $this->subject->getBaseStats('health'); $stats['health'] = Util::ucFirst(Lang::spell('powerTypes', -2)) . Lang::main('colon') . ($health[0] < $health[1] ? Lang::nf($health[0]) . ' - ' . Lang::nf($health[1]) : Lang::nf($health[0])); // Mana (may be 0) $mana = $this->subject->getBaseStats('power'); $stats['mana'] = $mana[0] ? Lang::spell('powerTypes', 0) . Lang::main('colon') . ($mana[0] < $mana[1] ? Lang::nf($mana[0]) . ' - ' . Lang::nf($mana[1]) : Lang::nf($mana[0])) : null; // Armor $armor = $this->subject->getBaseStats('armor'); $stats['armor'] = Lang::npc('armor') . Lang::main('colon') . ($armor[0] < $armor[1] ? Lang::nf($armor[0]) . ' - ' . Lang::nf($armor[1]) : Lang::nf($armor[0])); // Melee Damage $melee = $this->subject->getBaseStats('melee'); if ($_ = $this->subject->getField('dmgSchool')) { // magic damage $stats['melee'] = Lang::npc('melee') . Lang::main('colon') . Lang::nf($melee[0]) . ' - ' . Lang::nf($melee[1]) . ' (' . Lang::game('sc', $_) . ')'; } else { // phys. damage $stats['melee'] = Lang::npc('melee') . Lang::main('colon') . Lang::nf($melee[0]) . ' - ' . Lang::nf($melee[1]); } // Ranged Damage $ranged = $this->subject->getBaseStats('ranged'); $stats['ranged'] = Lang::npc('ranged') . Lang::main('colon') . Lang::nf($ranged[0]) . ' - ' . Lang::nf($ranged[1]); if (in_array($mapType, [1, 2])) { foreach ($_altIds as $id => $mode) { foreach ($_altNPCs->iterate() as $dId => $__) { if ($dId != $id) { continue; } $m = Lang::npc('modes', $mapType, $mode); // Health $health = $_altNPCs->getBaseStats('health'); $modes['health'][] = sprintf($modeRow, $m, $health[0] < $health[1] ? Lang::nf($health[0]) . ' - ' . Lang::nf($health[1]) : Lang::nf($health[0])); // Mana (may be 0) $mana = $_altNPCs->getBaseStats('power'); $modes['mana'][] = $mana[0] ? sprintf($modeRow, $m, $mana[0] < $mana[1] ? Lang::nf($mana[0]) . ' - ' . Lang::nf($mana[1]) : Lang::nf($mana[0])) : null; // Armor $armor = $_altNPCs->getBaseStats('armor'); $modes['armor'][] = sprintf($modeRow, $m, $armor[0] < $armor[1] ? Lang::nf($armor[0]) . ' - ' . Lang::nf($armor[1]) : Lang::nf($armor[0])); // Melee Damage $melee = $_altNPCs->getBaseStats('melee'); if ($_ = $_altNPCs->getField('dmgSchool')) { // magic damage $modes['melee'][] = sprintf($modeRow, $m, Lang::nf($melee[0]) . ' - ' . Lang::nf($melee[1]) . ' (' . Lang::game('sc', $_) . ')'); } else { // phys. damage $modes['melee'][] = sprintf($modeRow, $m, Lang::nf($melee[0]) . ' - ' . Lang::nf($melee[1])); } // Ranged Damage $ranged = $_altNPCs->getBaseStats('ranged'); $modes['ranged'][] = sprintf($modeRow, $m, Lang::nf($ranged[0]) . ' - ' . Lang::nf($ranged[1])); } } } if ($modes) { foreach ($stats as $k => $v) { if ($v) { $stats[$k] = sprintf($hint, implode('[/tr][tr]', $modes[$k]), $v, $k); } } } // < Stats if ($stats) { $infobox[] = Lang::npc('stats') . ($modes ? ' (' . Lang::npc('modes', $mapType, 0) . ')' : null) . Lang::main('colon') . '[ul][li]' . implode('[/li][li]', $stats) . '[/li][/ul]'; } /****************/ /* Main Content */ /****************/ // get spawns and path $map = null; if ($spawns = $this->subject->getSpawns(SPAWNINFO_FULL)) { $map = ['data' => ['parent' => 'mapper-generic'], 'mapperData' => &$spawns]; foreach ($spawns as $areaId => &$areaData) { $map['extra'][$areaId] = ZoneList::getName($areaId); } } // consider pooled spawns $this->map = $map; $this->infobox = '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]'; $this->placeholder = $placeholder; $this->accessory = $accessory; $this->quotes = $this->getQuotes(); $this->reputation = $this->getOnKillRep($_altIds, $mapType); $this->redButtons = array(BUTTON_WOWHEAD => true, BUTTON_LINKS => true, BUTTON_VIEW3D => ['type' => TYPE_NPC, 'typeId' => $this->typeId, 'displayId' => $this->subject->getRandomModelId()]); /**************/ /* Extra Tabs */ /**************/ // tab: SAI // hmm, how should this look like // tab: abilities / tab_controlledabilities (dep: VehicleId) // SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86 $smartSpells = DB::World()->selectCol('SELECT action_param1 FROM smart_scripts WHERE source_type = 0 AND action_type IN (11, 75, 85, 86) AND entryOrGUID = ?d', $this->typeId); $tplSpells = []; $conditions = ['OR']; for ($i = 1; $i < 9; $i++) { if ($_ = $this->subject->getField('spell' . $i)) { $tplSpells[] = $_; } } if ($tplSpells) { $conditions[] = ['id', $tplSpells]; } if ($smartSpells) { $conditions[] = ['id', $smartSpells]; } // Pet-Abilities if ($_typeFlags & 0x1 && ($_ = $this->subject->getField('family'))) { $skill = 0; $mask = 0x0; foreach (Util::$skillLineMask[-1] as $idx => $pair) { if ($pair[0] != $_) { continue; } $skill = $pair[1]; $mask = 1 << $idx; break; } $conditions[] = ['AND', ['s.typeCat', -3], ['OR', ['skillLine1', $skill], ['AND', ['skillLine1', 0, '>'], ['skillLine2OrMask', $skill]], ['AND', ['skillLine1', -1], ['skillLine2OrMask', $mask, '&']]]]; } if (count($conditions) > 1) { $abilities = new SpellList($conditions); if (!$abilities->error) { $this->extendGlobalData($abilities->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); $controled = $abilities->getListviewData(); $normal = []; foreach ($controled as $id => $values) { if (in_array($id, $smartSpells)) { $normal[$id] = $values; unset($controled[$id]); continue; } // not quite right. All seats should be checked for allowed-to-cast-flag-something if (!$this->subject->getField('vehicleId') && in_array($id, $tplSpells)) { $normal[$id] = $values; unset($controled[$id]); } } if ($normal) { $this->lvTabs[] = array('file' => 'spell', 'data' => $normal, 'params' => array('name' => '$LANG.tab_abilities', 'id' => 'abilities')); } if ($controled) { $this->lvTabs[] = array('file' => 'spell', 'data' => $controled, 'params' => array('name' => '$LANG.tab_controlledabilities', 'id' => 'controlled-abilities')); } } } // tab: summoned by $conditions = array('OR', ['AND', ['effect1Id', 28], ['effect1MiscValue', $this->typeId]], ['AND', ['effect2Id', 28], ['effect2MiscValue', $this->typeId]], ['AND', ['effect3Id', 28], ['effect3MiscValue', $this->typeId]]); $summoned = new SpellList($conditions); if (!$summoned->error) { $this->extendGlobalData($summoned->getJSGlobals()); $this->lvTabs[] = array('file' => 'spell', 'data' => $summoned->getListviewData(), 'params' => array('name' => '$LANG.tab_summonedby', 'id' => 'summoned-by')); } // tab: teaches if ($this->subject->getField('npcflag') & NPC_FLAG_TRAINER) { $teachQuery = ' SELECT IFNULL(t2.SpellID, t1.SpellID) AS ARRAY_KEY, IFNULL(t2.MoneyCost, t1.MoneyCost) AS cost, IFNULL(t2.ReqSkillLine, t1.ReqSkillLine) AS reqSkillId, IFNULL(t2.ReqSkillRank, t1.ReqSkillRank) AS reqSkillValue, IFNULL(t2.ReqLevel, t1.ReqLevel) AS reqLevel FROM npc_trainer t1 LEFT JOIN npc_trainer t2 ON t2.ID = IF(t1.SpellID < 0, -t1.SpellID, null) WHERE t1.ID = ?d '; if ($tSpells = DB::World()->select($teachQuery, $this->typeId)) { $teaches = new SpellList(array(['id', array_keys($tSpells)])); if (!$teaches->error) { $this->extendGlobalData($teaches->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); $data = $teaches->getListviewData(); $extra = []; foreach ($tSpells as $sId => $train) { if (empty($data[$sId])) { continue; } if ($_ = $train['reqSkillId']) { $this->extendGlobalIds(TYPE_SKILL, $_); if (!isset($extra[0])) { $extra[0] = 'Listview.extraCols.condition'; } $data[$sId]['condition'][0][$this->typeId][] = [[CND_SKILL, $_, $train['reqSkillValue']]]; } if ($_ = $train['reqLevel']) { if (!isset($extra[1])) { $extra[1] = "Listview.funcBox.createSimpleCol('reqLevel', LANG.tooltip_reqlevel, '7%', 'reqLevel')"; } $data[$sId]['reqLevel'] = $_; } if ($_ = $train['cost']) { $data[$sId]['trainingcost'] = $_; } } $this->lvTabs[] = array('file' => 'spell', 'data' => $data, 'params' => array('name' => '$LANG.tab_teaches', 'id' => 'teaches', 'visibleCols' => "\$['trainingcost']", 'extraCols' => $extra ? '$[' . implode(', ', $extra) . ']' : null)); } } else { trigger_error('NPC ' . $this->typeId . ' is flagged as trainer, but doesn\'t have any spells set', E_USER_WARNING); } } // tab: sells if ($sells = DB::World()->selectCol('SELECT item FROM npc_vendor nv WHERE entry = ?d UNION SELECT item FROM game_event_npc_vendor genv JOIN creature c ON genv.guid = c.guid WHERE c.id = ?d', $this->typeId, $this->typeId)) { $soldItems = new ItemList(array(['id', $sells])); if (!$soldItems->error) { $extraCols = ["Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", 'Listview.extraCols.cost']; if ($soldItems->hasSetFields(['condition'])) { $extraCols[] = 'Listview.extraCols.condition'; } $lvData = $soldItems->getListviewData(ITEMINFO_VENDOR, [TYPE_NPC => [$this->typeId]]); $sc = Util::getServerConditions(CND_SRC_NPC_VENDOR, $this->typeId); if (!empty($sc[0])) { $this->extendGlobalData($sc[1]); if (!array_search('Listview.extraCols.condition', $extraCols)) { $extraCols[] = 'Listview.extraCols.condition'; } foreach ($lvData as $id => &$row) { foreach ($sc[0] as $srcType => $cndData) { if (!empty($cndData[$id . ':' . $this->typeId])) { $row['condition'][0][$id . ':' . $this->typeId] = $cndData[$id . ':' . $this->typeId]; } } } } $this->lvTabs[] = array('file' => 'item', 'data' => $lvData, 'params' => array('name' => '$LANG.tab_sells', 'id' => 'currency-for', 'extraCols' => '$[' . implode(', ', $extraCols) . ']')); $this->extendGlobalData($soldItems->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); } } // tabs: this creature contains.. $skinTab = ['tab_skinning', 'skinning']; if ($_typeFlags & NPC_TYPEFLAG_HERBLOOT) { $skinTab = ['tab_herbalism', 'herbalism']; } else { if ($_typeFlags & NPC_TYPEFLAG_MININGLOOT) { $skinTab = ['tab_mining', 'mining']; } else { if ($_typeFlags & NPC_TYPEFLAG_ENGINEERLOOT) { $skinTab = ['tab_engineering', 'engineering']; } } } /* extraCols: [Listview.extraCols.count, Listview.extraCols.percent, Listview.extraCols.mode], _totalCount: 22531, computeDataFunc: Listview.funcBox.initLootTable, onAfterCreate: Listview.funcBox.addModeIndicator, modes:{"mode":1,"1":{"count":4408,"outof":16013},"4":{"count":4408,"outof":22531}} */ $sourceFor = array([LOOT_CREATURE, $this->subject->getField('lootId'), '$LANG.tab_drops', 'drops', []], [LOOT_PICKPOCKET, $this->subject->getField('pickpocketLootId'), '$LANG.tab_pickpocketing', 'pickpocketing', ['side', 'slot', 'reqlevel']], [LOOT_SKINNING, $this->subject->getField('skinLootId'), '$LANG.' . $skinTab[0], $skinTab[1], ['side', 'slot', 'reqlevel']]); // temp: manually add loot for difficulty-versions $langref = array("-2" => '$LANG.tab_heroic', "-1" => '$LANG.tab_normal', 1 => '$$WH.sprintf(LANG.tab_normalX, 10)', 2 => '$$WH.sprintf(LANG.tab_normalX, 25)', 3 => '$$WH.sprintf(LANG.tab_heroicX, 10)', 4 => '$$WH.sprintf(LANG.tab_heroicX, 25)'); if ($_altIds) { $sourceFor[0][2] = $mapType == 1 ? $langref[-1] : $langref[1]; foreach ($_altNPCs->iterate() as $id => $__) { $mode = ($_altIds[$id] + 1) * ($mapType == 1 ? -1 : 1); if ($lootGO = DB::Aowow()->selectRow('SELECT o.id, o.lootId, o.name_loc0, o.name_loc2, o.name_loc3, o.name_loc6, o.name_loc8 FROM ?_loot_link l JOIN ?_objects o ON o.id = l.objectId WHERE l.npcId = ?d', $id)) { array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lootGO['lootId'], $langref[$mode], 'drops-object-' . abs($mode), [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, ' . $lootGO['id'] . ', \'' . Util::jsEscape(Util::localizedString($lootGO, 'name')) . '\')']]); } if ($lootId = $_altNPCs->getField('lootId')) { array_splice($sourceFor, 1, 0, [[LOOT_CREATURE, $lootId, $langref[$mode], 'drops-' . abs($mode), []]]); } } } if ($lootGOs = DB::Aowow()->select('SELECT o.id, IF(npcId < 0, 1, 0) AS modeDummy, o.lootId, o.name_loc0, o.name_loc2, o.name_loc3, o.name_loc6, o.name_loc8 FROM ?_loot_link l JOIN ?_objects o ON o.id = l.objectId WHERE ABS(l.npcId) = ?d', $this->typeId)) { foreach ($lootGOs as $idx => $lgo) { array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lgo['lootId'], $mapType ? $langref[($mapType == 1 ? -1 : 1) + ($lgo['modeDummy'] ? 1 : 0)] : '$LANG.tab_drops', 'drops-object-' . $idx, [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, ' . $lgo['id'] . ', \'' . Util::jsEscape(Util::localizedString($lgo, 'name')) . '\')']]); } } $reqQuest = []; foreach ($sourceFor as $sf) { $creatureLoot = new Loot(); if ($creatureLoot->getByContainer($sf[0], $sf[1])) { $extraCols = $creatureLoot->extraCols; $extraCols[] = 'Listview.extraCols.percent'; $this->extendGlobalData($creatureLoot->jsGlobals); foreach ($creatureLoot->iterate() as &$lv) { if (!$lv['quest']) { continue; } $extraCols[] = 'Listview.extraCols.condition'; $reqQuest[$lv['id']] = 0; $lv['condition'][0][$this->typeId][] = [[CND_QUESTTAKEN, &$reqQuest[$lv['id']]]]; } $lootTab = array('file' => 'item', 'data' => $creatureLoot->getResult(), 'params' => array('name' => $sf[2], 'id' => $sf[3], 'extraCols' => "\$[" . implode(', ', array_unique($extraCols)) . "]", 'hiddenCols' => $sf[4] ? "\$" . Util::toJSON($sf[4]) : null, 'sort' => "\$['-percent', 'name']")); if (!empty($sf['note'])) { $lootTab['params']['note'] = $sf['note']; } $this->lvTabs[] = $lootTab; } } if ($reqIds = array_keys($reqQuest)) { $conditions = array('OR', ['reqSourceItemId1', $reqIds], ['reqSourceItemId2', $reqIds], ['reqSourceItemId3', $reqIds], ['reqSourceItemId4', $reqIds], ['reqItemId1', $reqIds], ['reqItemId2', $reqIds], ['reqItemId3', $reqIds], ['reqItemId4', $reqIds], ['reqItemId5', $reqIds], ['reqItemId6', $reqIds]); $reqQuests = new QuestList($conditions); $this->extendGlobalData($reqQuests->getJSGlobals()); foreach ($reqQuests->iterate() as $qId => $__) { if (empty($reqQuests->requires[$qId][TYPE_ITEM])) { continue; } foreach ($reqIds as $rId) { if (in_array($rId, $reqQuests->requires[$qId][TYPE_ITEM])) { $reqQuest[$rId] = $reqQuests->id; } } } } // tab: starts quest // tab: ends quest $startEnd = new QuestList(array(['qse.type', TYPE_NPC], ['qse.typeId', $this->typeId])); if (!$startEnd->error) { $this->extendGlobalData($startEnd->getJSGlobals()); $lvData = $startEnd->getListviewData(); $_ = [[], []]; foreach ($startEnd->iterate() as $id => $__) { $m = $startEnd->getField('method'); if ($m & 0x1) { $_[0][] = $lvData[$id]; } if ($m & 0x2) { $_[1][] = $lvData[$id]; } } if ($_[0]) { $this->lvTabs[] = array('file' => 'quest', 'data' => $_[0], 'params' => array('name' => '$LANG.tab_starts', 'id' => 'starts')); } if ($_[1]) { $this->lvTabs[] = array('file' => 'quest', 'data' => $_[1], 'params' => array('name' => '$LANG.tab_ends', 'id' => 'ends')); } } // tab: objective of quest $conditions = array('OR', ['AND', ['reqNpcOrGo1', $this->typeId], ['reqNpcOrGoCount1', 0, '>']], ['AND', ['reqNpcOrGo2', $this->typeId], ['reqNpcOrGoCount2', 0, '>']], ['AND', ['reqNpcOrGo3', $this->typeId], ['reqNpcOrGoCount3', 0, '>']], ['AND', ['reqNpcOrGo4', $this->typeId], ['reqNpcOrGoCount4', 0, '>']]); $objectiveOf = new QuestList($conditions); if (!$objectiveOf->error) { $this->extendGlobalData($objectiveOf->getJSGlobals()); $this->lvTabs[] = array('file' => 'quest', 'data' => $objectiveOf->getListviewData(), 'params' => array('name' => '$LANG.tab_objectiveof', 'id' => 'objective-of')); } // tab: criteria of [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE have no data set to check for] $conditions = array(['ac.type', [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE]], ['ac.value1', $this->typeId]); $crtOf = new AchievementList($conditions); if (!$crtOf->error) { $this->extendGlobalData($crtOf->getJSGlobals()); $this->lvTabs[] = array('file' => 'achievement', 'data' => $crtOf->getListviewData(), 'params' => array('name' => '$LANG.tab_criteriaof', 'id' => 'criteria-of')); } // tab: passengers if ($_ = DB::World()->selectCol('SELECT accessory_entry AS ARRAY_KEY, GROUP_CONCAT(seat_id) FROM vehicle_template_accessory WHERE entry = ?d GROUP BY accessory_entry', $this->typeId)) { $passengers = new CreatureList(array(['id', array_keys($_)])); if (!$passengers->error) { $data = $passengers->getListviewData(); $xCols = null; if (User::isInGroup(U_GROUP_STAFF)) { foreach ($data as $id => &$d) { $d['seat'] = str_replace(',', ', ', $_[$id]); } $xCols = "\$[Listview.funcBox.createSimpleCol('seat', '" . Lang::npc('seat') . "', '10%', 'seat')]"; } $this->extendGlobalData($passengers->getJSGlobals(GLOBALINFO_SELF)); $this->lvTabs[] = array('file' => 'creature', 'data' => $data, 'params' => array('extraCols' => $xCols, 'name' => Lang::npc('accessory'), 'id' => 'accessory')); } } }
public static function asBin($val) { $_ = decBin($val); while (fMod(strLen($_), 4)) { // in 4-blocks $_ = '0' . $_; } return 'b' . strToUpper($_); }
private function createDashboard() { if (!User::$id) { $this->forwardToSignIn('account'); } $user = DB::Aowow()->selectRow('SELECT * FROM ?_account WHERE id = ?d', User::$id); $bans = DB::Aowow()->select('SELECT ab.*, a.displayName, ab.id AS ARRAY_KEY FROM ?_account_banned ab LEFT JOIN ?_account a ON a.id = ab.staffId WHERE ab.userId = ?d', User::$id); /***********/ /* Infobox */ /***********/ $infobox = []; $infobox[] = Lang::user('joinDate') . Lang::main('colon') . '[tooltip name=joinDate]' . date('l, G:i:s', $user['joinDate']) . '[/tooltip][span class=tip tooltip=joinDate]' . date(Lang::main('dateFmtShort'), $user['joinDate']) . '[/span]'; $infobox[] = Lang::user('lastLogin') . Lang::main('colon') . '[tooltip name=lastLogin]' . date('l, G:i:s', $user['prevLogin']) . '[/tooltip][span class=tip tooltip=lastLogin]' . date(Lang::main('dateFmtShort'), $user['prevLogin']) . '[/span]'; $infobox[] = Lang::account('lastIP') . Lang::main('colon') . $user['prevIP']; $infobox[] = Lang::account('email') . Lang::main('colon') . $user['email']; $groups = []; foreach (Lang::account('groups') as $idx => $key) { if ($idx >= 0 && $user['userGroups'] & 1 << $idx) { $groups[] = (!fMod(count($groups) + 1, 3) ? '[br]' : null) . Lang::account('groups', $idx); } } $infobox[] = Lang::user('userGroups') . Lang::main('colon') . ($groups ? implode(', ', $groups) : Lang::account('groups', -1)); $infobox[] = Util::ucFirst(Lang::main('siteRep')) . Lang::main('colon') . User::getReputation(); $this->infobox = '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]'; /*************/ /* Ban Popup */ /*************/ foreach ($bans as $b) { if (!($b['typeMask'] & (ACC_BAN_TEMP | ACC_BAN_PERM)) || $b['end'] && $b['end'] <= time()) { continue; } $this->banned = array('by' => [$b['staffId'], $b['displayName']], 'end' => $b['end'], 'reason' => $b['reason']); break; // one is enough } /************/ /* Listview */ /************/ $this->forceTabs = true; // Reputation changelog (params only for comment-events) if ($repData = DB::Aowow()->select('SELECT action, amount, date AS \'when\', IF(action IN (3, 4, 5), sourceA, 0) AS param FROM ?_account_reputation WHERE userId = ?d', User::$id)) { foreach ($repData as &$r) { $r['when'] = date(Util::$dateFormatInternal, $r['when']); } $this->lvTabs[] = ['reputationhistory', ['data' => $repData]]; } // comments if ($_ = CommunityContent::getCommentPreviews(['user' => User::$id, 'replies' => false])) { // needs foundCount for params // _totalCount: 377, // note: $WH.sprintf(LANG.lvnote_usercomments, 377), $this->lvTabs[] = ['commentpreview', array('data' => $_, 'hiddenCols' => ['author'], 'onBeforeCreate' => '$Listview.funcBox.beforeUserComments')]; } // replies if ($_ = CommunityContent::getCommentPreviews(['user' => User::$id, 'replies' => true])) { // needs commentid (parentComment) for data // needs foundCount for params // _totalCount: 377, // note: $WH.sprintf(LANG.lvnote_usercomments, 377), $this->lvTabs[] = ['replypreview', array('data' => $_, 'hiddenCols' => ['author'])]; } /* <div id="description" class="left"><div id="description-generic"></div> <script type="text/javascript">//<![CDATA[ Markup.printHtml("description text here", "description-generic", { allow: Markup.CLASS_PREMIUM, roles: "256" }); //]]></script> </div> <script type="text/javascript">us_addDescription()</script> */ // claimed characters // profiles // own screenshots // own videos // own comments (preview) // articles guides..? // cpmsg change pass messaeg class:failure|success, msg:blabla }
protected function generateContent() { /***********/ /* Infobox */ /***********/ $infobox = $contrib = $groups = []; foreach (Lang::account('groups') as $idx => $key) { if ($idx >= 0 && $this->user['userGroups'] & 1 << $idx) { $groups[] = (!fMod(count($groups) + 1, 3) ? '[br]' : null) . Lang::account('groups', $idx); } } $infobox[] = Lang::user('joinDate') . Lang::main('colon') . '[tooltip name=joinDate]' . date('l, G:i:s', $this->user['joinDate']) . '[/tooltip][span class=tip tooltip=joinDate]' . date(Lang::main('dateFmtShort'), $this->user['joinDate']) . '[/span]'; $infobox[] = Lang::user('lastLogin') . Lang::main('colon') . '[tooltip name=lastLogin]' . date('l, G:i:s', $this->user['prevLogin']) . '[/tooltip][span class=tip tooltip=lastLogin]' . date(Lang::main('dateFmtShort'), $this->user['prevLogin']) . '[/span]'; $infobox[] = Lang::user('userGroups') . Lang::main('colon') . ($groups ? implode(', ', $groups) : Lang::account('groups', -1)); $infobox[] = Lang::user('consecVisits') . Lang::main('colon') . $this->user['consecutiveVisits']; $infobox[] = Util::ucFirst(Lang::main('siteRep')) . Lang::main('colon') . number_format($this->user['sumRep']); // contrib -> [url=http://www.wowhead.com/client]Data uploads: n [small]([tooltip=tooltip_totaldatauploads]xx.y MB[/tooltip])[/small][/url] $co = DB::Aowow()->selectRow('SELECT COUNT(DISTINCT c.id) AS sum, COUNT(cr.commentId) AS nRates FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id WHERE c.replyTo = 0 AND c.userId = ?d', $this->user['id']); if ($co['sum']) { $contrib[] = Lang::user('comments') . Lang::main('colon') . $co['sum'] . ' [small]([tooltip=tooltip_totalratings]' . $co['nRates'] . '[/tooltip])[/small]'; } $ss = DB::Aowow()->selectRow('SELECT COUNT(id) AS sum, SUM(IF(status & ?d, 1, 0)) as nSticky FROM ?_screenshots WHERE userIdOwner = ?d AND status & ?d AND (status & ?d) = 0', CC_FLAG_STICKY, $this->user['id'], CC_FLAG_APPROVED, CC_FLAG_DELETED); if ($ss['sum']) { $contrib[] = Lang::user('screenshots') . Lang::main('colon') . $ss['sum'] . ' [small]([tooltip=tooltip_normal]' . ($ss['sum'] - $ss['nSticky']) . '[/tooltip] + [tooltip=tooltip_sticky]' . $ss['nSticky'] . '[/tooltip])[/small]'; } $vi = DB::Aowow()->selectRow('SELECT COUNT(id) AS sum, SUM(IF(status & ?d, 1, 0)) as nSticky FROM ?_videos WHERE userIdOwner = ?d AND status & ?d AND (status & ?d) = 0', CC_FLAG_STICKY, $this->user['id'], CC_FLAG_APPROVED, CC_FLAG_DELETED); if ($vi['sum']) { $contrib[] = Lang::user('videos') . Lang::main('colon') . $vi['sum'] . ' [small]([tooltip=tooltip_normal]' . ($vi['sum'] - $vi['nSticky']) . '[/tooltip] + [tooltip=tooltip_sticky]' . $vi['nSticky'] . '[/tooltip])[/small]'; } // contrib -> Forum posts: 5769 [small]([tooltip=topics]579[/tooltip] + [tooltip=replies]5190[/tooltip])[/small] $this->infobox = '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]'; if ($contrib) { $this->contributions = '[ul][li]' . implode('[/li][li]', $contrib) . '[/li][/ul]'; } /****************/ /* Main Content */ /****************/ $this->name = $this->user['title'] ? $this->user['displayName'] . ' <' . $this->user['title'] . '>' : sprintf(Lang::user('profileTitle'), $this->user['displayName']); /**************/ /* Extra Tabs */ /**************/ $this->lvTabs = []; $this->forceTabs = true; // [unused] Site Achievements // Reputation changelog (params only for comment-events) if ($repData = DB::Aowow()->select('SELECT action, amount, date AS \'when\', IF(action IN (3, 4, 5), sourceA, 0) AS param FROM ?_account_reputation WHERE userId = ?d', $this->user['id'])) { foreach ($repData as &$r) { $r['when'] = date(Util::$dateFormatInternal, $r['when']); } $this->lvTabs[] = array('file' => 'reputationhistory', 'data' => $repData, 'params' => []); } // Comments if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => false], $nFound)) { $lvData = array('file' => 'commentpreview', 'data' => $_, 'params' => array('hiddenCols' => "\$['author']", 'onBeforeCreate' => '$Listview.funcBox.beforeUserComments', '_totalCount' => $nFound)); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $lvData['params']['name'] = '$LANG.tab_latestcomments'; $lvData['params']['note'] = '$$WH.sprintf(LANG.lvnote_usercomments, ' . $nFound . ')'; } $this->lvTabs[] = $lvData; } // Comment Replies if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => true], $nFound)) { $lvData = array('file' => 'replypreview', 'data' => $_, 'params' => array('hiddenCols' => "\$['author']", 'onBeforeCreate' => '$Listview.funcBox.beforeUserComments', '_totalCount' => $nFound)); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $lvData['params']['name'] = '$LANG.tab_latestreplies'; $lvData['params']['note'] = '$$WH.sprintf(LANG.lvnote_userreplies, ' . $nFound . ')'; } $this->lvTabs[] = $lvData; } // Screenshots if ($_ = CommunityContent::getScreenshots(-$this->user['id'], 0, $nFound)) { $lvData = array('file' => 'screenshot', 'data' => $_, 'params' => array('_totalCount' => $nFound)); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $lvData['params']['name'] = '$LANG.tab_latestscreenshots'; $lvData['params']['note'] = '$$WH.sprintf(LANG.lvnote_userscreenshots, ' . $nFound . ')'; } $this->lvTabs[] = $lvData; } // Videos if ($_ = CommunityContent::getVideos(-$this->user['id'], 0, $nFound)) { $lvData = array('file' => 'video', 'data' => $_, 'params' => array('_totalCount' => $nFound)); if ($nFound > CFG_SQL_LIMIT_DEFAULT) { $lvData['params']['name'] = '$LANG.tab_latestvideos'; $lvData['params']['note'] = '$$WH.sprintf(LANG.lvnote_uservideos, ' . $nFound . ')'; } $this->lvTabs[] = $lvData; } // forum -> latest topics [unused] // forum -> latest replies [unused] // Characters [todo] $this->user['characterData'] = []; // Profiles [todo] $this->user['profileData'] = []; }