Beispiel #1
0
 protected function generateContent()
 {
     $_level = $this->subject->getField('level');
     $_minLevel = $this->subject->getField('minLevel');
     $_flags = $this->subject->getField('flags');
     $_specialFlags = $this->subject->getField('specialFlags');
     $_side = Util::sideByRaceMask($this->subject->getField('reqRaceMask'));
     /***********/
     /* Infobox */
     /***********/
     $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
     // event (todo: assign eventData)
     if ($_ = $this->subject->getField('eventId')) {
         $this->extendGlobalIds(TYPE_WORLDEVENT, $_);
         $infobox[] = Lang::game('eventShort') . Lang::main('colon') . '[event=' . $_ . ']';
     }
     // level
     if ($_level > 0) {
         $infobox[] = Lang::game('level') . Lang::main('colon') . $_level;
     }
     // reqlevel
     if ($_minLevel) {
         $lvl = $_minLevel;
         if ($_ = $this->subject->getField('maxLevel')) {
             $lvl .= ' - ' . $_;
         }
         $infobox[] = sprintf(Lang::game('reqLevel'), $lvl);
     }
     // loremaster (i dearly hope those flags cover every case...)
     if ($this->subject->getField('zoneOrSortBak') > 0 && !$this->subject->isRepeatable()) {
         $conditions = array(['ac.type', ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE], ['ac.value1', $this->subject->getField('zoneOrSortBak')], ['a.faction', $_side, '&']);
         $loremaster = new AchievementList($conditions);
         $this->extendGlobalData($loremaster->getJSGlobals(GLOBALINFO_SELF));
         switch ($loremaster->getMatches()) {
             case 0:
                 break;
             case 1:
                 $infobox[] = Lang::quest('loremaster') . Lang::main('colon') . '[achievement=' . $loremaster->id . ']';
                 break;
             default:
                 $lm = Lang::quest('loremaster') . Lang::main('colon') . '[ul]';
                 foreach ($loremaster->iterate() as $id => $__) {
                     $lm .= '[li][achievement=' . $id . '][/li]';
                 }
                 $infobox[] = $lm . '[/ul]';
                 break;
         }
     }
     // type (maybe expand uppon?)
     $_ = [];
     if ($_flags & QUEST_FLAG_DAILY) {
         $_[] = Lang::quest('daily');
     } else {
         if ($_flags & QUEST_FLAG_WEEKLY) {
             $_[] = Lang::quest('weekly');
         } else {
             if ($_specialFlags & QUEST_FLAG_SPECIAL_MONTHLY) {
                 $_[] = Lang::quest('monthly');
             }
         }
     }
     if ($t = $this->subject->getField('type')) {
         $_[] = Lang::quest('questInfo', $t);
     }
     if ($_) {
         $infobox[] = Lang::game('type') . Lang::main('colon') . implode(' ', $_);
     }
     // side
     $_ = Lang::main('side') . Lang::main('colon');
     switch ($_side) {
         case 3:
             $infobox[] = $_ . Lang::game('si', 3);
             break;
         case 2:
             $infobox[] = $_ . '[span class=icon-horde]' . Lang::game('si', 2) . '[/span]';
             break;
         case 1:
             $infobox[] = $_ . '[span class=icon-alliance]' . Lang::game('si', 1) . '[/span]';
             break;
     }
     // races
     if ($_ = Lang::getRaceString($this->subject->getField('reqRaceMask'), $__, $jsg, $n, false)) {
         $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') . $_;
     }
     // profession / skill
     if ($_ = $this->subject->getField('reqSkillId')) {
         $this->extendGlobalIds(TYPE_SKILL, $_);
         $sk = '[skill=' . $_ . ']';
         if ($_ = $this->subject->getField('reqSkillPoints')) {
             $sk .= ' (' . $_ . ')';
         }
         $infobox[] = Lang::quest('profession') . Lang::main('colon') . $sk;
     }
     // timer
     if ($_ = $this->subject->getField('timeLimit')) {
         $infobox[] = Lang::quest('timer') . Lang::main('colon') . Util::formatTime($_ * 1000);
     }
     $startEnd = DB::Aowow()->select('SELECT * FROM ?_quests_startend WHERE questId = ?d', $this->typeId);
     // start
     $start = '[icon name=quest_start' . ($this->subject->isDaily() ? '_daily' : '') . ']' . Lang::event('start') . Lang::main('colon') . '[/icon]';
     $s = [];
     foreach ($startEnd as $se) {
         if ($se['method'] & 0x1) {
             $this->extendGlobalIds($se['type'], $se['typeId']);
             $s[] = ($s ? '[span=invisible]' . $start . '[/span] ' : $start . ' ') . '[' . Util::$typeStrings[$se['type']] . '=' . $se['typeId'] . ']';
         }
     }
     if ($s) {
         $infobox[] = implode('[br]', $s);
     }
     // end
     $end = '[icon name=quest_end' . ($this->subject->isDaily() ? '_daily' : '') . ']' . Lang::event('end') . Lang::main('colon') . '[/icon]';
     $e = [];
     foreach ($startEnd as $se) {
         if ($se['method'] & 0x2) {
             $this->extendGlobalIds($se['type'], $se['typeId']);
             $e[] = ($e ? '[span=invisible]' . $end . '[/span] ' : $end . ' ') . '[' . Util::$typeStrings[$se['type']] . '=' . $se['typeId'] . ']';
         }
     }
     if ($e) {
         $infobox[] = implode('[br]', $e);
     }
     // Repeatable
     if ($_flags & QUEST_FLAG_REPEATABLE || $_specialFlags & QUEST_FLAG_SPECIAL_REPEATABLE) {
         $infobox[] = Lang::quest('repeatable');
     }
     // sharable | not sharable
     $infobox[] = $_flags & QUEST_FLAG_SHARABLE ? Lang::quest('sharable') : Lang::quest('notSharable');
     // Keeps you PvP flagged
     if ($this->subject->isPvPEnabled()) {
         $infobox[] = Lang::quest('keepsPvpFlag');
     }
     // difficulty (todo (low): formula unclear. seems to be [minLevel,] -4, -2, (level), +3, +(9 to 15))
     if ($_level > 0) {
         $_ = [];
         // red
         if ($_minLevel && $_minLevel < $_level - 4) {
             $_[] = '[color=q10]' . $_minLevel . '[/color]';
         }
         // orange
         if (!$_minLevel || $_minLevel < $_level - 2) {
             $_[] = '[color=r1]' . (!$_ && $_minLevel > $_level - 4 ? $_minLevel : $_level - 4) . '[/color]';
         }
         // yellow
         $_[] = '[color=r2]' . (!$_ && $_minLevel > $_level - 2 ? $_minLevel : $_level - 2) . '[/color]';
         // green
         $_[] = '[color=r3]' . ($_level + 3) . '[/color]';
         // grey (is about +/-1 level off)
         $_[] = '[color=r4]' . ($_level + 3 + ceil(12 * $_level / MAX_LEVEL)) . '[/color]';
         if ($_) {
             $infobox[] = Lang::game('difficulty') . Lang::main('colon') . implode('[small] &nbsp;[/small]', $_);
         }
     }
     $this->infobox = '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]';
     /**********/
     /* Series */
     /**********/
     // Quest Chain (are there cases where quests go in parallel?)
     $chain = array(array(array('side' => $_side, 'typeStr' => Util::$typeStrings[TYPE_QUEST], 'typeId' => $this->typeId, 'name' => $this->name, '_next' => $this->subject->getField('nextQuestIdChain'))));
     $_ = $chain[0][0];
     while ($_) {
         if ($_ = DB::Aowow()->selectRow('SELECT id AS typeId, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, reqRaceMask FROM ?_quests WHERE nextQuestIdChain = ?d', $_['typeId'])) {
             $n = Util::localizedString($_, 'name');
             array_unshift($chain, array(array('side' => Util::sideByRaceMask($_['reqRaceMask']), 'typeStr' => Util::$typeStrings[TYPE_QUEST], 'typeId' => $_['typeId'], 'name' => strlen($n) > 40 ? substr($n, 0, 40) . '…' : $n)));
         }
     }
     $_ = end($chain)[0];
     while ($_) {
         if ($_ = DB::Aowow()->selectRow('SELECT id AS typeId, name_loc0, name_loc2, name_loc3, name_loc6, name_loc8, reqRaceMask, nextQuestIdChain AS _next FROM ?_quests WHERE id = ?d', $_['_next'])) {
             $n = Util::localizedString($_, 'name');
             array_push($chain, array(array('side' => Util::sideByRaceMask($_['reqRaceMask']), 'typeStr' => Util::$typeStrings[TYPE_QUEST], 'typeId' => $_['typeId'], 'name' => strlen($n) > 40 ? substr($n, 0, 40) . '…' : $n, '_next' => $_['_next'])));
         }
     }
     if (count($chain) > 1) {
         $this->series[] = [$chain, null];
     }
     // todo (low): sensibly merge the following lists into 'series'
     $listGen = function ($cnd) {
         $chain = [];
         $list = new QuestList($cnd);
         if ($list->error) {
             return null;
         }
         foreach ($list->iterate() as $id => $__) {
             $n = $list->getField('name', true);
             $chain[] = array(array('side' => Util::sideByRaceMask($list->getField('reqRaceMask')), 'typeStr' => Util::$typeStrings[TYPE_QUEST], 'typeId' => $id, 'name' => strlen($n) > 40 ? substr($n, 0, 40) . '…' : $n));
         }
         return $chain;
     };
     $extraLists = array(['reqQ', array('OR', ['AND', ['nextQuestId', $this->typeId], ['exclusiveGroup', 0, '<']], ['AND', ['id', $this->subject->getField('prevQuestId')], ['nextQuestIdChain', $this->typeId, '!']])], ['reqOneQ', array(['exclusiveGroup', 0, '>'], ['nextQuestId', $this->typeId])], ['opensQ', array('OR', ['AND', ['prevQuestId', $this->typeId], ['id', $this->subject->getField('nextQuestIdChain'), '!']], ['id', $this->subject->getField('nextQuestId')])], ['closesQ', array(['exclusiveGroup', 0, '!'], ['exclusiveGroup', $this->subject->getField('exclusiveGroup')], ['id', $this->typeId, '!'])], ['enablesQ', array(['prevQuestId', -$this->typeId])], ['enabledByQ', array(['id', -$this->subject->getField('prevQuestId')])]);
     foreach ($extraLists as $el) {
         if ($_ = $listGen($el[1])) {
             $this->series[] = [$_, sprintf(Util::$dfnString, Lang::quest($el[0] . 'Desc'), Lang::quest($el[0]))];
         }
     }
     /*******************/
     /* Objectives List */
     /*******************/
     $this->objectiveList = [];
     $this->providedItem = [];
     // gather ids for lookup
     $olItems = $olNPCs = $olGOs = $olFactions = [];
     // items
     $olItems[0] = array($this->subject->getField('sourceItemId'), $this->subject->getField('sourceItemCount'), false);
     for ($i = 1; $i < 7; $i++) {
         $id = $this->subject->getField('reqItemId' . $i);
         $qty = $this->subject->getField('reqItemCount' . $i);
         if (!$id || !$qty) {
             continue;
         }
         $olItems[$i] = [$id, $qty, $id == $olItems[0][0]];
     }
     if ($ids = array_column($olItems, 0)) {
         $olItemData = new ItemList(array(['id', $ids]));
         $this->extendGlobalData($olItemData->getJSGlobals(GLOBALINFO_SELF));
         $providedRequired = false;
         foreach ($olItems as $i => list($itemId, $qty, $provided)) {
             if (!$i || !$itemId || !in_array($itemId, $olItemData->getFoundIDs())) {
                 continue;
             }
             if ($provided) {
                 $providedRequired = true;
             }
             $this->objectiveList[] = array('typeStr' => Util::$typeStrings[TYPE_ITEM], 'id' => $itemId, 'name' => $olItemData->json[$itemId]['name'], 'qty' => $qty > 1 ? $qty : 0, 'quality' => 7 - $olItemData->json[$itemId]['quality'], 'extraText' => $provided ? '&nbsp;(' . Lang::quest('provided') . ')' : '');
         }
         // if providd item is not required by quest, list it below other requirements
         if (!$providedRequired && $olItems[0][0] && in_array($olItems[0][0], $olItemData->getFoundIDs())) {
             $this->providedItem = array('id' => $olItems[0][0], 'name' => $olItemData->json[$olItems[0][0]]['name'], 'qty' => $olItems[0][1] > 1 ? $olItems[0][1] : 0, 'quality' => 7 - $olItemData->json[$olItems[0][0]]['quality']);
         }
     }
     // creature or GO...
     for ($i = 1; $i < 5; $i++) {
         $id = $this->subject->getField('reqNpcOrGo' . $i);
         $qty = $this->subject->getField('reqNpcOrGoCount' . $i);
         $altTxt = $this->subject->getField('objectiveText' . $i, true);
         if ($id > 0 && $qty) {
             $olNPCs[$id] = [$qty, $altTxt, []];
         } else {
             if ($id < 0 && $qty) {
                 $olGOs[-$id] = [$qty, $altTxt];
             }
         }
     }
     // .. creature kills
     if ($ids = array_keys($olNPCs)) {
         $olNPCData = new CreatureList(array('OR', ['id', $ids], ['killCredit1', $ids], ['killCredit2', $ids]));
         $this->extendGlobalData($olNPCData->getJSGlobals(GLOBALINFO_SELF));
         // create proxy-references
         foreach ($olNPCData->iterate() as $id => $__) {
             if ($p = $olNPCData->getField('KillCredit1')) {
                 if (isset($olNPCs[$p])) {
                     $olNPCs[$p][2][$id] = $olNPCData->getField('name', true);
                 }
             }
             if ($p = $olNPCData->getField('KillCredit2')) {
                 if (isset($olNPCs[$p])) {
                     $olNPCs[$p][2][$id] = $olNPCData->getField('name', true);
                 }
             }
         }
         foreach ($olNPCs as $i => $pair) {
             if (!$i || !in_array($i, $olNPCData->getFoundIDs())) {
                 continue;
             }
             $ol = array('typeStr' => Util::$typeStrings[TYPE_NPC], 'id' => $i, 'name' => $pair[1] ?: Util::localizedString($olNPCData->getEntry($i), 'name'), 'qty' => $pair[0] > 1 ? $pair[0] : 0, 'extraText' => $_specialFlags & QUEST_FLAG_SPECIAL_SPELLCAST || $pair[1] ? '' : ' ' . Lang::achievement('slain'), 'proxy' => $pair[2]);
             if ($pair[2]) {
                 // has proxies assigned, add yourself as another proxy
                 $ol['proxy'][$i] = Util::localizedString($olNPCData->getEntry($i), 'name');
             }
             $this->objectiveList[] = $ol;
         }
     }
     // .. GO interactions
     if ($ids = array_keys($olGOs)) {
         $olGOData = new GameObjectList(array(['id', $ids]));
         $this->extendGlobalData($olGOData->getJSGlobals(GLOBALINFO_SELF));
         foreach ($olNPCs as $i => $pair) {
             if (!$i || !in_array($i, $olGOData->getFoundIDs())) {
                 continue;
             }
             $this->objectiveList[] = array('typeStr' => Util::$typeStrings[TYPE_OBJECT], 'id' => $i, 'name' => $pair[1] ?: Util::localizedString($olGOData->getEntry($i), 'name'), 'qty' => $pair[0] > 1 ? $pair[0] : 0);
         }
     }
     // reputation required
     for ($i = 1; $i < 3; $i++) {
         $id = $this->subject->getField('reqFactionId' . $i);
         $val = $this->subject->getField('reqFactionValue' . $i);
         if (!$id) {
             continue;
         }
         $olFactions[$id] = $val;
     }
     if ($ids = array_keys($olFactions)) {
         $olFactionsData = new FactionList(array(['id', $ids]));
         $this->extendGlobalData($olFactionsData->getJSGlobals(GLOBALINFO_SELF));
         foreach ($olFactions as $i => $val) {
             if (!$i || !in_array($i, $olFactionsData->getFoundIDs())) {
                 continue;
             }
             $this->objectiveList[] = array('typeStr' => Util::$typeStrings[TYPE_FACTION], 'id' => $i, 'name' => Util::localizedString($olFactionsData->getEntry($i), 'name'), 'qty' => sprintf(Util::$dfnString, $val . ' ' . Lang::achievement('points'), Lang::getReputationLevelForPoints($val)), 'extraText' => '');
         }
     }
     // granted spell
     if ($_ = $this->subject->getField('sourceSpellId')) {
         $this->extendGlobalIds(TYPE_SPELL, $_);
         $this->objectiveList[] = array('typeStr' => Util::$typeStrings[TYPE_SPELL], 'id' => $_, 'name' => SpellList::getName($_), 'qty' => 0, 'extraText' => '&nbsp;(' . Lang::quest('provided') . ')');
     }
     // required money
     if ($this->subject->getField('rewardOrReqMoney') < 0) {
         $this->objectiveList[] = ['text' => Lang::quest('reqMoney') . Lang::main('colon') . Util::formatMoney(abs($this->subject->getField('rewardOrReqMoney')))];
     }
     // required pvp kills
     if ($_ = $this->subject->getField('reqPlayerKills')) {
         $this->objectiveList[] = ['text' => Lang::quest('playerSlain') . '&nbsp;(' . $_ . ')'];
     }
     /**********/
     /* Mapper */
     /**********/
     $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']);
     /*
         TODO (GODDAMNIT): jeez..
     */
     // $startend + reqNpcOrGo[1-4]
     $this->map = null;
     // array(
     // 'data' => ['zone' => $this->typeId],
     // 'som'  => Util::toJSON($som)
     // );
     /****************/
     /* Main Content */
     /****************/
     $this->gains = $this->createGains();
     $this->mail = $this->createMail($maTab, $startEnd);
     $this->rewards = $this->createRewards();
     $this->objectives = $this->subject->parseText('objectives', false);
     $this->details = $this->subject->parseText('details', false);
     $this->offerReward = $this->subject->parseText('offerReward', false);
     $this->requestItems = $this->subject->parseText('requestItems', false);
     $this->completed = $this->subject->parseText('completed', false);
     $this->end = $this->subject->parseText('end', false);
     $this->suggestedPl = $this->subject->getField('suggestedPlayers');
     $this->unavailable = $_flags & QUEST_FLAG_UNAVAILABLE || $this->subject->getField('cuFlags') & CUSTOM_EXCLUDE_FOR_LISTVIEW;
     $this->redButtons = array(BUTTON_LINKS => ['color' => 'ffffff00', 'linkId' => 'quest:' . $this->typeId . ':' . $_level . ''], BUTTON_WOWHEAD => true);
     if ($maTab) {
         $this->lvTabs[] = $maTab;
     }
     // factionchange-equivalent
     if ($pendant = DB::World()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_quests WHERE alliance_id = ?d OR horde_id = ?d', $this->typeId, $this->typeId, $this->typeId)) {
         $altQuest = new QuestList(array(['id', abs($pendant)]));
         if (!$altQuest->error) {
             $this->transfer = sprintf(Lang::quest('_transfer'), $altQuest->id, $altQuest->getField('name', true), $pendant > 0 ? 'alliance' : 'horde', $pendant > 0 ? Lang::game('si', 1) : Lang::game('si', 2));
         }
     }
     /**************/
     /* Extra Tabs */
     /**************/
     // tab: see also
     $seeAlso = new QuestList(array(['name_loc' . User::$localeId, '%' . $this->name . '%'], ['id', $this->typeId, '!']));
     if (!$seeAlso->error) {
         $this->extendGlobalData($seeAlso->getJSGlobals());
         $this->lvTabs[] = array('file' => 'quest', 'data' => $seeAlso->getListviewData(), 'params' => array('name' => '$LANG.tab_seealso', 'id' => 'see-also'));
     }
     // tab: criteria of
     $criteriaOf = new AchievementList(array(['ac.type', ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST], ['ac.value1', $this->typeId]));
     if (!$criteriaOf->error) {
         $this->extendGlobalData($criteriaOf->getJSGlobals());
         $this->lvTabs[] = array('file' => 'achievement', 'data' => $criteriaOf->getListviewData(), 'params' => array('name' => '$LANG.tab_criteriaof', 'id' => 'criteria-of'));
     }
     // tab: conditions
     $cnd = [];
     if ($_ = $this->subject->getField('reqMinRepFaction')) {
         $cnd[CND_SRC_QUEST_ACCEPT][$this->typeId][0][] = [CND_REPUTATION_RANK, $_, 1 << Util::getReputationLevelForPoints($this->subject->getField('reqMinRepValue'))];
         $this->extendGlobalIds(TYPE_FACTION, $_);
     }
     if ($_ = $this->subject->getField('reqMaxRepFaction')) {
         $cnd[CND_SRC_QUEST_ACCEPT][$this->typeId][0][] = [-CND_REPUTATION_RANK, $_, 1 << Util::getReputationLevelForPoints($this->subject->getField('reqMaxRepValue'))];
         $this->extendGlobalIds(TYPE_FACTION, $_);
     }
     $_ = Util::getServerConditions([CND_SRC_QUEST_ACCEPT, CND_SRC_QUEST_SHOW_MARK], null, $this->typeId);
     if (!empty($_[0])) {
         // awkward merger
         if (isset($_[0][CND_SRC_QUEST_ACCEPT][$this->typeId][0])) {
             if (isset($cnd[CND_SRC_QUEST_ACCEPT][$this->typeId][0])) {
                 $cnd[CND_SRC_QUEST_ACCEPT][$this->typeId][0] = array_merge($cnd[CND_SRC_QUEST_ACCEPT][$this->typeId][0], $_[0][CND_SRC_QUEST_ACCEPT][$this->typeId][0]);
             } else {
                 $cnd[CND_SRC_QUEST_ACCEPT] = $_[0][CND_SRC_QUEST_ACCEPT];
             }
         }
         if (isset($_[0][CND_SRC_QUEST_SHOW_MARK])) {
             $cnd[CND_SRC_QUEST_SHOW_MARK] = $_[0][CND_SRC_QUEST_SHOW_MARK];
         }
         $this->extendGlobalData($_[1]);
     }
     if ($cnd) {
         $tab = "<script type=\"text/javascript\">\n" . "var markup = ConditionList.createTab(" . Util::toJSON($cnd) . ");\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'));
     }
 }
