private function getOnKillRep($dummyIds, $mapType) { $spilledParents = []; $reputation = []; // base NPC if ($base = $this->getRepForId($this->typeId, $spilledParents)) { $reputation[] = [Lang::npc('modes', 1, 0), $base]; } // difficulty dummys if ($dummyIds && ($mapType == 1 || $mapType == 2)) { $alt = []; $rep = $this->getRepForId(array_keys($dummyIds), $spilledParents); // order by difficulty foreach ($rep as $r) { $alt[$dummyIds[$r['npc']]][] = $r; } // apply by difficulty foreach ($alt as $mode => $dat) { $reputation[] = [Lang::npc('modes', $mapType, $mode), $dat]; } } // get spillover factions and apply if ($spilledParents) { $spilled = new FactionList(array(['parentFactionId', array_keys($spilledParents)])); foreach ($reputation as &$sets) { foreach ($sets[1] as &$row) { if (empty($row['spillover'])) { continue; } foreach ($spilled->iterate() as $spId => $__) { // find parent if ($spilled->getField('parentFactionId') != $row['spillover']) { continue; } // don't readd parent if ($row['id'] == $spId) { continue; } $spMax = $spilledParents[$row['spillover']][1]; $sets[1][] = array('id' => $spId, 'qty' => $spilledParents[$row['spillover']][0], 'name' => $spilled->getField('name', true), 'cap' => $spMax && $spMax < REP_EXALTED ? Lang::game('rep', $spMax) : null); } } } } return $reputation; }
protected function generateContent() { $this->addJS('?data=zones&locale=' . User::$localeId . '&t=' . $_SESSION['dataKey']); /***********/ /* Infobox */ /***********/ $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); // Quartermaster if any if ($ids = $this->subject->getField('qmNpcIds')) { $this->extendGlobalIds(TYPE_NPC, $ids); $qmStr = Lang::faction('quartermaster') . Lang::main('colon'); if (count($ids) == 1) { $qmStr .= '[npc=' . $ids[0] . ']'; } else { if (count($ids) > 1) { $qmStr .= '[ul]'; foreach ($ids as $id) { $qmStr .= '[li][npc=' . $id . '][/li]'; } $qmStr .= '[/ul]'; } } $infobox[] = $qmStr; } // side if any if ($_ = $this->subject->getField('side')) { $infobox[] = Lang::main('side') . Lang::main('colon') . '[span class=icon-' . ($_ == 1 ? 'alliance' : 'horde') . ']' . Lang::game('si', $_) . '[/span]'; } /****************/ /* Main Content */ /****************/ $this->extraText = ''; $this->infobox = $infobox ? '[ul][li]' . implode('[/li][li]', $infobox) . '[/li][/ul]' : null; $this->redButtons = array(BUTTON_WOWHEAD => true, BUTTON_LINKS => true); // Spillover Effects /* todo (low): also check on reputation_spillover_template (but its data is identical to calculation below $rst = DB::World()->selectRow('SELECT CONCAT_WS(" ", faction1, faction2, faction3, faction4) AS faction, CONCAT_WS(" ", rate_1, rate_2, rate_3, rate_4) AS rate, CONCAT_WS(" ", rank_1, rank_2, rank_3, rank_4) AS rank FROM reputation_spillover_template WHERE faction = ?d', $this->typeId); */ $conditions = array(['id', $this->typeId, '!'], ['repIdx', -1, '!']); if ($p = $this->subject->getField('parentFactionId')) { // linked via parent $conditions[] = ['OR', ['id', $p], ['parentFactionId', $p]]; } else { // self as parent $conditions[] = ['parentFactionId', $this->typeId]; } $spillover = new FactionList($conditions); $this->extendGlobalData($spillover->getJSGlobals()); $buff = ''; foreach ($spillover->iterate() as $spillId => $__) { if ($val = $spillover->getField('spilloverRateIn') * $this->subject->getField('spilloverRateOut') * 100) { $buff .= '[tr][td][faction=' . $spillId . '][/td][td][span class=q' . ($val > 0 ? '2]+' : '10]') . $val . '%[/span][/td][td]' . Lang::game('rep', $spillover->getField('spilloverMaxRank')) . '[/td][/tr]'; } } if ($buff) { $this->extraText .= '[h3 class=clear]' . Lang::faction('spillover') . '[/h3][div margin=15px]' . Lang::faction('spilloverDesc') . '[/div][table class=grid width=400px][tr][td width=150px][b]' . Util::ucFirst(Lang::game('faction')) . '[/b][/td][td width=100px][b]' . Lang::spell('_value') . '[/b][/td][td width=150px][b]' . Lang::faction('maxStanding') . '[/b][/td][/tr]' . $buff . '[/table]'; } // reward rates (ultimately this should be calculated into each reward display) if ($rates = DB::World()->selectRow('SELECT * FROM reputation_reward_rate WHERE faction = ?d', $this->typeId)) { $buff = ''; foreach ($rates as $k => $v) { if ($v == 1) { continue; } switch ($k) { case 'quest_rate': $buff .= '[tr][td]' . Lang::game('quests') . Lang::main('colon') . '[/td]'; break; case 'quest_daily_rate': $buff .= '[tr][td]' . Lang::game('quests') . ' (' . Lang::quest('daily') . ')' . Lang::main('colon') . '[/td]'; break; case 'quest_weekly_rate': $buff .= '[tr][td]' . Lang::game('quests') . ' (' . Lang::quest('weekly') . ')' . Lang::main('colon') . '[/td]'; break; case 'quest_monthly_rate': $buff .= '[tr][td]' . Lang::game('quests') . ' (' . Lang::quest('monthly') . ')' . Lang::main('colon') . '[/td]'; break; case 'creature_rate': $buff .= '[tr][td]' . Lang::game('npcs') . Lang::main('colon') . '[/td]'; break; case 'spell_rate': $buff .= '[tr][td]' . Lang::game('spells') . Lang::main('colon') . '[/td]'; break; } $buff .= '[td width=35px align=right][span class=q' . ($v < 1 ? '10]' : '2]+') . intVal(($v - 1) * 100) . '%[/span][/td][/tr]'; } if ($buff) { $this->extraText .= '[h3 class=clear]' . Lang::faction('customRewRate') . '[/h3][table]' . $buff . '[/table]'; } } // factionchange-equivalent if ($pendant = DB::World()->selectCell('SELECT IF(horde_id = ?d, alliance_id, -horde_id) FROM player_factionchange_reputations WHERE alliance_id = ?d OR horde_id = ?d', $this->typeId, $this->typeId, $this->typeId)) { $altFac = new FactionList(array(['id', abs($pendant)])); if (!$altFac->error) { $this->transfer = sprintf(Lang::faction('_transfer'), $altFac->id, $altFac->getField('name', true), $pendant > 0 ? 'alliance' : 'horde', $pendant > 0 ? Lang::game('si', 1) : Lang::game('si', 2)); } } /**************/ /* Extra Tabs */ /**************/ // tab: items $items = new ItemList(array(['requiredFaction', $this->typeId])); if (!$items->error) { $this->extendGlobalData($items->getJSGlobals(GLOBALINFO_SELF)); $tabData = array('data' => array_values($items->getListviewData()), 'extraCols' => '$_', 'sort' => ['standing', 'name']); if ($items->getMatches() > CFG_SQL_LIMIT_DEFAULT) { $tabData['note'] = sprintf(Util::$filterResultString, '?items&filter=cr=17;crs=' . $this->typeId . ';crv=0'); } $this->lvTabs[] = ['item', $tabData, 'itemStandingCol']; } // tab: creatures with onKill reputation if ($this->subject->getField('reputationIndex') != -1) { // inherit siblings/children from $spillover $cRep = DB::World()->selectCol('SELECT DISTINCT creature_id AS ARRAY_KEY, qty FROM ( SELECT creature_id, RewOnKillRepValue1 as qty FROM creature_onkill_reputation WHERE RewOnKillRepValue1 > 0 AND (RewOnKillRepFaction1 = ?d{ OR (RewOnKillRepFaction1 IN (?a) AND IsTeamAward1 <> 0)}) UNION SELECT creature_id, RewOnKillRepValue2 as qty FROM creature_onkill_reputation WHERE RewOnKillRepValue2 > 0 AND (RewOnKillRepFaction2 = ?d{ OR (RewOnKillRepFaction2 IN (?a) AND IsTeamAward2 <> 0)}) ) x', $this->typeId, $spillover->getFoundIDs() ?: DBSIMPLE_SKIP, $this->typeId, $spillover->getFoundIDs() ?: DBSIMPLE_SKIP); if ($cRep) { $killCreatures = new CreatureList(array(['id', array_keys($cRep)])); if (!$killCreatures->error) { $data = $killCreatures->getListviewData(); foreach ($data as $id => &$d) { $d['reputation'] = $cRep[$id]; } $tabData = array('data' => array_values($data), 'extraCols' => '$_', 'sort' => ['-reputation', 'name']); if ($killCreatures->getMatches() > CFG_SQL_LIMIT_DEFAULT) { $tabData['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=42;crs=' . $this->typeId . ';crv=0'); } $this->lvTabs[] = ['creature', $tabData, 'npcRepCol']; } } } // tab: members if ($_ = $this->subject->getField('templateIds')) { $members = new CreatureList(array(['faction', $_])); if (!$members->error) { $tabData = array('data' => array_values($members->getListviewData()), 'id' => 'member', 'name' => '$LANG.tab_members'); if ($members->getMatches() > CFG_SQL_LIMIT_DEFAULT) { $tabData['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=3;crs=' . $this->typeId . ';crv=0'); } $this->lvTabs[] = ['creature', $tabData]; } } // tab: objects if ($_ = $this->subject->getField('templateIds')) { $objects = new GameObjectList(array(['faction', $_])); if (!$objects->error) { $this->lvTabs[] = ['object', ['data' => array_values($objects->getListviewData())]]; } } // tab: quests $conditions = array(['AND', ['rewardFactionId1', $this->typeId], ['rewardFactionValue1', 0, '>']], ['AND', ['rewardFactionId2', $this->typeId], ['rewardFactionValue2', 0, '>']], ['AND', ['rewardFactionId3', $this->typeId], ['rewardFactionValue3', 0, '>']], ['AND', ['rewardFactionId4', $this->typeId], ['rewardFactionValue4', 0, '>']], ['AND', ['rewardFactionId5', $this->typeId], ['rewardFactionValue5', 0, '>']], 'OR'); $quests = new QuestList($conditions); if (!$quests->error) { $this->extendGlobalData($quests->getJSGlobals(GLOBALINFO_ANY)); $tabData = array('data' => array_values($quests->getListviewData($this->typeId)), 'extraCols' => '$_'); if ($quests->getMatches() > CFG_SQL_LIMIT_DEFAULT) { $tabData['note'] = sprintf(Util::$filterResultString, '?quests&filter=cr=1;crs=' . $this->typeId . ';crv=0'); } $this->lvTabs[] = ['quest', $tabData, 'questRepCol']; } // tab: achievements $conditions = array(['ac.type', ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION], ['ac.value1', $this->typeId]); $acvs = new AchievementList($conditions); if (!$acvs->error) { $this->extendGlobalData($acvs->getJSGlobals(GLOBALINFO_ANY)); $this->lvTabs[] = ['achievement', array('data' => array_values($acvs->getListviewData()), 'id' => 'criteria-of', 'name' => '$LANG.tab_criteriaof', 'visibleCols' => ['category'])]; } }
protected function createSQLForCriterium(&$cr) { if (in_array($cr[0], array_keys($this->genericFilter))) { if ($genCr = $this->genericCriterion($cr)) { return $genCr; } unset($cr); $this->error = true; return [1]; } switch ($cr[0]) { case 1: // health [num] if (!$this->isSaneNumeric($cr[2]) || !$this->int2Op($cr[1])) { break; } // remap OP for this special case switch ($cr[1]) { case '=': // min > max is totally possible $this->extraOpts['ct']['h'][] = 'healthMin = healthMax AND healthMin = ' . $cr[2]; break; case '>': $this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMax, healthMin) > ' . $cr[2]; break; case '>=': $this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMax, healthMin) >= ' . $cr[2]; break; case '<': $this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMin, healthMax) < ' . $cr[2]; break; case '<=': $this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMin, healthMax) <= ' . $cr[2]; break; } return [1]; // always true, use post-filter // always true, use post-filter case 2: // mana [num] if (!$this->isSaneNumeric($cr[2]) || !$this->int2Op($cr[1])) { break; } // remap OP for this special case switch ($cr[1]) { case '=': $this->extraOpts['ct']['h'][] = 'manaMin = manaMax AND manaMin = ' . $cr[2]; break; case '>': $this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMin, manaMax) > ' . $cr[2]; break; case '>=': $this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMin, manaMax) >= ' . $cr[2]; break; case '<': $this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMax, manaMin) < ' . $cr[2]; break; case '<=': $this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMax, manaMin) <= ' . $cr[2]; break; } return [1]; // always true, use post-filter // always true, use post-filter case 7: // startsquest [enum] switch ($cr[1]) { case 1: // any return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!']]; case 2: // alliance return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']]; case 3: // horde return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']]; case 4: // both return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]]; case 5: // none $this->extraOpts['ct']['h'][] = 'startsQuests = 0'; return [1]; } break; case 8: // endsquest [enum] switch ($cr[1]) { case 1: // any return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!']]; case 2: // alliance return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']]; case 3: // horde return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']]; case 4: // both return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]]; case 5: // none $this->extraOpts['ct']['h'][] = 'endsQuests = 0'; return [1]; } break; case 3: // faction [enum] if (in_array($cr[1], $this->enums[$cr[0]])) { $facTpls = []; $facs = new FactionList(array('OR', ['parentFactionId', $cr[1]], ['id', $cr[1]])); foreach ($facs->iterate() as $__) { $facTpls = array_merge($facTpls, $facs->getField('templateIds')); } if (!$facTpls) { return [0]; } return ['faction', $facTpls]; } break; case 38: // relatedevent if (!$this->isSaneNumeric($cr[1])) { break; } if ($cr[1] == FILTER_ENUM_ANY) { $eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0'); $cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds); return ['s.guid', $cGuids]; } else { if ($cr[1] == FILTER_ENUM_NONE) { $eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0'); $cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds); return ['s.guid', $cGuids, '!']; } else { if ($cr[1]) { $eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId = ?d', $cr[1]); $cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds); return ['s.guid', $cGuids]; } } } break; case 42: // increasesrepwith [enum] if (in_array($cr[1], $this->enums[3])) { if ($cIds = DB::World()->selectCol('SELECT creature_id FROM creature_onkill_reputation WHERE (RewOnKillRepFaction1 = ?d AND RewOnKillRepValue1 > 0) OR (RewOnKillRepFaction2 = ?d AND RewOnKillRepValue2 > 0)', $cr[1], $cr[1])) { return ['id', $cIds]; } else { return [0]; } } break; case 43: // decreasesrepwith [enum] if (in_array($cr[1], $this->enums[3])) { if ($cIds = DB::World()->selectCol('SELECT creature_id FROM creature_onkill_reputation WHERE (RewOnKillRepFaction1 = ?d AND RewOnKillRepValue1 < 0) OR (RewOnKillRepFaction2 = ?d AND RewOnKillRepValue2 < 0)', $cr[1], $cr[1])) { return ['id', $cIds]; } else { return [0]; } } break; case 12: // averagemoneydropped [op] [int] if (!$this->isSaneNumeric($cr[2]) || !$this->int2Op($cr[1])) { break; } return ['AND', ['((minGold + maxGold) / 2)', $cr[2], $cr[1]]]; case 15: // gatherable [yn] if ($this->int2Bool($cr[1])) { if ($cr[1]) { return ['AND', ['skinLootId', 0, '>'], ['typeFlags', NPC_TYPEFLAG_HERBLOOT, '&']]; } else { return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_HERBLOOT, '&'], 0]]; } } break; case 44: // salvageable [yn] if ($this->int2Bool($cr[1])) { if ($cr[1]) { return ['AND', ['skinLootId', 0, '>'], ['typeFlags', NPC_TYPEFLAG_ENGINEERLOOT, '&']]; } else { return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_ENGINEERLOOT, '&'], 0]]; } } break; case 16: // minable [yn] if ($this->int2Bool($cr[1])) { if ($cr[1]) { return ['AND', ['skinLootId', 0, '>'], ['typeFlags', NPC_TYPEFLAG_MININGLOOT, '&']]; } else { return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_MININGLOOT, '&'], 0]]; } } break; case 10: // skinnable [yn] if ($this->int2Bool($cr[1])) { if ($cr[1]) { return ['AND', ['skinLootId', 0, '>'], [['typeFlags', NPC_TYPEFLAG_SPECIALLOOT, '&'], 0]]; } else { return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_SPECIALLOOT, '&'], 0, '!']]; } } break; case 34: // usemodel [str] // displayId -> id:creatureDisplayInfo.dbc/model -> id:cratureModelData.dbc/modelPath // usemodel [str] // displayId -> id:creatureDisplayInfo.dbc/model -> id:cratureModelData.dbc/modelPath case 41: // haslocation [yn] [staff] /* todo */ return [1]; } unset($cr); $this->error = true; return [1]; }