示例#1
0
 public function getModelInfo($spellId = 0, $effIdx = 0)
 {
     $displays = [0 => []];
     foreach ($this->iterate() as $id => $__) {
         if ($spellId && $spellId != $id) {
             continue;
         }
         for ($i = 1; $i < 4; $i++) {
             $effMV = $this->curTpl['effect' . $i . 'MiscValue'];
             if (!$effMV) {
                 continue;
             }
             // GO Model from MiscVal
             if (in_array($this->curTpl['effect' . $i . 'Id'], [50, 76, 104, 105, 106, 107])) {
                 if (isset($displays[TYPE_OBJECT][$id])) {
                     $displays[TYPE_OBJECT][$id][0][] = $i;
                 } else {
                     $displays[TYPE_OBJECT][$id] = [[$i], $effMV];
                 }
             } else {
                 if (in_array($this->curTpl['effect' . $i . 'Id'], [28, 90, 134]) || in_array($this->curTpl['effect' . $i . 'AuraId'], [56, 78])) {
                     if (isset($displays[TYPE_NPC][$id])) {
                         $displays[TYPE_NPC][$id][0][] = $i;
                     } else {
                         $displays[TYPE_NPC][$id] = [[$i], $effMV];
                     }
                 } else {
                     if ($this->curTpl['effect' . $i . 'AuraId'] == 36) {
                         $subForms = array(892 => [892, 29407, 29406, 29408, 29405], 8571 => [8571, 29410, 29411, 29412], 2281 => [2281, 29413, 29414, 29416, 29417], 2289 => [2289, 29415, 29418, 29419, 29420, 29421]);
                         if ($st = DB::Aowow()->selectRow('SELECT *, displayIdA as model1, displayIdH as model2 FROM ?_shapeshiftforms WHERE id = ?d', $effMV)) {
                             foreach ([1, 2] as $j) {
                                 if (isset($subForms[$st['model' . $j]])) {
                                     $st['model' . $j] = $subForms[$st['model' . $j]][array_rand($subForms[$st['model' . $j]])];
                                 }
                             }
                             $displays[0][$id][$i] = array('typeId' => 0, 'displayId' => $st['model2'] ? $st['model' . rand(1, 2)] : $st['model1'], 'creatureType' => $st['creatureType'], 'displayName' => Util::localizedString($st, 'name'));
                         }
                     }
                 }
             }
         }
     }
     $results = $displays[0];
     if (!empty($displays[TYPE_NPC])) {
         $nModels = new CreatureList(array(['id', array_column($displays[TYPE_NPC], 1)]));
         foreach ($nModels->iterate() as $nId => $__) {
             $srcId = 0;
             foreach ($displays[TYPE_NPC] as $srcId => $set) {
                 if ($set[1] == $nId) {
                     break;
                 }
             }
             foreach ($set[0] as $idx) {
                 $results[$srcId][$idx] = array('typeId' => $nId, 'displayId' => $nModels->getRandomModelId(), 'displayName' => $nModels->getField('name', true));
             }
         }
     }
     if (!empty($displays[TYPE_OBJECT])) {
         $oModels = new GameObjectList(array(['id', array_column($displays[TYPE_OBJECT], 1)]));
         foreach ($oModels->iterate() as $oId => $__) {
             $srcId = 0;
             foreach ($displays[TYPE_OBJECT] as $srcId => $set) {
                 if ($set[1] == $oId) {
                     break;
                 }
             }
             foreach ($set[0] as $idx) {
                 $results[$srcId][$idx] = array('typeId' => $oId, 'displayId' => $oModels->getField('displayId'), 'displayName' => $oModels->getField('name', true));
             }
         }
     }
     if ($spellId && $effIdx) {
         return !empty($results[$spellId][$effIdx]) ? $results[$spellId][$effIdx] : 0;
     }
     return $results;
 }