Beispiel #2
0
 protected function generateContent()
 {
     $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']);
     /***********/
     /* Infobox */
     /***********/
     $this->infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
     // boss
     if ($_ = $this->subject->getField('bossCreature')) {
         $this->extendGlobalIds(TYPE_NPC, $_);
         $this->infobox[] = Lang::npc('rank', 3) . Lang::main('colon') . '[npc=' . $_ . ']';
     }
     // display internal id to staff
     if (User::isInGroup(U_GROUP_STAFF)) {
         $this->infobox[] = 'Event-Id' . Lang::main('colon') . $this->eId;
     }
     /****************/
     /* Main Content */
     /****************/
     // no entry in ?_articles? use default HolidayDescription
     if ($this->hId && empty($this->article)) {
         $this->article = ['text' => Util::jsEscape($this->subject->getField('description', true)), 'params' => []];
     }
     $this->headIcons = [$this->subject->getField('iconString')];
     $this->redButtons = array(BUTTON_WOWHEAD => $this->hId > 0, BUTTON_LINKS => true);
     /**************/
     /* Extra Tabs */
     /**************/
     $hasFilter = in_array($this->hId, [372, 283, 285, 353, 420, 400, 284, 201, 374, 409, 141, 324, 321, 424, 335, 327, 341, 181, 404, 398, 301]);
     // tab: npcs
     if ($npcIds = DB::World()->selectCol('SELECT id AS ARRAY_KEY, IF(ec.eventEntry > 0, 1, 0) AS added FROM creature c, game_event_creature ec WHERE ec.guid = c.guid AND ABS(ec.eventEntry) = ?d', $this->eId)) {
         $creatures = new CreatureList(array(['id', array_keys($npcIds)]));
         if (!$creatures->error) {
             $data = $creatures->getListviewData();
             foreach ($data as &$d) {
                 $d['method'] = $npcIds[$d['id']];
             }
             $tabData = ['data' => array_values($data)];
             if ($hasFilter) {
                 $tabData['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=38;crs=' . $this->hId . ';crv=0');
             }
             $this->lvTabs[] = ['creature', $tabData];
         }
     }
     // tab: objects
     if ($objectIds = DB::World()->selectCol('SELECT id AS ARRAY_KEY, IF(eg.eventEntry > 0, 1, 0) AS added FROM gameobject g, game_event_gameobject eg WHERE eg.guid = g.guid AND ABS(eg.eventEntry) = ?d', $this->eId)) {
         $objects = new GameObjectList(array(['id', array_keys($objectIds)]));
         if (!$objects->error) {
             $data = $objects->getListviewData();
             foreach ($data as &$d) {
                 $d['method'] = $objectIds[$d['id']];
             }
             $tabData = ['data' => array_values($data)];
             if ($hasFilter) {
                 $tabData['note'] = sprintf(Util::$filterResultString, '?objects&filter=cr=16;crs=' . $this->hId . ';crv=0');
             }
             $this->lvTabs[] = ['object', $tabData];
         }
     }
     // tab: achievements
     if ($_ = $this->subject->getField('achievementCatOrId')) {
         $condition = $_ > 0 ? [['category', $_]] : [['id', -$_]];
         $acvs = new AchievementList($condition);
         if (!$acvs->error) {
             $this->extendGlobalData($acvs->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
             $tabData = array('data' => array_values($acvs->getListviewData()), 'visibleCols' => ['category']);
             if ($hasFilter) {
                 $tabData['note'] = sprintf(Util::$filterResultString, '?achievements&filter=cr=11;crs=' . $this->hId . ';crv=0');
             }
             $this->lvTabs[] = ['achievement', $tabData];
         }
     }
     $itemCnd = [];
     if ($this->hId) {
         $itemCnd = array('OR', ['eventId', $this->eId]);
         // tab: quests (by table, go & creature)
         $quests = new QuestList(array(['eventId', $this->eId]));
         if (!$quests->error) {
             $this->extendGlobalData($quests->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
             $tabData = ['data' => array_values($quests->getListviewData())];
             if ($hasFilter) {
                 $tabData['note'] = sprintf(Util::$filterResultString, '?quests&filter=cr=33;crs=' . $this->hId . ';crv=0');
             }
             $this->lvTabs[] = ['quest', $tabData];
             $questItems = [];
             foreach (array_column($quests->rewards, TYPE_ITEM) as $arr) {
                 $questItems = array_merge($questItems, $arr);
             }
             foreach (array_column($quests->requires, TYPE_ITEM) as $arr) {
                 $questItems = array_merge($questItems, $arr);
             }
             if ($questItems) {
                 $itemCnd[] = ['id', $questItems];
             }
         }
     }
     // items from creature
     if ($npcIds && !$creatures->error) {
         // vendor
         $cIds = $creatures->getFoundIDs();
         if ($sells = DB::World()->selectCol('SELECT item FROM npc_vendor nv WHERE entry IN (?a) UNION SELECT item FROM game_event_npc_vendor genv JOIN creature c ON genv.guid = c.guid WHERE c.id IN (?a)', $cIds, $cIds)) {
             $itemCnd[] = ['id', $sells];
         }
     }
     // tab: items
     // not checking for loot ... cant distinguish between eventLoot and fillerCrapLoot
     if ($itemCnd) {
         $eventItems = new ItemList($itemCnd);
         if (!$eventItems->error) {
             $this->extendGlobalData($eventItems->getJSGlobals(GLOBALINFO_SELF));
             $tabData = ['data' => array_values($eventItems->getListviewData())];
             if ($hasFilter) {
                 $tabData['note'] = sprintf(Util::$filterResultString, '?items&filter=cr=160;crs=' . $this->hId . ';crv=0');
             }
             $this->lvTabs[] = ['item', $tabData];
         }
     }
     // tab: see also (event conditions)
     if ($rel = DB::World()->selectCol('SELECT IF(eventEntry = prerequisite_event, NULL, IF(eventEntry = ?d, prerequisite_event, -eventEntry)) FROM game_event_prerequisite WHERE prerequisite_event = ?d OR eventEntry = ?d', $this->eId, $this->eId, $this->eId)) {
         $list = [];
         array_walk($rel, function ($v, $k) use(&$list) {
             if ($v > 0) {
                 $list[] = $v;
             } else {
                 if ($v === null) {
                     trigger_error('game_event_prerequisite: this event has itself as prerequisite', E_USER_WARNING);
                 }
             }
         });
         if ($list) {
             $relEvents = new WorldEventList(array(['id', $list]));
             $this->extendGlobalData($relEvents->getJSGlobals());
             $relData = $relEvents->getListviewData();
             foreach ($relEvents->getFoundIDs() as $id) {
                 $relData[$id]['condition'][0][$this->typeId][] = [[-CND_ACTIVE_EVENT, $this->eId]];
             }
             $this->extendGlobalData($this->subject->getJSGlobals());
             foreach ($rel as $r) {
                 if ($r <= 0) {
                     continue;
                 }
                 $this->extendGlobalIds(TYPE_WORLDEVENT, $r);
                 $d = $this->subject->getListviewData();
                 $d[$this->eId]['condition'][0][$this->typeId][] = [[-CND_ACTIVE_EVENT, $r]];
                 $relData = array_merge($relData, $d);
             }
             $this->lvTabs[] = ['event', array('data' => array_values($relData), 'id' => 'see-also', 'name' => '$LANG.tab_seealso', 'hiddenCols' => ['date'], 'extraCols' => ['$Listview.extraCols.condition'])];
         }
     }
 }