예제 #1
0
function realms()
{
    $realms = [];
    if (DB::isConnectable(DB_AUTH)) {
        $realms = DB::Auth()->select('SELECT id AS ARRAY_KEY, name, ? AS battlegroup, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0 AND gamebuild = ?d', CFG_BATTLEGROUP, WOW_VERSION);
    } else {
        CLISetup::log(' - realms: Auth-DB not set up .. static data g_realms will be empty', CLISetup::LOG_WARN);
    }
    $toFile = "var g_realms = " . Util::toJSON($realms) . ";";
    $file = 'datasets/realms';
    return CLISetup::writeFile($file, $toFile);
}
예제 #2
0
파일: gems.func.php 프로젝트: qyh214/aowow
function gems()
{
    // sketchy, but should work
    // Id < 36'000 || ilevel < 70 ? BC : WOTLK
    $gems = DB::Aowow()->Select('SELECT    i.id AS itemId,
                      i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc4, i.name_loc6, i.name_loc8,
                      IF (i.id < 36000 OR i.itemLevel < 70, 1 , 2) AS expansion,
                      i.quality,
                      ic.iconString AS icon,
                      i.gemEnchantmentId AS enchId,
                      i.gemColorMask AS colors
            FROM      ?_items i
            JOIN      ?_icons ic ON ic.id = -i.displayId
            WHERE     i.gemEnchantmentId <> 0
            ORDER BY  i.id DESC');
    $success = true;
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $enchIds = [];
    foreach ($gems as $pop) {
        $enchIds[] = $pop['enchId'];
    }
    $enchantments = new EnchantmentList(array(['id', $enchIds], CFG_SQL_LIMIT_NONE));
    if ($enchantments->error) {
        CLISetup::log('Required table ?_itemenchantment seems to be empty! Leaving gems()...', CLISetup::LOG_ERROR);
        CLISetup::log();
        return false;
    }
    foreach (CLISetup::$localeIds as $lId) {
        set_time_limit(5);
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $gemsOut = [];
        foreach ($gems as $pop) {
            if (!$enchantments->getEntry($pop['enchId'])) {
                CLISetup::log(' * could not find enchantment #' . $pop['enchId'] . ' referenced by item #' . $gem['itemId'], CLISetup::LOG_WARN);
                continue;
            }
            $gemsOut[$pop['itemId']] = array('name' => Util::localizedString($pop, 'name'), 'quality' => $pop['quality'], 'icon' => strToLower($pop['icon']), 'enchantment' => $enchantments->getField('name', true), 'jsonequip' => $enchantments->getStatGain(), 'colors' => $pop['colors'], 'expansion' => $pop['expansion']);
        }
        $toFile = "var g_gems = " . Util::toJSON($gemsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/gems';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
예제 #3
0
파일: realms.func.php 프로젝트: saqar/aowow
function realms()
{
    $realms = Util::getRealms();
    if (!$realms) {
        CLISetup::log(' - realms: Auth-DB not set up .. static data g_realms will be empty', CLISetup::LOG_WARN);
    } else {
        foreach ($realms as &$r) {
            $r['battlegroup'] = CFG_BATTLEGROUP;
        }
    }
    $toFile = "var g_realms = " . Util::toJSON($realms) . ";";
    $file = 'datasets/realms';
    return CLISetup::writeFile($file, $toFile);
}
예제 #4
0
파일: glyphs.func.php 프로젝트: saqar/aowow
function glyphs()
{
    $success = true;
    $glyphList = DB::Aowow()->Select('SELECT i.id AS itemId,
                   i.*,
                   IF (g.typeFlags & 0x1, 2, 1) AS type,
                   i.subclass AS classs,
                   i.requiredLevel AS level,
                   s1.Id AS glyphSpell,
                   ic.iconString AS icon,
                   s1.skillLine1 AS skillId,
                   s2.Id AS glyphEffect,
                   s2.Id AS ARRAY_KEY
            FROM   ?_items i
            JOIN   ?_spell s1 ON s1.Id = i.spellid1
            JOIN   ?_glyphproperties g ON g.Id = s1.effect1MiscValue
            JOIN   ?_spell s2 ON s2.Id = g.spellId
            JOIN   ?_icons ic ON ic.Id = s1.iconIdAlt
            WHERE  i.classBak = 16');
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE));
    foreach (CLISetup::$localeIds as $lId) {
        set_time_limit(30);
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $glyphsOut = [];
        foreach ($glyphSpells->iterate() as $__) {
            $pop = $glyphList[$glyphSpells->id];
            if (!$pop['glyphEffect']) {
                continue;
            }
            if ($glyphSpells->getField('effect1Id') != 6 && $glyphSpells->getField('effect2Id') != 6 && $glyphSpells->getField('effect3Id') != 6) {
                continue;
            }
            $glyphsOut[$pop['itemId']] = array('name' => Util::localizedString($pop, 'name'), 'description' => $glyphSpells->parseText()[0], 'icon' => $pop['icon'], 'type' => $pop['type'], 'classs' => $pop['classs'], 'skill' => $pop['skillId'], 'level' => $pop['level']);
        }
        $toFile = "var g_glyphs = " . Util::toJSON($glyphsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/glyphs';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
예제 #5
0
파일: pets.func.php 프로젝트: Niknox/aowow
function pets()
{
    $success = true;
    $locations = [];
    $petList = DB::Aowow()->Select('SELECT    cr. id,
                      cr.name_loc0, cr.name_loc2, cr.name_loc3, cr.name_loc6, cr.name_loc8,
                      cr.minLevel,
                      cr.maxLevel,
                      ft.A,
                      ft.H,
                      cr.rank AS classification,
                      cr.family,
                      cr.displayId1 AS displayId,
                      cr.textureString AS skin,
                      LOWER(SUBSTRING_INDEX(cf.iconString, "\\\\", -1)) AS icon,
                      cf.petTalentType AS type
            FROM      ?_creature cr
            JOIN      ?_factiontemplate  ft ON ft.Id = cr.faction
            JOIN      dbc_creaturefamily cf ON cf.id = cr.family
            WHERE     cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0
            ORDER BY  cr.id ASC');
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    foreach (CLISetup::$localeIds as $lId) {
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $petsOut = [];
        foreach ($petList as $pet) {
            // get locations
            // again: caching will save you time and nerves
            if (!isset($locations[$pet['id']])) {
                $locations[$pet['id']] = DB::Aowow()->SelectCol('SELECT DISTINCT areaId FROM ?_spawns WHERE type = ?d AND typeId = ?d', TYPE_NPC, $pet['id']);
            }
            $petsOut[$pet['id']] = array('id' => $pet['id'], 'name' => Util::localizedString($pet, 'name'), 'minlevel' => $pet['minLevel'], 'maxlevel' => $pet['maxLevel'], 'location' => $locations[$pet['id']], 'react' => [$pet['A'], $pet['H']], 'classification' => $pet['classification'], 'family' => $pet['family'], 'displayId' => $pet['displayId'], 'skin' => $pet['skin'], 'icon' => $pet['icon'], 'type' => $pet['type']);
        }
        $toFile = "var g_pets = " . Util::toJSON($petsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/pets';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
예제 #6
0
function gems()
{
    // sketchy, but should work
    // Id < 36'000 || ilevel < 70 ? BC : WOTLK
    $gems = DB::Aowow()->Select('SELECT    i.id AS itemId,
                      i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc6, i.name_loc8,
                      IF (i.id < 36000 OR i.itemLevel < 70, 1 , 2) AS expansion,
                      i.quality,
                      ic.iconString AS icon,
                      i.gemEnchantmentId AS enchId,
                      i.gemColorMask AS colors
            FROM      ?_items i
            JOIN      ?_icons ic ON ic.id = -i.displayId
            WHERE     i.gemEnchantmentId <> 0
            ORDER BY  i.id DESC');
    $success = true;
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $enchIds = [];
    foreach ($gems as $pop) {
        $enchIds[] = $pop['enchId'];
    }
    $enchMisc = [];
    $enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
    foreach (CLISetup::$localeIds as $lId) {
        set_time_limit(5);
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $gemsOut = [];
        foreach ($gems as $pop) {
            $gemsOut[$pop['itemId']] = array('name' => Util::localizedString($pop, 'name'), 'quality' => $pop['quality'], 'icon' => strToLower($pop['icon']), 'enchantment' => Util::localizedString(@$enchMisc[$pop['enchId']]['text'] ?: [], 'text'), 'jsonequip' => @$enchJSON[$pop['enchId']] ?: [], 'colors' => $pop['colors'], 'expansion' => $pop['expansion']);
        }
        $toFile = "var g_gems = " . Util::toJSON($gemsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/gems';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
예제 #7
0
function weightPresets()
{
    // check directory-structure
    if (!CLISetup::writeDir('datasets/')) {
        return false;
    }
    $wtPresets = [];
    $scales = DB::Aowow()->select('SELECT id, name, icon, class FROM ?_account_weightscales WHERE userId = 0 ORDER BY class, id ASC');
    foreach ($scales as $s) {
        $weights = DB::Aowow()->selectCol('SELECT field AS ARRAY_KEY, val FROM ?_account_weightscale_data WHERE id = ?d', $s['id']);
        if (!$weights) {
            CLISetup::log('WeightScale \'' . CLISetup::bold($s['name']) . '\' has no data set. Skipping...', CLISetup::LOG_WARN);
            continue;
        }
        $wtPresets[$s['class']]['pve'][$s['name']] = array_merge(['__icon' => $s['icon']], $weights);
    }
    $toFile = "var wt_presets = " . Util::toJSON($wtPresets) . ";";
    $file = 'datasets/weight-presets';
    if (!CLISetup::writeFile($file, $toFile)) {
        return false;
    }
    return true;
}
예제 #8
0
function dbconfig()
{
    $databases = ['aowow', 'world', 'auth', 'characters'];
    $AoWoWconf = [];
    $dbFields = array('host' => ['Server Host', false], 'user' => ['User', false], 'pass' => ['Password', true], 'db' => ['Database Name', false], 'prefix' => ['Table prefix', false]);
    $testDB = function ($idx, $name, $dbInfo) {
        $buff = '[' . CLISetup::bold($idx) . '] ' . str_pad($name, 17);
        $errStr = '';
        if ($dbInfo['host']) {
            // test DB
            if ($link = @mysqli_connect($dbInfo['host'], $dbInfo['user'], $dbInfo['pass'], $dbInfo['db'])) {
                mysqli_close($link);
            } else {
                $errStr = '[' . mysqli_connect_errno() . '] ' . mysqli_connect_error();
            }
            $buff .= $errStr ? CLISetup::red('ERR   ') : CLISetup::green('OK    ');
            $buff .= 'mysqli://' . $dbInfo['user'] . ':' . str_pad('', strlen($dbInfo['pass']), '*') . '@' . $dbInfo['host'] . '/' . $dbInfo['db'];
            $buff .= ($dbInfo['prefix'] ? '    table prefix: ' . $dbInfo['prefix'] : null) . '    ' . $errStr;
        } else {
            $buff .= '      ' . CLISetup::bold('<empty>');
        }
        return $buff;
    };
    if (file_exists('config/config.php')) {
        require 'config/config.php';
    }
    foreach ($databases as $idx => $name) {
        if (empty($AoWoWconf[$name]) && $name != 'characters') {
            $AoWoWconf[$name] = array_combine(array_keys($dbFields), ['', '', '', '', '']);
        }
    }
    while (true) {
        CLISetup::log();
        CLISetup::log("select a numerical index to use the corresponding entry");
        $nCharDBs = 0;
        foreach ($databases as $idx => $name) {
            if ($idx != 3) {
                CLISetup::log($testDB($idx, $name, $AoWoWconf[$name]));
            } else {
                if (!empty($AoWoWconf[$name])) {
                    foreach ($AoWoWconf[$name] as $charIdx => $dbInfo) {
                        CLISetup::log($testDB($idx + $nCharDBs++, $name . ' [' . $charIdx . ']', $AoWoWconf[$name][$charIdx]));
                    }
                }
            }
        }
        CLISetup::log("[" . CLISetup::bold(3 + $nCharDBs) . "] add an additional Character DB");
        while (true) {
            $inp = ['idx' => ['', true, '/\\d/']];
            if (CLISetup::readInput($inp, true) && $inp) {
                if ($inp['idx'] >= 0 && $inp['idx'] <= 3 + $nCharDBs) {
                    $curFields = $dbFields;
                    if ($inp['idx'] == 3 + $nCharDBs) {
                        // add new realmDB
                        $curFields['realmId'] = ['Realm Id', false, '/[1-9][0-9]*/'];
                    }
                    if (CLISetup::readInput($curFields)) {
                        // auth, world or aowow
                        if ($inp['idx'] < 3) {
                            $AoWoWconf[$databases[$inp['idx']]] = $curFields ?: array_combine(array_keys($dbFields), ['', '', '', '', '']);
                        } else {
                            if ($inp['idx'] == 3 + $nCharDBs) {
                                if ($curFields) {
                                    $_ = $curFields['realmId'];
                                    unset($curFields['realmId']);
                                    $AoWoWconf[$databases[3]][$_] = $curFields;
                                }
                            } else {
                                $i = 0;
                                foreach ($AoWoWconf[$databases[3]] as $realmId => &$dbInfo) {
                                    if ($inp['idx'] - 3 != $i++) {
                                        continue;
                                    }
                                    if ($curFields) {
                                        $dbInfo = $curFields;
                                    } else {
                                        unset($AoWoWconf[$databases[3]][$realmId]);
                                    }
                                }
                            }
                        }
                        // write config file
                        $buff = "<?php\n\nif (!defined('AOWOW_REVISION'))\n    die('illegal access');\n\n\n";
                        foreach ($databases as $db) {
                            if ($db != 'characters') {
                                $buff .= '$AoWoWconf[\'' . $db . '\'] = ' . var_export($AoWoWconf[$db], true) . ";\n\n";
                            } else {
                                foreach ($AoWoWconf[$db] as $idx => $charInfo) {
                                    $buff .= '$AoWoWconf[\'' . $db . '\'][\'' . $idx . '\'] = ' . var_export($AoWoWconf[$db][$idx], true) . ";\n\n";
                                }
                            }
                        }
                        $buff .= "?>\n";
                        CLISetup::log();
                        CLISetup::writeFile('config/config.php', $buff);
                        continue 2;
                    } else {
                        CLISetup::log();
                        CLISetup::log("edit canceled! returning to list...", CLISetup::LOG_WARN);
                        sleep(1);
                        continue 2;
                    }
                }
            } else {
                CLISetup::log();
                CLISetup::log("db setup aborted", CLISetup::LOG_WARN);
                break 2;
            }
        }
    }
}
예제 #9
0
function profiler()
{
    $success = true;
    $scripts = [];
    /**********/
    /* Quests */
    /**********/
    $scripts[] = function () {
        $success = true;
        $condition = [CFG_SQL_LIMIT_NONE, 'AND', [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW], 0], [['flags', QUEST_FLAG_DAILY | QUEST_FLAG_WEEKLY | QUEST_FLAG_REPEATABLE | QUEST_FLAG_AUTO_REWARDED, '&'], 0], [['specialFlags', QUEST_FLAG_SPECIAL_REPEATABLE | QUEST_FLAG_SPECIAL_DUNGEON_FINDER | QUEST_FLAG_SPECIAL_MONTHLY, '&'], 0]];
        $questz = new QuestList($condition);
        $_ = [];
        $currencies = array_column($questz->rewards, TYPE_CURRENCY);
        foreach ($currencies as $curr) {
            foreach ($curr as $cId => $qty) {
                $_[] = $cId;
            }
        }
        $relCurr = new CurrencyList(array(['id', $_]));
        foreach (CLISetup::$localeIds as $l) {
            set_time_limit(20);
            User::useLocale($l);
            Lang::load(Util::$localeStrings[$l]);
            $buff = "var _ = g_gatheredcurrencies;\n";
            foreach ($relCurr->getListviewData() as $id => $data) {
                $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
            }
            $buff .= "\n\nvar _ = g_quests;\n";
            foreach ($questz->getListviewData() as $id => $data) {
                $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
            }
            $buff .= "\ng_quest_catorder = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n";
            if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-quests', $buff)) {
                $success = false;
            }
        }
        return $success;
    };
    /****************/
    /* Achievements */
    /****************/
    $scripts[] = function () {
        $success = true;
        $condition = array(CFG_SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], [['flags', 1, '&'], 0]);
        $achievez = new AchievementList($condition);
        foreach (CLISetup::$localeIds as $l) {
            set_time_limit(5);
            User::useLocale($l);
            Lang::load(Util::$localeStrings[$l]);
            $sumPoints = 0;
            $buff = "var _ = g_achievements;\n";
            foreach ($achievez->getListviewData(ACHIEVEMENTINFO_PROFILE) as $id => $data) {
                $sumPoints += $data['points'];
                $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
            }
            // categories to sort by
            $buff .= "\ng_achievement_catorder = [92, 14863, 97, 169, 170, 171, 172, 14802, 14804, 14803, 14801, 95, 161, 156, 165, 14806, 14921, 96, 201, 160, 14923, 14808, 14805, 14778, 14865, 14777, 14779, 155, 14862, 14861, 14864, 14866, 158, 162, 14780, 168, 14881, 187, 14901, 163, 14922, 159, 14941, 14961, 14962, 14981, 15003, 15002, 15001, 15041, 15042, 81]";
            // sum points
            $buff .= "\ng_achievement_points = [" . $sumPoints . "];\n";
            if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-achievements', $buff)) {
                $success = false;
            }
        }
        return $success;
    };
    /**********/
    /* Titles */
    /**********/
    $scripts[] = function () {
        $success = true;
        $condition = array(CFG_SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0]);
        $titlez = new TitleList($condition);
        foreach (CLISetup::$localeIds as $l) {
            set_time_limit(5);
            User::useLocale($l);
            Lang::load(Util::$localeStrings[$l]);
            foreach ([0, 1] as $g) {
                $buff = "var _ = g_titles;\n";
                foreach ($titlez->getListviewData() as $id => $data) {
                    $data['name'] = Util::localizedString($titlez->getEntry($id), $g ? 'female' : 'male');
                    unset($data['namefemale']);
                    $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
                }
                if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-titles-' . $g, $buff)) {
                    $success = false;
                }
            }
        }
        return $success;
    };
    /**********/
    /* Mounts */
    /**********/
    $scripts[] = function () {
        $success = true;
        $condition = array(CFG_SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], ['typeCat', -5]);
        $mountz = new SpellList($condition);
        foreach (CLISetup::$localeIds as $l) {
            set_time_limit(5);
            User::useLocale($l);
            Lang::load(Util::$localeStrings[$l]);
            $buff = "var _ = g_spells;\n";
            foreach ($mountz->getListviewData(ITEMINFO_MODEL) as $id => $data) {
                $data['quality'] = $data['name'][0];
                $data['name'] = mb_substr($data['name'], 1);
                $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
            }
            if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-mounts', $buff)) {
                $success = false;
            }
        }
        return $success;
    };
    /**************/
    /* Companions */
    /**************/
    $scripts[] = function () {
        $success = true;
        $condition = array(CFG_SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], ['typeCat', -6]);
        $companionz = new SpellList($condition);
        foreach (CLISetup::$localeIds as $l) {
            set_time_limit(5);
            User::useLocale($l);
            Lang::load(Util::$localeStrings[$l]);
            $buff = "var _ = g_spells;\n";
            foreach ($companionz->getListviewData(ITEMINFO_MODEL) as $id => $data) {
                $data['quality'] = $data['name'][0];
                $data['name'] = mb_substr($data['name'], 1);
                $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
            }
            if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-companions', $buff)) {
                $success = false;
            }
        }
        return $success;
    };
    /************/
    /* Factions */
    /************/
    $scripts[] = function () {
        $success = true;
        $condition = array(CFG_SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0]);
        $factionz = new FactionList($condition);
        foreach (CLISetup::$localeIds as $l) {
            set_time_limit(5);
            User::useLocale($l);
            Lang::load(Util::$localeStrings[$l]);
            $buff = "var _ = g_factions;\n";
            foreach ($factionz->getListviewData() as $id => $data) {
                $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
            }
            $buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n";
            if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-factions', $buff)) {
                $success = false;
            }
        }
        return $success;
    };
    /***********/
    /* Recipes */
    /***********/
    $scripts[] = function () {
        // special case: secondary skills are always requested, so put them in one single file (185, 129, 356); it also contains g_skill_order
        $skills = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, [185, 129, 356]];
        $success = true;
        $baseCnd = array(CFG_SQL_LIMIT_NONE, [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], ['effect1Id', [6, 45, 57, 127, 33, 158, 99, 28, 95], '!'], ['effect2Id', [118, 60], '!'], ['OR', ['typeCat', 9], ['typeCat', 11]]);
        foreach ($skills as $s) {
            $file = is_array($s) ? 'sec' : (string) $s;
            $cnd = array_merge($baseCnd, [['skillLine1', $s]]);
            $recipez = new SpellList($cnd);
            $created = '';
            foreach ($recipez->iterate() as $__) {
                foreach ($recipez->canCreateItem() as $idx) {
                    $id = $recipez->getField('effect' . $idx . 'CreateItemId');
                    $created .= "g_items.add(" . $id . ", {'icon':'" . $recipez->relItems->getEntry($id)['iconString'] . "'});\n";
                }
            }
            foreach (CLISetup::$localeIds as $l) {
                set_time_limit(10);
                User::useLocale($l);
                Lang::load(Util::$localeStrings[$l]);
                $buff = '';
                foreach ($recipez->getListviewData() as $id => $data) {
                    $buff .= '_[' . $id . '] = ' . Util::toJSON($data) . ";\n";
                }
                if (!$buff) {
                    // this behaviour is intended, do not create an error
                    CLISetup::log('profiler - file datasets/' . User::$localeString . '/p-recipes-' . $file . ' has no content => skipping', CLISetup::LOG_WARN);
                    continue;
                }
                $buff = $created . "\nvar _ = g_spells;\n" . $buff;
                if (is_array($s)) {
                    $buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n";
                }
                if (!CLISetup::writeFile('datasets/' . User::$localeString . '/p-recipes-' . $file, $buff)) {
                    $success = false;
                }
            }
        }
        return $success;
    };
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    // run scripts
    foreach ($scripts as $func) {
        if (!$func()) {
            $success = false;
        }
    }
    return $success;
}
예제 #10
0
function enchants()
{
    // from g_item_slots: 13:"One-Hand", 26:"Ranged", 17:"Two-Hand",
    $slotPointer = [13, 17, 26, 26, 13, 17, 17, 13, 17, null, 17, null, null, 13, null, 13, null, null, null, null, 17];
    $castItems = [];
    $successs = true;
    $enchantSpells = new SpellList([['effect1Id', 53], ['name_loc0', 'QA%', '!'], CFG_SQL_LIMIT_NONE]);
    // enchantItemPermanent && !qualityAssurance
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $enchIds = [];
    foreach ($enchantSpells->iterate() as $__) {
        $enchIds[] = $enchantSpells->getField('effect1MiscValue');
    }
    $enchMisc = [];
    $enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
    foreach (CLISetup::$localeIds as $lId) {
        set_time_limit(120);
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $enchantsOut = [];
        foreach ($enchantSpells->iterate() as $__) {
            // slots have to be recalculated
            $slot = 0;
            if ($enchantSpells->getField('equippedItemClass') == 4) {
                if ($invType = $enchantSpells->getField('equippedItemInventoryTypeMask')) {
                    $slot = $invType >> 1;
                } else {
                    /* if (equippedItemSubClassMask == 64) */
                    // shields have it their own way <_<
                    $slot = 1 << 14 - 1;
                }
            } else {
                if ($enchantSpells->getField('equippedItemClass') == 2) {
                    foreach ($slotPointer as $i => $sp) {
                        if (!$sp) {
                            continue;
                        }
                        if (1 << $i & $enchantSpells->getField('equippedItemSubClassMask')) {
                            if ($sp == 13) {
                                // also mainHand & offHand *siiigh*
                                $slot |= 1 << 21 - 1 | 1 << 22 - 1;
                            }
                            $slot |= 1 << $sp - 1;
                        }
                    }
                }
            }
            $eId = $enchantSpells->getField('effect1MiscValue');
            // defaults
            $ench = array('name' => [], 'quality' => -1, 'icon' => strToLower($enchantSpells->getField('iconString')), 'source' => [], 'skill' => -1, 'slots' => [], 'enchantment' => Util::localizedString($enchMisc[$eId]['text'], 'text'), 'jsonequip' => @$enchJSON[$eId] ?: [], 'temp' => 0, 'classes' => 0);
            if (isset($enchMisc[$eId]['reqskill'])) {
                $ench['jsonequip']['reqskill'] = $enchMisc[$eId]['reqskill'];
            }
            if (isset($enchMisc[$eId]['reqskillrank'])) {
                $ench['jsonequip']['reqskill'] = $enchMisc[$eId]['reqskillrank'];
            }
            if (isset($enchMisc[$eId]['requiredLevel'])) {
                $ench['jsonequip']['requiredLevel'] = $enchMisc[$eId]['requiredLevel'];
            }
            // check if the spell has an entry in skill_line_ability -> Source:Profession
            if ($skills = $enchantSpells->getField('skillLines')) {
                $ench['name'][] = $enchantSpells->getField('name', true);
                $ench['source'][] = $enchantSpells->id;
                $ench['skill'] = $skills[0];
                $ench['slots'][] = $slot;
            }
            // check if this spell can be cast via item -> Source:Item
            if (!isset($castItems[$enchantSpells->id])) {
                $castItems[$enchantSpells->id] = new ItemList([['spellId1', $enchantSpells->id], ['name_loc0', 'Scroll of Enchant%', '!']]);
            }
            // do not reuse enchantment scrolls
            $cI =& $castItems[$enchantSpells->id];
            // this construct is a bit .. unwieldy
            foreach ($cI->iterate() as $__) {
                $ench['name'][] = $cI->getField('name', true);
                $ench['source'][] = -$cI->id;
                $ench['icon'] = strTolower($cI->getField('iconString'));
                $ench['slots'][] = $slot;
                if ($cI->getField('quality') > $ench['quality']) {
                    $ench['quality'] = $cI->getField('quality');
                }
                if ($cI->getField('requiredClass') > 0) {
                    $ench['classes'] = $cI->getField('requiredClass');
                    $ench['jsonequip']['classes'] = $cI->getField('requiredClass');
                }
                if (!isset($ench['jsonequip']['reqlevel'])) {
                    if ($cI->getField('requiredLevel') > 0) {
                        $ench['jsonequip']['reqlevel'] = $cI->getField('requiredLevel');
                    }
                }
            }
            // enchant spell not in use
            if (empty($ench['source'])) {
                continue;
            }
            // everything gathered
            if (isset($enchantsOut[$eId])) {
                foreach ($enchantsOut[$eId] as $k => $v) {
                    if (is_array($v)) {
                        while ($pop = array_pop($ench[$k])) {
                            $enchantsOut[$eId][$k][] = $pop;
                        }
                    } else {
                        if ($k == 'quality') {
                            if ($enchantsOut[$eId]['source'][0] > 0 && $ench['source'][0] < 0) {
                                $enchantsOut[$eId][$k] = -1;
                            } else {
                                if ($enchantsOut[$eId]['source'][0] < 0 && $ench['source'][0] > 0) {
                                    $enchantsOut[$eId][$k] = -1;
                                } else {
                                    $enchantsOut[$eId][$k] = $ench[$k];
                                }
                            }
                        } else {
                            if ($enchantsOut[$eId][$k] <= 0) {
                                $enchantsOut[$eId][$k] = $ench[$k];
                            }
                        }
                    }
                }
            } else {
                // nothing yet, create new
                $enchantsOut[$eId] = $ench;
            }
        }
        // walk over each entry and strip single-item arrays
        foreach ($enchantsOut as &$ench) {
            foreach ($ench as $k => $v) {
                if (is_array($v) && count($v) == 1 && $k != 'jsonequip') {
                    $ench[$k] = $v[0];
                }
            }
        }
        $toFile = "var g_enchants = " . Util::toJSON($enchantsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/enchants';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $successs;
}
예제 #11
0
function talents()
{
    $success = true;
    $buildTree = function ($class) use(&$petFamIcons, &$tSpells) {
        $petCategories = [];
        $mask = $class ? 1 << $class - 1 : 0;
        // All "tabs" of a given class talent
        $tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE classMask = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $mask);
        $result = [];
        for ($l = 0; $l < count($tabs); $l++) {
            $talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, s.name_loc0, s.name_loc2, s.name_loc3, s.name_loc6, s.name_loc8, LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AS iconString FROM dbc_talent t, dbc_spell s, dbc_spellicon si WHERE si.`Id` = s.`iconId` AND t.`tabId`= ?d AND s.`Id` = t.`rank1` ORDER  by t.`row`, t.`column`', $tabs[$l]['Id']);
            $result[$l] = array('n' => Util::localizedString($tabs[$l], 'name'), 't' => []);
            if (!$class) {
                $petFamId = log($tabs[$l]['creatureFamilyMask'], 2);
                $result[$l]['icon'] = $petFamIcons[$petFamId];
                $petCategories = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, categoryEnumID FROM dbc_creaturefamily WHERE petTalentType = ?d', $petFamId);
                $result[$l]['f'] = array_keys($petCategories);
            }
            // talent dependencies go here
            $depLinks = [];
            $tNums = [];
            for ($j = 0; $j < count($talents); $j++) {
                $tNums[$talents[$j]['tId']] = $j;
                $d = [];
                $s = [];
                $i = $talents[$j]['tId'];
                $n = Util::localizedString($talents[$j], 'name');
                $x = $talents[$j]['column'];
                $y = $talents[$j]['row'];
                $r = null;
                $t = [];
                $icon = $talents[$j]['iconString'];
                $m = $talents[$j]['rank2'] == 0 ? 1 : ($talents[$j]['rank3'] == 0 ? 2 : ($talents[$j]['rank4'] == 0 ? 3 : ($talents[$j]['rank5'] == 0 ? 4 : 5)));
                // duplet handling
                $f = [];
                foreach ($petCategories as $k => $v) {
                    // cant handle 64bit integer .. split
                    if ($v >= 32 && 1 << $v - 32 & $talents[$j]['petCategory2']) {
                        $f[] = $k;
                    } else {
                        if ($v < 32 && 1 << $v & $talents[$j]['petCategory1']) {
                            $f[] = $k;
                        }
                    }
                }
                for ($k = 0; $k <= $m - 1; $k++) {
                    if (!$tSpells->getEntry($talents[$j]['rank' . ($k + 1)])) {
                        continue;
                    }
                    $d[] = $tSpells->parseText()[0];
                    $s[] = $talents[$j]['rank' . ($k + 1)];
                    if ($talents[$j]['talentSpell']) {
                        $t[] = $tSpells->getTalentHeadForCurrent();
                    }
                }
                if ($talents[$j]['reqTalent']) {
                    // we didn't encounter the required talent yet => create reference
                    if (!isset($tNums[$talents[$j]['reqTalent']])) {
                        $depLinks[$talents[$j]['reqTalent']] = $j;
                    }
                    $r = @[$tNums[$talents[$j]['reqTalent']], $talents[$j]['reqRank'] + 1];
                }
                $result[$l]['t'][$j] = array('i' => $i, 'n' => $n, 'm' => $m, 'd' => $d, 's' => $s, 'x' => $x, 'y' => $y);
                if (isset($r)) {
                    $result[$l]['t'][$j]['r'] = $r;
                }
                if (!empty($t)) {
                    $result[$l]['t'][$j]['t'] = $t;
                }
                if (!empty($f)) {
                    $result[$l]['t'][$j]['f'] = $f;
                }
                if ($class) {
                    $result[$l]['t'][$j]['iconname'] = $icon;
                }
                // If this talent is a reference, add it to the array of talent dependencies
                if (isset($depLinks[$talents[$j]['tId']])) {
                    $result[$l]['t'][$depLinks[$talents[$j]['tId']]]['r'][0] = $j;
                    unset($depLinks[$talents[$j]['tId']]);
                }
            }
            // Remove all dependencies for which the talent has not been found
            foreach ($depLinks as $dep_link) {
                unset($result[$l]['t'][$dep_link]['r']);
            }
        }
        return $result;
    };
    // my neighbour is noisy as f**k and my head hurts, so ..
    $petFamIcons = ['Ability_Druid_KingoftheJungle', 'Ability_Druid_DemoralizingRoar', 'Ability_EyeOfTheOwl'];
    // .. i've no idea where to fetch these from
    $classes = [CLASS_WARRIOR, CLASS_PALADIN, CLASS_HUNTER, CLASS_ROGUE, CLASS_PRIEST, CLASS_DEATHKNIGHT, CLASS_SHAMAN, CLASS_MAGE, CLASS_WARLOCK, CLASS_DRUID];
    $petIcons = '';
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $tSpellIds = DB::Aowow()->selectCol('SELECT rank1 FROM dbc_talent UNION SELECT rank2 FROM dbc_talent UNION SELECT rank3 FROM dbc_talent UNION SELECT rank4 FROM dbc_talent UNION SELECT rank5 FROM dbc_talent');
    $tSpells = new SpellList(array(['s.id', $tSpellIds], CFG_SQL_LIMIT_NONE));
    foreach (CLISetup::$localeIds as $lId) {
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        // TalentCalc
        foreach ($classes as $cMask) {
            set_time_limit(20);
            $cId = log($cMask, 2) + 1;
            $file = 'datasets/' . User::$localeString . '/talents-' . $cId;
            $toFile = '$WowheadTalentCalculator.registerClass(' . $cId . ', ' . Util::toJSON($buildTree($cId)) . ')';
            if (!CLISetup::writeFile($file, $toFile)) {
                $success = false;
            }
        }
        // PetCalc
        if (empty($petIcons)) {
            $pets = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS iconString FROM dbc_creaturefamily WHERE petTalentType IN (0, 1, 2)');
            $petIcons = Util::toJSON($pets);
        }
        $toFile = "var g_pet_icons = " . $petIcons . ";\n\n";
        $toFile .= 'var g_pet_talents = ' . Util::toJSON($buildTree(0)) . ';';
        $file = 'datasets/' . User::$localeString . '/pet-talents';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
예제 #12
0
function statistics()
{
    $classs = function () {
        // constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp)
        /*  content per Index
                mleatkpwr[base, strMultiplier, agiMultiplier, levelMultiplier]
                rngatkpwr[base, strMultiplier, agiMultiplier, levelMultiplier]
                baseCritPct[phys, spell]
                diminishingConstant
                baseDodgePct
                DodgeCap
                baseParryPct
                ParryCap
                baseBlockPct
                directMod1   applies mod directly       only one class having something worth mentioning: DK
                directMod2   applies mod directly       so what were they originally used for..?
            */
        $dataz = array(1 => [[-20, 2, 0, 3], [-10, 0, 1, 1], null, 0.956, 3.664, 88.12902099999999, 5, 47.003525, 5, 0, 0], 2 => [[-20, 2, 0, 3], [-10, 0, 1, 0], null, 0.956, 3.4943, 88.12902099999999, 5, 47.003525, 5, 0, 0], 3 => [[-20, 1, 1, 2], [-10, 0, 2, 2], null, 0.988, -4.0873, 145.560408, 5, 145.560408, 0, 0, 0], 4 => [[-20, 1, 1, 2], [-10, 0, 1, 1], null, 0.988, 2.0957, 145.560408, 5, 145.560408, 0, 0, 0], 5 => [[-10, 1, 0, 0], [-10, 0, 1, 0], null, 0.983, 3.4178, 150.37594, 0, 0.0, 0, 0, 0], 6 => [[-20, 2, 0, 3], [-10, 0, 1, 0], null, 0.956, 3.664, 88.12902099999999, 5, 47.003525, 0, 0, ['parryrtng' => [0.25, 'percentOf', 'str']]], 7 => [[-20, 1, 1, 2], [-10, 0, 1, 0], null, 0.988, 2.108, 145.560408, 0, 145.560408, 5, 0, 0], 8 => [[-10, 1, 0, 0], [-10, 0, 1, 0], null, 0.983, 3.6587, 150.37594, 0, 0.0, 0, 0, 0], 9 => [[-10, 1, 0, 0], [-10, 0, 1, 0], null, 0.983, 2.4211, 150.37594, 0, 0.0, 0, 0, 0], 11 => [[-20, 2, 0, 0], [-10, 0, 1, 0], null, 0.972, 5.6097, 116.890707, 0, 0.0, 0, 0, 0]);
        foreach ($dataz as $class => &$data) {
            $data[2] = array_values(DB::Aowow()->selectRow('SELECT mle.chance*100 cMle, spl.chance*100 cSpl FROM dbc_gtchancetomeleecritbase mle, dbc_gtchancetospellcritbase spl WHERE mle.idx = spl.idx AND mle.idx = ?d', $class - 1));
        }
        return $dataz;
    };
    $race = function () {
        // { str, agi, sta, int, spi, hp, mana, directMod1, directMod2 }
        return array(1 => [20, 20, 20, 20, 20, 0, ['spi' => [0.05, 'percentOf', 'spi']]], 2 => [23, 17, 22, 17, 23, 0, 0], 3 => [22, 16, 23, 19, 19, 0, 0], 4 => [17, 25, 19, 20, 20, 0, 0], 5 => [19, 18, 21, 18, 25, 0, 0], 6 => [25, 15, 22, 15, 22, 0, ['health' => [0.05, 'functionOf', '$function(p) { return g_statistics.combo[p.classs][p.level][5]; }']]], 7 => [15, 23, 19, 24, 20, 0, ['int' => [0.05, 'percentOf', 'int']]], 8 => [21, 22, 21, 16, 21, 0, ['healthrgn' => [0.1, 'percentOf', 'healthrgn']]], 10 => [17, 22, 18, 24, 19, 0, 0], 11 => [21, 17, 19, 21, 22, 0, 0]);
    };
    $combo = function () {
        $result = [];
        $critToDodge = array(1 => 0.85 / 1.15, 2 => 1.0 / 1.15, 3 => 1.11 / 1.15, 4 => 2.0 / 1.15, 5 => 1.0 / 1.15, 6 => 0.85 / 1.15, 7 => 1.6 / 1.15, 8 => 1.0 / 1.15, 9 => 0.97 / 1.15, 11 => 2.0 / 1.15);
        // TrinityCore claims, DodgePerAgi per level and class can be constituted from critPerAgi (and level (and class))
        // who am i to argue
        // rebase stats to a specific race. chosen human as all stats are 20
        // level:{ str, agi, sta, int, spi, hp, mana, mleCrt%Agi, splCrt%Int, dodge%Agi, HealthRegenModToBaseStat, HealthRegenModToBonusStat }
        foreach ($critToDodge as $class => $mod) {
            // humans can't be hunter, shaman, druids (use tauren here)
            if (in_array($class, [3, 7, 11])) {
                $offset = [25, 15, 22, 15, 22];
            } else {
                $offset = [20, 20, 20, 20, 20];
            }
            $gtData = DB::Aowow()->select('
                    SELECT mlecrt.idx - ?d AS ARRAY_KEY, mlecrt.chance * 100, splcrt.chance * 100, mlecrt.chance * 100 * ?f, baseHP5.ratio * 1, extraHP5.ratio * 1
                    FROM   dbc_gtchancetomeleecrit mlecrt
                    JOIN   dbc_gtchancetospellcrit splcrt ON splcrt.idx   = mlecrt.idx
                    JOIN   dbc_gtoctregenhp baseHP5       ON baseHP5.idx  = mlecrt.idx
                    JOIN   dbc_gtregenhpperspt extraHP5   ON extraHP5.idx = mlecrt.idx
                    WHERE  mlecrt.idx BETWEEN ?d AND ?d', ($class - 1) * 100 - 1, $mod, ($class - 1) * 100 + 0, ($class - 1) * 100 + 79);
            $rows = DB::World()->select('
                    SELECT
                        pls.level AS ARRAY_KEY,
                        pls.str - ?d, pls.agi - ?d, pls.sta - ?d, pls.inte - ?d, pls.spi - ?d,
                        pcls.basehp, IF(pcls.basemana <> 0, pcls.basemana, 100)
                    FROM
                        player_levelstats pls
                    JOIN
                        player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class
                    WHERE
                        pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC', $offset[0], $offset[1], $offset[2], $offset[3], $offset[4], in_array($class, [3, 7, 11]) ? 6 : 1, $class);
            $result[$class] = [];
            foreach ($rows as $lvl => $row) {
                $result[$class][$lvl] = array_values(array_merge($row, $gtData[$lvl]));
            }
        }
        return $result;
    };
    $level = function () {
        // base mana regeneration per level
        // identical across classes (just use one, that acutally has mana (offset: 100))
        // content of gtRegenMPPerSpt.dbc
        return DB::Aowow()->selectCol('SELECT idx-99 AS ARRAY_KEY, ratio FROM dbc_gtregenmpperspt WHERE idx >= 100 AND idx < 100 + ?d', MAX_LEVEL);
    };
    $skills = function () {
        // profession perks (skinning => +crit, mining => +stam) and maybe some others;      skillId:{rankNo:someJSON, ..}?
        return [];
    };
    // todo:                                         x
    $sub = ['classs', 'race', 'combo', 'level', 'skills'];
    $out = [];
    $success = true;
    foreach ($sub as $s) {
        $res = ${$s}();
        $out[$s] = $res;
        if (!$res) {
            CLISetup::log('statistics - generator $' . $s . '() returned empty', CLISetup::LOG_WARN);
        }
    }
    $toFile = 'g_statistics = ' . preg_replace('/"\\$([^$"]+)"/', '\\1', Util::toJSON($out)) . ';';
    if (!CLISetup::writeFile('datasets/statistics', $toFile)) {
        $success = false;
    }
    return $success;
}
예제 #13
0
function itemsets()
{
    $success = true;
    $setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY refSetId DESC');
    $jsonBonus = [];
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    foreach (CLISetup::$localeIds as $lId) {
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $itemsetOut = [];
        foreach ($setList as $set) {
            set_time_limit(15);
            $setOut = array('id' => $set['id'], 'name' => 7 - $set['quality'] . Util::jsEscape(Util::localizedString($set, 'name')), 'pieces' => [], 'heroic' => !!$set['heroic'], 'maxlevel' => $set['maxLevel'], 'minlevel' => $set['minLevel'], 'type' => $set['type'], 'setbonus' => []);
            if ($set['classMask']) {
                $setOut['reqclass'] = $set['classMask'];
                $setOut['classes'] = [];
                for ($i = 0; $i < 12; $i++) {
                    if ($set['classMask'] & 1 << $i - 1) {
                        $setOut['classes'][] = $i;
                    }
                }
            }
            if ($set['contentGroup']) {
                $setOut['note'] = $set['contentGroup'];
            }
            if ($set['id'] < 0) {
                $setOut['idbak'] = $set['refSetId'];
            }
            for ($i = 1; $i < 11; $i++) {
                if ($set['item' . $i]) {
                    $setOut['pieces'][] = $set['item' . $i];
                }
            }
            for ($i = 1; $i < 9; $i++) {
                if (!$set['bonus' . $i] || !$set['spell' . $i]) {
                    continue;
                }
                // costy and locale-independant -> cache
                if (!isset($jsonBonus[$set['spell' . $i]])) {
                    $jsonBonus[$set['spell' . $i]] = (new SpellList(array(['s.id', (int) $set['spell' . $i]])))->getStatGain()[$set['spell' . $i]];
                }
                if (!isset($setOut['setbonus'][$set['bonus' . $i]])) {
                    $setOut['setbonus'][$set['bonus' . $i]] = $jsonBonus[$set['spell' . $i]];
                } else {
                    foreach ($jsonBonus[$set['spell' . $i]] as $k => $v) {
                        @($setOut['setbonus'][$set['bonus' . $i]][$k] += $v);
                    }
                }
            }
            foreach ($setOut['setbonus'] as $k => $v) {
                if (empty($v)) {
                    unset($setOut['setbonus'][$k]);
                } else {
                    foreach ($v as $sk => $sv) {
                        if ($str = Util::$itemMods[$sk]) {
                            $setOut['setbonus'][$k][$str] = $sv;
                            unset($setOut['setbonus'][$k][$sk]);
                        }
                    }
                }
            }
            if (empty($setOut['setbonus'])) {
                unset($setOut['setbonus']);
            }
            $itemsetOut[$setOut['id']] = $setOut;
        }
        $toFile = "var g_itemsets = " . Util::toJSON($itemsetOut) . ";";
        $file = 'datasets/' . User::$localeString . '/itemsets';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}