示例#2
0
 public function getByItem($entry, $maxResults = CFG_SQL_LIMIT_DEFAULT, $lootTableList = [])
 {
     $this->entry = intVal($entry);
     if (!$this->entry) {
         return false;
     }
     //  [fileName, tabData, tabName, tabId, extraCols, hiddenCols, visibleCols]
     $tabsFinal = array(['item', [], '$LANG.tab_containedin', 'contained-in-item', [], [], []], ['item', [], '$LANG.tab_disenchantedfrom', 'disenchanted-from', [], [], []], ['item', [], '$LANG.tab_prospectedfrom', 'prospected-from', [], [], []], ['item', [], '$LANG.tab_milledfrom', 'milled-from', [], [], []], ['creature', [], '$LANG.tab_droppedby', 'dropped-by', [], [], []], ['creature', [], '$LANG.tab_pickpocketedfrom', 'pickpocketed-from', [], [], []], ['creature', [], '$LANG.tab_skinnedfrom', 'skinned-from', [], [], []], ['creature', [], '$LANG.tab_minedfromnpc', 'mined-from-npc', [], [], []], ['creature', [], '$LANG.tab_salvagedfrom', 'salvaged-from', [], [], []], ['creature', [], '$LANG.tab_gatheredfromnpc', 'gathered-from-npc', [], [], []], ['quest', [], '$LANG.tab_rewardfrom', 'reward-from-quest', [], [], []], ['zone', [], '$LANG.tab_fishedin', 'fished-in-zone', [], [], []], ['object', [], '$LANG.tab_containedin', 'contained-in-object', [], [], []], ['object', [], '$LANG.tab_minedfrom', 'mined-from-object', [], [], []], ['object', [], '$LANG.tab_gatheredfrom', 'gathered-from-object', [], [], []], ['object', [], '$LANG.tab_fishedin', 'fished-in-object', [], [], []], ['spell', [], '$LANG.tab_createdby', 'created-by', [], [], []], ['achievement', [], '$LANG.tab_rewardfrom', 'reward-from-achievement', [], [], []]);
     $refResults = [];
     $chanceMods = [];
     $query = 'SELECT
                         lt1.entry AS ARRAY_KEY,
                         IF(lt1.reference = 0, lt1.item, lt1.reference) AS item,
                         lt1.chance,
                         SUM(IF(lt2.chance = 0, 1, 0)) AS nZeroItems,
                         SUM(lt2.chance) AS sumChance,
                         IF(lt1.groupid > 0, 1, 0) AS isGrouped,
                         IF(lt1.reference = 0, lt1.mincount, 1) AS min,
                         IF(lt1.reference = 0, lt1.maxcount, 1) AS max,
                         IF(lt1.reference > 0, lt1.maxcount, 1) AS multiplier
                     FROM
                         ?# lt1
                     LEFT JOIN
                         ?# lt2 ON lt1.entry = lt2.entry AND lt1.groupid = lt2.groupid
                     WHERE
                         %s
                     GROUP BY lt2.entry, lt2.groupid';
     $calcChance = function ($refs, $parents = []) use(&$chanceMods) {
         $retData = [];
         $retKeys = [];
         foreach ($refs as $rId => $ref) {
             // check for possible database inconsistencies
             if (!$ref['chance'] && !$ref['isGrouped']) {
                 Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: ungrouped Item/Ref ' . $ref['item'] . ' has 0% chance assigned!');
             }
             if ($ref['isGrouped'] && $ref['sumChance'] > 100) {
                 Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: group with Item/Ref ' . $ref['item'] . ' has ' . number_format($ref['sumChance'], 2) . '% total chance! Some items cannot drop!');
             }
             if ($ref['isGrouped'] && $ref['sumChance'] >= 100 && !$ref['chance']) {
                 Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: Item/Ref ' . $ref['item'] . ' with adaptive chance cannot drop. Group already at 100%!');
             }
             $chance = abs($ref['chance'] ?: (100 - $ref['sumChance']) / $ref['nZeroItems']) / 100;
             // apply inherited chanceMods
             if (isset($chanceMods[$ref['item']])) {
                 $chance *= $chanceMods[$ref['item']][0];
                 $chance = 1 - pow(1 - $chance, $chanceMods[$ref['item']][1]);
             }
             // save chance for parent-ref
             $chanceMods[$rId] = [$chance, $ref['multiplier']];
             // refTemplate doesn't point to a new ref -> we are done
             if (!in_array($rId, $parents)) {
                 $data = array('percent' => $chance, 'stack' => [$ref['min'], $ref['max']], 'count' => 1);
                 if ($_ = self::createStack($ref)) {
                     $data['pctstack'] = $_;
                 }
                 // sort highest chances first
                 $i = 0;
                 for (; $i < count($retData); $i++) {
                     if ($retData[$i]['percent'] < $data['percent']) {
                         break;
                     }
                 }
                 array_splice($retData, $i, 0, [$data]);
                 array_splice($retKeys, $i, 0, [$rId]);
             }
         }
         return array_combine($retKeys, $retData);
     };
     /*
         get references containing the item
     */
     $newRefs = DB::World()->select(sprintf($query, 'lt1.item = ?d AND lt1.reference = 0'), LOOT_REFERENCE, LOOT_REFERENCE, $this->entry);
     while ($newRefs) {
         $curRefs = $newRefs;
         $newRefs = DB::World()->select(sprintf($query, 'lt1.reference IN (?a)'), LOOT_REFERENCE, LOOT_REFERENCE, array_keys($curRefs));
         $refResults += $calcChance($curRefs, array_column($newRefs, 'item'));
     }
     /*
         search the real loot-templates for the itemId and gathered refds
     */
     for ($i = 1; $i < count($this->lootTemplates); $i++) {
         if ($lootTableList && !in_array($this->lootTemplates[$i], $lootTableList)) {
             continue;
         }
         $result = $calcChance(DB::World()->select(sprintf($query, '{lt1.reference IN (?a) OR }(lt1.reference = 0 AND lt1.item = ?d)'), $this->lootTemplates[$i], $this->lootTemplates[$i], $refResults ? array_keys($refResults) : DBSIMPLE_SKIP, $this->entry));
         // do not skip here if $result is empty. Additional loot for spells and quest is added separately
         // format for actual use
         foreach ($result as $k => $v) {
             unset($result[$k]);
             $v['percent'] = round($v['percent'] * 100, 3);
             $result[abs($k)] = $v;
         }
         // cap fetched entries to the sql-limit to guarantee, that the highest chance items get selected first
         // screws with GO-loot and skinnig-loot as these templates are shared for several tabs (fish, herb, ore) (herb, ore, leather)
         $ids = array_slice(array_keys($result), 0, $maxResults);
         switch ($this->lootTemplates[$i]) {
             case LOOT_CREATURE:
                 $field = 'lootId';
                 $tabId = 4;
                 break;
             case LOOT_PICKPOCKET:
                 $field = 'pickpocketLootId';
                 $tabId = 5;
                 break;
             case LOOT_SKINNING:
                 $field = 'skinLootId';
                 $tabId = -6;
                 break;
                 // assigned later
             // assigned later
             case LOOT_PROSPECTING:
                 $field = 'id';
                 $tabId = 2;
                 break;
             case LOOT_MILLING:
                 $field = 'id';
                 $tabId = 3;
                 break;
             case LOOT_ITEM:
                 $field = 'id';
                 $tabId = 0;
                 break;
             case LOOT_DISENCHANT:
                 $field = 'disenchantId';
                 $tabId = 1;
                 break;
             case LOOT_FISHING:
                 $field = 'id';
                 $tabId = 11;
                 break;
                 // subAreas are currently ignored
             // subAreas are currently ignored
             case LOOT_GAMEOBJECT:
                 if (!$ids) {
                     continue 2;
                 }
                 $srcObj = new GameObjectList(array(['lootId', $ids]));
                 if ($srcObj->error) {
                     continue 2;
                 }
                 $srcData = $srcObj->getListviewData();
                 foreach ($srcObj->iterate() as $__id => $curTpl) {
                     switch ($curTpl['typeCat']) {
                         case 25:
                             $tabId = 15;
                             break;
                             // fishing node
                         // fishing node
                         case -3:
                             $tabId = 14;
                             break;
                             // herb
                         // herb
                         case -4:
                             $tabId = 13;
                             break;
                             // vein
                         // vein
                         default:
                             $tabId = 12;
                             break;
                             // general chest loot
                     }
                     $tabsFinal[$tabId][1][] = array_merge($srcData[$srcObj->id], $result[$srcObj->getField('lootId')]);
                     $tabsFinal[$tabId][4][] = 'Listview.extraCols.percent';
                     if ($tabId != 15) {
                         $tabsFinal[$tabId][6][] = 'skill';
                     }
                 }
                 continue 2;
             case LOOT_MAIL:
                 // quest part
                 $conditions = array(['rewardChoiceItemId1', $this->entry], ['rewardChoiceItemId2', $this->entry], ['rewardChoiceItemId3', $this->entry], ['rewardChoiceItemId4', $this->entry], ['rewardChoiceItemId5', $this->entry], ['rewardChoiceItemId6', $this->entry], ['rewardItemId1', $this->entry], ['rewardItemId2', $this->entry], ['rewardItemId3', $this->entry], ['rewardItemId4', $this->entry], 'OR');
                 if ($ids) {
                     $conditions[] = ['rewardMailTemplateId', $ids];
                 }
                 $srcObj = new QuestList($conditions);
                 if (!$srcObj->error) {
                     self::storeJSGlobals($srcObj->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
                     $srcData = $srcObj->getListviewData();
                     foreach ($srcObj->iterate() as $_) {
                         $tabsFinal[10][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
                     }
                 }
                 // achievement part
                 $conditions = array(['itemExtra', $this->entry]);
                 if ($ar = DB::World()->selectCol('SELECT entry FROM achievement_reward WHERE item = ?d{ OR mailTemplate IN (?a)}', $this->entry, $ids ?: DBSIMPLE_SKIP)) {
                     array_push($conditions, ['id', $ar], 'OR');
                 }
                 $srcObj = new AchievementList($conditions);
                 if (!$srcObj->error) {
                     self::storeJSGlobals($srcObj->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
                     $srcData = $srcObj->getListviewData();
                     foreach ($srcObj->iterate() as $_) {
                         $tabsFinal[17][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
                     }
                     $tabsFinal[17][5][] = 'rewards';
                     $tabsFinal[17][6][] = 'category';
                 }
                 continue 2;
             case LOOT_SPELL:
                 $conditions = array('OR', ['AND', ['effect1CreateItemId', $this->entry], ['OR', ['effect1Id', SpellList::$effects['itemCreate']], ['effect1AuraId', SpellList::$auras['itemCreate']]]], ['AND', ['effect2CreateItemId', $this->entry], ['OR', ['effect2Id', SpellList::$effects['itemCreate']], ['effect2AuraId', SpellList::$auras['itemCreate']]]], ['AND', ['effect3CreateItemId', $this->entry], ['OR', ['effect3Id', SpellList::$effects['itemCreate']], ['effect3AuraId', SpellList::$auras['itemCreate']]]]);
                 if ($ids) {
                     $conditions[] = ['id', $ids];
                 }
                 $srcObj = new SpellList($conditions);
                 if (!$srcObj->error) {
                     self::storeJSGlobals($srcObj->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
                     $srcData = $srcObj->getListviewData();
                     if (!empty($result)) {
                         $tabsFinal[16][4][] = 'Listview.extraCols.percent';
                     }
                     if ($srcObj->hasSetFields(['reagent1'])) {
                         $tabsFinal[16][6][] = 'reagents';
                     }
                     foreach ($srcObj->iterate() as $_) {
                         $tabsFinal[16][1][] = array_merge($srcData[$srcObj->id], empty($result[$srcObj->id]) ? ['percent' => -1] : $result[$srcObj->id]);
                     }
                 }
                 continue 2;
         }
         if (!$ids) {
             continue;
         }
         switch ($tabsFinal[abs($tabId)][0]) {
             case 'creature':
                 // new CreatureList
             // new CreatureList
             case 'item':
                 // new ItemList
             // new ItemList
             case 'zone':
                 // new ZoneList
                 $oName = ucFirst($tabsFinal[abs($tabId)][0]) . 'List';
                 $srcObj = new $oName(array([$field, $ids]));
                 if (!$srcObj->error) {
                     $srcData = $srcObj->getListviewData();
                     self::storeJSGlobals($srcObj->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
                     foreach ($srcObj->iterate() as $curTpl) {
                         if ($tabId < 0 && $curTpl['typeFlags'] & NPC_TYPEFLAG_HERBLOOT) {
                             $tabId = 9;
                         } else {
                             if ($tabId < 0 && $curTpl['typeFlags'] & NPC_TYPEFLAG_ENGINEERLOOT) {
                                 $tabId = 8;
                             } else {
                                 if ($tabId < 0 && $curTpl['typeFlags'] & NPC_TYPEFLAG_MININGLOOT) {
                                     $tabId = 7;
                                 } else {
                                     if ($tabId < 0) {
                                         $tabId = abs($tabId);
                                     }
                                 }
                             }
                         }
                         // general case (skinning)
                         $tabsFinal[$tabId][1][] = array_merge($srcData[$srcObj->id], $result[$srcObj->getField($field)]);
                         $tabsFinal[$tabId][4][] = 'Listview.extraCols.percent';
                     }
                 }
                 break;
         }
     }
     $this->results = $tabsFinal;
     return true;
 }