Пример #1
0
function realmMenu()
{
    $subEU = [];
    $subUS = [];
    $set = 0x0;
    $menu = [['us', 'US & Oceanic', null, [[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subUS]]], ['eu', 'Europe', null, [[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subEU]]]];
    foreach (Util::getRealms() as $row) {
        if ($row['region'] == 'eu') {
            $set |= 0x1;
            $subEU[] = [Util::urlize($row['name']), $row['name']];
        } else {
            if ($row['region'] == 'us') {
                $set |= 0x2;
                $subUS[] = [Util::urlize($row['name']), $row['name']];
            }
        }
    }
    if (!$set) {
        CLISetup::log(' - realmMenu: Auth-DB not set up .. menu will be empty', CLISetup::LOG_WARN);
    }
    if (!($set & 0x1)) {
        array_pop($menu);
    }
    if (!($set & 0x2)) {
        array_shift($menu);
    }
    return Util::toJSON($menu);
}
Пример #2
0
function realmMenu()
{
    $subEU = [];
    $subUS = [];
    $set = 0x0;
    $menu = [['us', 'US & Oceanic', null, [[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subEU]]], ['eu', 'Europe', null, [[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subUS]]]];
    if (DB::isConnectable(DB_AUTH)) {
        $rows = DB::Auth()->select('SELECT name, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0 AND gamebuild = ?d', WOW_VERSION);
        foreach ($rows as $row) {
            if ($row['region'] == 'eu') {
                $set |= 0x1;
                $subEU[] = [Util::urlize($row['name']), $row['name']];
            } else {
                if ($row['region'] == 'us') {
                    $set |= 0x2;
                    $subUS[] = [Util::urlize($row['name']), $row['name']];
                }
            }
        }
    } else {
        CLISetup::log(' - realmMenu: Auth-DB not set up .. menu will be empty', CLISetup::LOG_WARN);
    }
    if (!($set & 0x1)) {
        array_shift($menu);
    }
    if (!($set & 0x2)) {
        array_pop($menu);
    }
    return Util::toJSON($menu);
}
Пример #3
0
function sql($syncMe = null)
{
    require_once 'setup/tools/sqlGen.class.php';
    SqlGen::init($syncMe !== null ? SqlGen::MODE_UPDATE : SqlGen::MODE_NORMAL, $syncMe ?: []);
    $done = [];
    if (SqlGen::$subScripts) {
        $allOk = true;
        // start file generation
        CLISetup::log('begin generation of ' . implode(', ', SqlGen::$subScripts));
        CLISetup::log();
        foreach (SqlGen::$subScripts as $tbl) {
            $syncIds = [];
            // todo: fetch what exactly must be regenerated
            $ok = SqlGen::generate($tbl, $syncIds);
            if (!$ok) {
                $allOk = false;
            } else {
                $done[] = $tbl;
            }
            CLISetup::log(' - subscript \'' . $tbl . '\' returned ' . ($ok ? 'sucessfully' : 'with errors'), $ok ? CLISetup::LOG_OK : CLISetup::LOG_ERROR);
            set_time_limit(SqlGen::$defaultExecTime);
            // reset to default for the next script
        }
        // end
        CLISetup::log();
        if ($allOk) {
            CLISetup::log('successfully finished sql generation', CLISetup::LOG_OK);
        } else {
            CLISetup::log('finished sql generation with errors', CLISetup::LOG_ERROR);
        }
    } else {
        CLISetup::log('no valid script names supplied', CLISetup::LOG_ERROR);
    }
    return $done;
}
Пример #4
0
function build()
{
    require_once 'setup/tools/fileGen.class.php';
    FileGen::init();
    if (FileGen::$subScripts) {
        $allOk = true;
        // start file generation
        CLISetup::log('begin generation of ' . implode(', ', FileGen::$subScripts));
        CLISetup::log();
        // files with template
        foreach (FileGen::$tplFiles as $name => list($file, $destPath, $deps)) {
            $reqDBC = [];
            if (!in_array($name, FileGen::$subScripts)) {
                continue;
            }
            if (!file_exists(FileGen::$tplPath . $file . '.in')) {
                CLISetup::log(sprintf(ERR_MISSING_FILE, FileGen::$tplPath . $file . '.in'), CLISetup::LOG_ERROR);
                $allOk = false;
                continue;
            }
            if (!CLISetup::writeDir($destPath)) {
                continue;
            }
            $syncIds = [];
            // todo: fetch what exactly must be regenerated
            $ok = FileGen::generate($name, $syncIds);
            if (!$ok) {
                $allOk = false;
            }
            CLISetup::log(' - subscript \'' . $file . '\' returned ' . ($ok ? 'sucessfully' : 'with errors'), $ok ? CLISetup::LOG_OK : CLISetup::LOG_ERROR);
            set_time_limit(FileGen::$defaultExecTime);
            // reset to default for the next script
        }
        // files without template
        foreach (FileGen::$datasets as $file => $deps) {
            if (!in_array($file, FileGen::$subScripts)) {
                continue;
            }
            $syncIds = [];
            // todo: fetch what exactly must be regenerated
            $ok = FileGen::generate($file, $syncIds);
            if (!$ok) {
                $allOk = false;
            }
            CLISetup::log(' - subscript \'' . $file . '\' returned ' . ($ok ? 'sucessfully' : 'with errors'), $ok ? CLISetup::LOG_OK : CLISetup::LOG_ERROR);
            set_time_limit(FileGen::$defaultExecTime);
            // reset to default for the next script
        }
        // end
        CLISetup::log();
        if ($allOk) {
            CLISetup::log('successfully finished file generation', CLISetup::LOG_OK);
        } else {
            CLISetup::log('finished file generation with errors', CLISetup::LOG_ERROR);
        }
    } else {
        CLISetup::log('no valid script names supplied', CLISetup::LOG_ERROR);
    }
}
Пример #5
0
function finish()
{
    if (!getopt('d', ['delete'])) {
        // generated with TEMPORARY keyword. Manual deletion is not needed
        CLISetup::log('generated dbc_* - tables kept available', CLISetup::LOG_INFO);
    }
    die("\n");
}
Пример #6
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);
}
Пример #7
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_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;
}
Пример #8
0
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);
}
Пример #9
0
function finish()
{
    if (!getopt('d', ['delete'])) {
        // generated with TEMPORARY keyword. Manual deletion is not needed
        CLISetup::log('generated dbc_* - tables kept available', CLISetup::LOG_INFO);
    }
    // send "i'm in use @" - ping
    $u = !empty($_SERVER['USER']) ? $_SERVER['USER'] : '******';
    $s = !empty($_SERVER['SSH_CONNECTION']) ? explode(' ', $_SERVER['SSH_CONNECTION'])[2] : 'NULL';
    if ($h = @fopen('http://aowow.meedns.com/ref?u=' . $u . '&s=' . $s, 'r')) {
        fclose($h);
    }
    die("\n");
}
Пример #10
0
function update()
{
    list($date, $part) = array_values(DB::Aowow()->selectRow('SELECT `date`, `part` FROM ?_dbversion'));
    CLISetup::log('checking sql updates');
    $nFiles = 0;
    foreach (glob('setup/updates/*.sql') as $file) {
        $pi = pathinfo($file);
        list($fDate, $fPart) = explode('_', $pi['filename']);
        if ($date && $fDate < $date) {
            continue;
        } else {
            if ($part && $date && $fDate == $date && $fPart <= $part) {
                continue;
            }
        }
        $nFiles++;
        $updQuery = '';
        $nQuerys = 0;
        foreach (file($file) as $line) {
            // skip comments
            if (substr($line, 0, 2) == '--' || $line == '') {
                continue;
            }
            $updQuery .= $line;
            // semicolon at the end -> end of query
            if (substr(trim($line), -1, 1) == ';') {
                if (DB::Aowow()->query($updQuery)) {
                    $nQuerys++;
                }
                $updQuery = '';
            }
        }
        DB::Aowow()->query('UPDATE ?_dbversion SET `date`= ?d, `part` = ?d', $fDate, $fPart);
        CLISetup::log(' -> ' . date('d.m.Y', $fDate) . ' #' . $fPart . ': ' . $nQuerys . ' queries applied', CLISetup::LOG_OK);
    }
    CLISetup::log($nFiles ? 'applied ' . $nFiles . ' update(s)' : 'db is already up to date', CLISetup::LOG_OK);
    // fetch sql/build after applying updates, as they may contain sync-prompts
    list($sql, $build) = array_values(DB::Aowow()->selectRow('SELECT `sql`, `build` FROM ?_dbversion'));
    sleep(1);
    $sql = trim($sql) ? array_unique(explode(' ', trim($sql))) : [];
    $build = trim($build) ? array_unique(explode(' ', trim($build))) : [];
    if ($sql) {
        CLISetup::log('The following table(s) require syncing: ' . implode(', ', $sql));
    }
    if ($build) {
        CLISetup::log('The following file(s) require syncing: ' . implode(', ', $build));
    }
    return [$sql, $build];
}
Пример #11
0
function update()
{
    $createQuery = "\r\n        CREATE TABLE `aowow_dbversion` (\r\n            `date` INT(10) UNSIGNED NOT NULL DEFAULT '0',\r\n            `part` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0'\r\n        ) ENGINE=MyISAM";
    $date = $part = 0;
    if (!DB::Aowow()->selectCell('SHOW TABLES LIKE "%dbversion"')) {
        DB::Aowow()->query($createQuery);
        DB::Aowow()->query('INSERT INTO ?_dbversion VALUES (0, 0)');
    } else {
        list($date, $part) = array_values(DB::Aowow()->selectRow('SELECT `date`, `part` FROM ?_dbversion'));
    }
    CLISetup::log('checking sql updates');
    $nFiles = 0;
    foreach (glob('setup/updates/*.sql') as $file) {
        $pi = pathinfo($file);
        list($fDate, $fPart) = explode('_', $pi['filename']);
        if ($date && $fDate < $date) {
            continue;
        } else {
            if ($part && $date && $fDate == $date && $fPart <= $part) {
                continue;
            }
        }
        $nFiles++;
        $updQuery = '';
        $nQuerys = 0;
        foreach (file($file) as $line) {
            // skip comments
            if (substr($line, 0, 2) == '--' || $line == '') {
                continue;
            }
            $updQuery .= $line;
            // semicolon at the end -> end of query
            if (substr(trim($line), -1, 1) == ';') {
                if (DB::Aowow()->query($updQuery)) {
                    $nQuerys++;
                }
                $updQuery = '';
            }
        }
        DB::Aowow()->query('UPDATE ?_dbversion SET `date`= ?d, `part` = ?d', $fDate, $fPart);
        CLISetup::log(' -> ' . date('d.m.Y', $fDate) . ' #' . $fPart . ': ' . $nQuerys . ' queries applied', CLISetup::LOG_OK);
    }
    CLISetup::log($nFiles ? 'applied ' . $nFiles . ' update(s)' : 'db is already up to date', CLISetup::LOG_OK);
}
Пример #12
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;
}
Пример #13
0
function account()
{
    $fields = array('name' => ['Username', false], 'pass1' => ['Enter Password', true], 'pass2' => ['Confirm Password', true]);
    if (CLISetup::readInput($fields)) {
        CLISetup::log();
        if (!User::isValidName($fields['name'], $e)) {
            CLISetup::log(Lang::account($e == 1 ? 'errNameLength' : 'errNameChars'), CLISetup::LOG_ERROR);
        } else {
            if (!User::isValidPass($fields['pass1'], $e)) {
                CLISetup::log(Lang::account($e == 1 ? 'errPassLength' : 'errPassChars'), CLISetup::LOG_ERROR);
            } else {
                if ($fields['pass1'] != $fields['pass2']) {
                    CLISetup::log(Lang::account('passMismatch'), CLISetup::LOG_ERROR);
                } else {
                    if ($_ = DB::Aowow()->SelectCell('SELECT 1 FROM ?_account WHERE user = ? AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $fields['name'], ACC_STATUS_NEW, ACC_STATUS_NEW)) {
                        CLISetup::log(Lang::account('nameInUse'), CLISetup::LOG_ERROR);
                    } else {
                        // write to db
                        $ok = DB::Aowow()->query('REPLACE INTO ?_account (user, passHash, displayName, joindate, email, allowExpire, userGroups, userPerms) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)', $fields['name'], User::hashCrypt($fields['pass1']), Util::ucFirst($fields['name']), CFG_CONTACT_EMAIL, U_GROUP_ADMIN);
                        if ($ok) {
                            $newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $fields['name']);
                            Util::gainSiteReputation($newId, SITEREP_ACTION_REGISTER);
                            CLISetup::log("account " . $fields['name'] . " created successfully", CLISetup::LOG_OK);
                        } else {
                            // something went wrong
                            CLISetup::log(Lang::main('intError'), CLISetup::LOG_ERROR);
                        }
                    }
                }
            }
        }
    } else {
        CLISetup::log();
        CLISetup::log("account creation aborted", CLISetup::LOG_WARN);
    }
}
Пример #14
0
function currencies(array $ids = [])
{
    if (!$ids) {
        DB::Aowow()->query('REPLACE INTO ?_currencies (id, category, itemId) SELECT Id, category, itemId FROM dbc_currencytypes');
    }
    $moneyItems = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, itemId FROM dbc_currencytypes{ WHERE id IN (?a)}', $ids ?: DBSIMPLE_SKIP);
    // apply names
    $moneyNames = DB::World()->select('SELECT it.entry AS ARRAY_KEY, name AS name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM item_template it LEFT JOIN locales_item li ON li.entry = it.entry WHERE it.entry IN (?a)', $moneyItems);
    foreach ($moneyItems as $cId => $itemId) {
        if (!empty($moneyNames[$itemId])) {
            $strings = $moneyNames[$itemId];
        } else {
            CLISetup::log('item #' . $itemId . ' required by currency #' . $cId . ' not in item_template', CLISetup::LOG_WARN);
            $strings = ['name_loc0' => 'Item #' . $itemId . ' not in DB', 'iconId' => -1240, 'cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3];
        }
        DB::Aowow()->query('UPDATE ?_currencies SET ?a WHERE itemId = ?d', $strings, $itemId);
    }
    // apply icons
    $displayIds = DB::World()->selectCol('SELECT entry AS ARRAY_KEY, displayid FROM item_template WHERE entry IN (?a)', $moneyItems);
    foreach ($displayIds as $itemId => $iconId) {
        DB::Aowow()->query('UPDATE ?_currencies SET iconId = ?d WHERE itemId = ?d', -$iconId, $itemId);
    }
    return true;
}
Пример #15
0
function objects(array $ids = [])
{
    $baseQuery = '
        SELECT
            go.entry,
            `type`,
            IF(`type` = 2, -2,                                                                  -- quests 1
                IF(`type` = 8 AND Data0 IN (1, 2, 3, 4, 1552), -6,                              -- tools
                IF(`type` = 3 AND IFNULL(gqi.ItemId, 0) <> 0, -2,                               -- quests 2
                IF(`type` IN (3, 9, 25), `type`, 0)))),                                         -- regular chests, books, pools
            0 AS event,                                                                         -- linked worldevent
            displayId,
            go.name,
            gtl2.`name` AS name_loc2,
            gtl3.`name` AS name_loc3,
            gtl6.`name` AS name_loc6,
            gtl8.`name` AS name_loc8,
            faction,
            flags,
            0 AS cuFlags,                                                                       -- custom Flags
            IF(`type` IN (3, 25), Data1, 0),                                                    -- lootId
            IF(`type` IN (2, 3, 6, 10, 13, 24, 26), Data0, IF(`type` IN (0, 1), Data1, 0)),     -- lockId
            0 AS reqSkill,                                                                      -- reqSkill
            IF(`type` = 9, Data0, IF(`type` = 10, Data7, 0)),                                   -- pageTextId
            IF(`type` = 1, Data3,                                                               -- linkedTrapIds
                IF(`type` = 3, Data7,
                    IF(`type` = 10, Data12,
                        IF(`type` = 8, Data2, 0)))),
            IF(`type` = 5, Data5,                                                               -- reqQuest
                IF(`type` = 3, Data8,
                    IF(`type` = 10, Data1,
                        IF(`type` = 8, Data4, 0)))),
            IF(`type` = 8, Data0, 0),                                                           -- spellFocusId
            IF(`type` = 10, Data10,                                                             -- onUseSpell
                IF(`type` IN (18, 24), Data1,
                    IF(`type` = 26, Data2,
                        IF(`type` = 22, Data0, 0)))),
            IF(`type` = 18, Data4, 0),                                                          -- onSuccessSpell
            IF(`type` = 18, Data2, IF(`type` = 24, Data3, 0)),                                  -- auraSpell
            IF(`type` = 30, Data2, IF(`type` = 24, Data4, IF(`type` = 6, Data3, 0))),           -- triggeredSpell
            IF(`type` = 29, CONCAT_WS(" ", Data14, Data15, Data16, Data17, Data0),              -- miscInfo: capturePoint
                IF(`type` =  3, CONCAT_WS(" ", Data4, Data5, Data2),                            -- miscInfo: loot v
                    IF(`type` = 25, CONCAT_WS(" ", Data2, Data3, 0),
                        IF(`type` = 23, CONCAT_WS(" ", Data0, Data1, Data2), "")))),            -- miscInfo: meetingStone
            IF(ScriptName <> "", ScriptName, AIName)
        FROM
            gameobject_template go
        LEFT JOIN
            gameobject_template_locale gtl2 ON go.entry = gtl2.entry AND gtl2.`locale` = "frFR"
        LEFT JOIN
            gameobject_template_locale gtl3 ON go.entry = gtl3.entry AND gtl3.`locale` = "deDE"
        LEFT JOIN
            gameobject_template_locale gtl6 ON go.entry = gtl6.entry AND gtl6.`locale` = "esES"
        LEFT JOIN
            gameobject_template_locale gtl8 ON go.entry = gtl8.entry AND gtl8.`locale` = "ruRU"
        LEFT JOIN
            gameobject_questitem gqi ON gqi.GameObjectEntry = go.entry
        {
        WHERE
            go.entry IN (?a)
        }
        GROUP BY
            go.entry
        LIMIT
            ?d, ?d';
    $updateQuery = '
        UPDATE
            ?_objects o
        LEFT JOIN
            dbc_lock l ON l.id = IF(o.`type` = 3, lockId, null)
        SET
            typeCat = IF(`type` = 3 AND (l.properties1 = 1 OR l.properties2 = 1), -5,                       -- footlocker
                          IF(`type` = 3 AND (l.properties1 = 2), -3,                                        -- herb
                              IF(`type` = 3 AND (l.properties1 = 3), -4, typeCat))),                        -- ore
            reqSkill = IF(`type` = 3 AND l.properties1 IN (1, 2, 3), IF(l.reqSkill1 > 1, l.reqSkill1, 1),
                           IF(`type` = 3 AND l.properties2 = 1, IF(l.reqSkill2 > 1, l.reqSkill2, 1), 0))
        {
        WHERE
            o.id IN (?a)
        }';
    $offset = 0;
    while ($objects = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, $offset, SqlGen::$stepSize)) {
        CLISetup::log(' * sets ' . ($offset + 1) . ' - ' . ($offset + count($objects)));
        $offset += SqlGen::$stepSize;
        foreach ($objects as $o) {
            DB::Aowow()->query('REPLACE INTO ?_objects VALUES (?a)', array_values($o));
        }
    }
    // apply typeCat and reqSkill depending on locks
    DB::Aowow()->query($updateQuery, $ids ?: DBSIMPLE_SKIP);
    return true;
}
Пример #16
0
function firstrun($resume)
{
    require_once 'setup/tools/sqlGen.class.php';
    require_once 'setup/tools/fileGen.class.php';
    SqlGen::init(true);
    FileGen::init(true);
    /****************/
    /* define steps */
    /****************/
    $steps = array(['dbconfig', null, 'testDB', 'Please enter your database credentials.', 'could not establish connection to:'], ['siteconfig', null, 'testSelf', 'SITE_HOST and STATIC_HOST ' . CLISetup::bold('must') . ' be set. Also enable FORCE_SSL if needed. You may also want to change other variables such as NAME, NAME_SHORT OR LOCALES.', 'could not access:'], ['SqlGen::generate', 'achievementcategory', null, null, null], ['SqlGen::generate', 'achievementcriteria', null, null, null], ['SqlGen::generate', 'glyphproperties', null, null, null], ['SqlGen::generate', 'itemenchantment', null, null, null], ['SqlGen::generate', 'itemenchantmentcondition', null, null, null], ['SqlGen::generate', 'itemextendedcost', null, null, null], ['SqlGen::generate', 'itemlimitcategory', null, null, null], ['SqlGen::generate', 'itemrandomproppoints', null, null, null], ['SqlGen::generate', 'lock', null, null, null], ['SqlGen::generate', 'mailtemplate', null, null, null], ['SqlGen::generate', 'scalingstatdistribution', null, null, null], ['SqlGen::generate', 'scalingstatvalues', null, null, null], ['SqlGen::generate', 'spellfocusobject', null, null, null], ['SqlGen::generate', 'spellrange', null, null, null], ['SqlGen::generate', 'spellvariables', null, null, null], ['SqlGen::generate', 'totemcategory', null, null, null], ['SqlGen::generate', 'classes', null, null, null], ['SqlGen::generate', 'factions', null, null, null], ['SqlGen::generate', 'factiontemplate', null, null, null], ['SqlGen::generate', 'holidays', null, null, null], ['SqlGen::generate', 'icons', null, null, null], ['SqlGen::generate', 'itemrandomenchant', null, null, null], ['SqlGen::generate', 'races', null, null, null], ['SqlGen::generate', 'shapeshiftforms', null, null, null], ['SqlGen::generate', 'skillline', null, null, null], ['SqlGen::generate', 'achievement', null, null, null], ['SqlGen::generate', 'creature', null, null, null], ['SqlGen::generate', 'currencies', null, null, null], ['SqlGen::generate', 'events', null, null, null], ['SqlGen::generate', 'objects', null, null, null], ['SqlGen::generate', 'pet', null, null, null], ['SqlGen::generate', 'quests', null, null, null], ['SqlGen::generate', 'quests_startend', null, null, null], ['SqlGen::generate', 'spell', null, null, null], ['SqlGen::generate', 'spelldifficulty', null, null, null], ['SqlGen::generate', 'taxi', null, null, null], ['SqlGen::generate', 'titles', null, null, null], ['SqlGen::generate', 'items', null, null, null], ['FileGen::generate', 'complexImg', null, null, null], ['SqlGen::generate', 'spawns', null, null, null], ['SqlGen::generate', 'zones', null, null, null], ['SqlGen::generate', 'itemset', null, null, null], ['SqlGen::generate', 'item_stats', null, null, null], ['SqlGen::generate', 'source', null, null, null], ['FileGen::generate', 'searchplugin', null, null, null], ['FileGen::generate', 'power', null, null, null], ['FileGen::generate', 'searchboxScript', null, null, null], ['FileGen::generate', 'demo', null, null, null], ['FileGen::generate', 'searchboxBody', null, null, null], ['FileGen::generate', 'realmMenu', null, null, null], ['FileGen::generate', 'locales', null, null, null], ['FileGen::generate', 'itemScaling', null, null, null], ['FileGen::generate', 'realms', null, null, null], ['FileGen::generate', 'statistics', null, null, null], ['FileGen::generate', 'simpleImg', null, null, null], ['FileGen::generate', 'talents', null, null, null], ['FileGen::generate', 'pets', null, null, null], ['FileGen::generate', 'talentIcons', null, null, null], ['FileGen::generate', 'glyphs', null, null, null], ['FileGen::generate', 'itemsets', null, null, null], ['FileGen::generate', 'enchants', null, null, null], ['FileGen::generate', 'gems', null, null, null], ['FileGen::generate', 'profiler', null, null, null], ['FileGen::generate', 'statistics', null, null, null], ['FileGen::generate', 'statistics', null, null, null], ['update', null, null, null, null], ['account', null, 'testAcc', 'Please create your admin account.', 'There is no user with administrator priviledges in the DB.'], ['endSetup', null, null, null, null]);
    /**********/
    /* helper */
    /**********/
    $saveProgress = function ($nStep) {
        $h = fopen('cache/firstrun', 'w');
        fwrite($h, AOWOW_REVISION . "\n" . ($nStep + 1) . "\n");
        fclose($h);
    };
    $testDB = function (&$error) {
        require 'config/config.php';
        $error = [];
        foreach (['world', 'aowow', 'auth'] as $what) {
            if ($what == 'auth' && (empty($AoWoWconf['auth']) || empty($AoWoWconf['auth']['host']))) {
                continue;
            }
            if ($link = @mysqli_connect($AoWoWconf[$what]['host'], $AoWoWconf[$what]['user'], $AoWoWconf[$what]['pass'], $AoWoWconf[$what]['db'])) {
                mysqli_close($link);
            } else {
                $error[] = ' * ' . $what . ': ' . '[' . mysqli_connect_errno() . '] ' . mysqli_connect_error();
            }
        }
        return empty($error);
    };
    $testSelf = function (&$error) {
        $error = [];
        $test = function ($url, &$rCode) {
            $res = get_headers($url, true);
            if (preg_match("/HTTP\\/[0-9\\.]+\\s+([0-9]+)/", $res[0], $m)) {
                $rCode = $m[1];
                return $m[1] == 200;
            }
            $rCode = 0;
            return false;
        };
        $res = DB::Aowow()->selectCol('SELECT `key` AS ARRAY_KEY, value FROM ?_config WHERE `key` IN ("site_host", "static_host", "force_ssl")');
        $prot = $res['force_ssl'] ? 'https://' : 'http://';
        if ($res['site_host']) {
            if (!$test($prot . $res['site_host'] . '/README', $resp)) {
                $error[] = ' * could not access ' . $prot . $res['site_host'] . '/README [' . $resp . ']';
            }
        } else {
            $error[] = ' * SITE_HOST is empty';
        }
        if ($res['static_host']) {
            if (!$test($prot . $res['static_host'] . '/css/aowow.css', $resp)) {
                $error[] = ' * could not access ' . $prot . $res['static_host'] . '/css/aowow.css [' . $resp . ']';
            }
        } else {
            $error[] = ' * STATIC_HOST is empty';
        }
        return empty($error);
    };
    $testAcc = function (&$error) {
        $error = [];
        return !!DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE userPerms = 1');
    };
    function endSetup()
    {
        return DB::Aowow()->query('UPDATE ?_config SET value = 0 WHERE `key` = "maintenance"');
    }
    /********************/
    /* get current step */
    /********************/
    $startStep = 0;
    if ($resume) {
        if (file_exists('cache/firstrun')) {
            $rows = file('cache/firstrun');
            if ((int) $rows[0] == AOWOW_REVISION) {
                $startStep = (int) $rows[1];
            } else {
                CLISetup::log('firstrun info is outdated! Starting from scratch.', CLISetup::LOG_WARN);
            }
        }
        if (!$startStep) {
            CLISetup::log('no usable info found.', CLISetup::LOG_WARN);
            $inp = ['x' => ['start from scratch? (y/n)', true, '/y|n/i']];
            if (!CLISetup::readInput($inp, true) || !$inp || strtolower($inp['x']) == 'n') {
                CLISetup::log();
                return;
            }
            CLISetup::log();
        } else {
            CLISetup::log('Resuming setup from step ' . $startStep);
            sleep(1);
        }
    }
    /*******/
    /* run */
    /*******/
    foreach ($steps as $idx => $step) {
        if ($startStep > $idx) {
            continue;
        }
        if (!strpos($step[0], '::') && !is_callable($step[0])) {
            require_once 'setup/tools/clisetup/' . $step[0] . '.func.php';
        }
        if ($step[3]) {
            CLISetup::log($step[3]);
            $inp = ['x' => ['Press any key to continue', true]];
            if (!CLISetup::readInput($inp, true)) {
                // we don't actually care about the input
                return;
            }
        }
        while (true) {
            $res = call_user_func($step[0], $step[1]);
            // check script result
            if ($step[2]) {
                if (!${$step}[2]($errors)) {
                    CLISetup::log($step[4], CLISetup::LOG_ERROR);
                    foreach ($errors as $e) {
                        CLISetup::log($e);
                    }
                } else {
                    $saveProgress($idx);
                    break;
                }
            } else {
                if ($res !== false) {
                    $saveProgress($idx);
                    break;
                }
            }
            $inp = ['x' => ['[' . CLISetup::bold('c') . ']ontinue anyway? [' . CLISetup::bold('r') . ']etry? [' . CLISetup::bold('a') . ']bort?', true, '/c|r|a/i']];
            if (CLISetup::readInput($inp, true) && $inp) {
                switch (strtolower($inp['x'])) {
                    case 'c':
                        $saveProgress($idx);
                        break 2;
                    case 'r':
                        CLISetup::log();
                        break;
                    case 'a':
                        CLISetup::log();
                        return;
                }
            } else {
                CLISetup::log();
                return;
            }
        }
    }
    unlink('cache/firstrun');
    CLISetup::log('setup finished', CLISetup::LOG_OK);
}
Пример #17
0
function complexImg()
{
    if (isset(FileGen::$cliOpts['help'])) {
        echo "\n";
        echo "available options for subScript 'complexImg':\n";
        // modeMask
        echo "--talentbgs  (backgrounds for talent calculator)\n";
        // 0x01
        echo "--maps       (generates worldmaps)\n";
        // 0x02
        echo "--spawn-maps (creates alphaMasks of each zone to check spawns against)\n";
        // 0x04
        echo "--artwork    (optional: imagery from /glues/credits (not used, skipped by default))\n";
        // 0x08
        echo "--area-maps  (optional: renders maps with highlighted subZones for each area)\n";
        // 0x10
        return true;
    }
    $mapWidth = 1002;
    $mapHeight = 668;
    $threshold = 95;
    // alpha threshold to define subZones: set it too low and you have unspawnable areas inside a zone; set it too high and the border regions overlap
    $runTime = ini_get('max_execution_time');
    $locStr = null;
    $dbcPath = CLISetup::$srcDir . '%sDBFilesClient/';
    $imgPath = CLISetup::$srcDir . '%sInterface/';
    $destDir = 'static/images/wow/';
    $success = true;
    $paths = ['WorldMap/', 'TalentFrame/', 'Glues/Credits/'];
    $modeMask = 0x7;
    // talentBGs, regular maps, spawn-related alphaMaps
    $createAlphaImage = function ($w, $h) {
        $img = imagecreatetruecolor($w, $h);
        imagesavealpha($img, true);
        imagealphablending($img, false);
        $bgColor = imagecolorallocatealpha($img, 0, 0, 0, 127);
        imagefilledrectangle($img, 0, 0, imagesx($img) - 1, imagesy($img) - 1, $bgColor);
        imagecolortransparent($img, $bgColor);
        imagealphablending($img, true);
        imagecolordeallocate($img, $bgColor);
        return $img;
    };
    // prefer manually converted PNG files (as the imagecreatefromblp-script has issues with some formats)
    // alpha channel issues observed with locale deDE Hilsbrad and Elwynn - maps
    // see: https://github.com/Kanma/BLPConverter
    $loadImageFile = function ($path) {
        $result = null;
        $file = $path . '.png';
        if (CLISetup::fileExists($file)) {
            CLISetup::log('manually converted png file present for ' . $path . '.', CLISetup::LOG_WARN);
            $result = imagecreatefrompng($file);
        }
        if (!$result) {
            $file = $path . '.blp';
            if (CLISetup::fileExists($file)) {
                $result = imagecreatefromblp($file);
            }
        }
        return $result;
    };
    $assembleImage = function ($baseName, $order, $w, $h) use($loadImageFile) {
        $dest = imagecreatetruecolor($w, $h);
        imagesavealpha($dest, true);
        imagealphablending($dest, false);
        $_h = $h;
        foreach ($order as $y => $row) {
            $_w = $w;
            foreach ($row as $x => $suffix) {
                $src = $loadImageFile($baseName . $suffix);
                if (!$src) {
                    CLISetup::log(' - complexImg: tile ' . $baseName . $suffix . '.blp missing.', CLISetup::LOG_ERROR);
                    unset($dest);
                    return null;
                }
                imagecopyresampled($dest, $src, 256 * $x, 256 * $y, 0, 0, min($_w, 256), min($_h, 256), min($_w, 256), min($_h, 256));
                $_w -= 256;
                unset($src);
            }
            $_h -= 256;
        }
        return $dest;
    };
    $writeImage = function ($name, $ext, $src, $w, $h, $done) {
        $ok = false;
        $dest = imagecreatetruecolor($w, $h);
        imagesavealpha($dest, true);
        imagealphablending($dest, false);
        imagecopyresampled($dest, $src, 0, 0, 0, 0, $w, $h, imagesx($src), imagesy($src));
        switch ($ext) {
            case 'jpg':
                $ok = imagejpeg($dest, $name . '.' . $ext, 85);
                break;
            case 'png':
                $ok = imagepng($dest, $name . '.' . $ext);
                break;
            default:
                CLISetup::log($done . ' - unsupported file fromat: ' . $ext, CLISetup::LOG_WARN);
        }
        imagedestroy($dest);
        if ($ok) {
            chmod($name . '.' . $ext, CLISetup::FILE_ACCESS);
            CLISetup::log($done . ' - image ' . $name . '.' . $ext . ' written', CLISetup::LOG_OK);
        } else {
            CLISetup::log($done . ' - could not create image ' . $name . '.' . $ext, CLISetup::LOG_ERROR);
        }
        return $ok;
    };
    $createSpawnMap = function ($img, $zoneId) use($mapHeight, $mapWidth, $threshold) {
        CLISetup::log(' - creating spawn map');
        $tmp = imagecreate(1000, 1000);
        $cbg = imagecolorallocate($tmp, 255, 255, 255);
        $cfg = imagecolorallocate($tmp, 0, 0, 0);
        for ($y = 0; $y < 1000; $y++) {
            for ($x = 0; $x < 1000; $x++) {
                $a = imagecolorat($img, $x * $mapWidth / 1000, $y * $mapHeight / 1000) >> 24;
                imagesetpixel($tmp, $x, $y, $a < $threshold ? $cfg : $cbg);
            }
        }
        imagepng($tmp, 'setup/generated/alphaMaps/' . $zoneId . '.png');
        imagecolordeallocate($tmp, $cbg);
        imagecolordeallocate($tmp, $cfg);
        imagedestroy($tmp);
    };
    $checkSourceDirs = function ($sub, &$missing = []) use($imgPath, $dbcPath, $paths, &$modeMask) {
        $hasMissing = false;
        foreach ($paths as $idx => $subDir) {
            if ($idx == 0 && !($modeMask & 0x16)) {
                // map related
                continue;
            } else {
                if ($idx == 1 && !($modeMask & 0x1)) {
                    // talentBGs
                    continue;
                } else {
                    if ($idx == 2 && !($modeMask & 0x8)) {
                        // artwork
                        continue;
                    }
                }
            }
            $p = sprintf($imgPath, $sub) . $subDir;
            if (!CLISetup::fileExists($p)) {
                $hasMissing = true;
                $missing[] = $p;
            }
        }
        if ($modeMask & 0x17) {
            $p = sprintf($dbcPath, $sub);
            if (!CLISetup::fileExists($p)) {
                $hasMissing = true;
                $missing[] = $p;
            }
        }
        return !$hasMissing;
    };
    // do not change order of params!
    if ($_ = FileGen::hasOpt('talentbgs', 'maps', 'spawn-maps', 'artwork', 'area-maps')) {
        $modeMask = $_;
    }
    foreach (CLISetup::$expectedPaths as $xp => $__) {
        if ($xp) {
            // if in subDir add trailing slash
            $xp .= '/';
        }
        if ($checkSourceDirs($xp, $missing)) {
            $locStr = $xp;
            break;
        }
    }
    // if no subdir had sufficient data, diaf
    if ($locStr === null) {
        CLISetup::log('one or more required directories are missing:', CLISetup::LOG_ERROR);
        foreach ($missing as $m) {
            CLISetup::log(' - ' . $m, CLISetup::LOG_ERROR);
        }
        return;
    }
    /**************/
    /* TalentTabs */
    /**************/
    if ($modeMask & 0x1) {
        if (CLISetup::writeDir($destDir . 'hunterpettalents/') && CLISetup::writeDir($destDir . 'talents/backgrounds/')) {
            // [classMask, creatureFamilyMask, tabNr, textureStr]
            $tTabs = DB::Aowow()->select('SELECT tt.creatureFamilyMask, tt.textureFile, tt.tabNumber, cc.fileString FROM dbc_talenttab tt LEFT JOIN dbc_chrclasses cc ON cc.Id = (LOG(2, tt.classMask) + 1)');
            $order = array(['-TopLeft', '-TopRight'], ['-BottomLeft', '-BottomRight']);
            if ($tTabs) {
                $sum = 0;
                $total = count($tTabs);
                CLISetup::log('Processing ' . $total . ' files from TalentFrame/ ...');
                foreach ($tTabs as $tt) {
                    ini_set('max_execution_time', 30);
                    // max 30sec per image (loading takes the most time)
                    $sum++;
                    $done = ' - ' . str_pad($sum . '/' . $total, 8) . str_pad('(' . number_format($sum * 100 / $total, 2) . '%)', 9);
                    if ($tt['creatureFamilyMask']) {
                        $size = [244, 364];
                        $name = $destDir . 'hunterpettalents/bg_' . (log($tt['creatureFamilyMask'], 2) + 1);
                    } else {
                        $size = [204, 554];
                        $name = $destDir . 'talents/backgrounds/' . strtolower($tt['fileString']) . '_' . ($tt['tabNumber'] + 1);
                    }
                    if (!isset(FileGen::$cliOpts['force']) && file_exists($name . '.jpg')) {
                        CLISetup::log($done . ' - file ' . $name . '.jpg was already processed');
                        continue;
                    }
                    $im = $assembleImage(sprintf($imgPath, $locStr) . 'TalentFrame/' . $tt['textureFile'], $order, 256 + 44, 256 + 75);
                    if (!$im) {
                        CLISetup::log(' - could not assemble file ' . $tt['textureFile'], CLISetup::LOG_ERROR);
                        continue;
                    }
                    if (!$writeImage($name, 'jpg', $im, $size[0], $size[1], $done)) {
                        $success = false;
                    }
                }
            } else {
                $success = false;
            }
            ini_set('max_execution_time', $runTime);
        } else {
            $success = false;
        }
    }
    /************/
    /* Worldmap */
    /************/
    if ($modeMask & 0x16) {
        $mapDirs = array(['maps/%snormal/', 'jpg', 488, 325], ['maps/%soriginal/', 'jpg', 0, 0], ['maps/%ssmall/', 'jpg', 224, 163], ['maps/%szoom/', 'jpg', 772, 515]);
        // as the js expects them
        $baseLevelFix = array(4264 => 1, 4265 => 1, 4415 => 1, 4416 => 1, 4493 => 0, 4500 => 1, 4603 => 1, 4723 => 1, 4809 => 1, 4813 => 1, 4820 => 1, 717 => 1, 3713 => 1, 2437 => 1, 3716 => 1, 3847 => 1, 718 => 1, 3717 => 1, 3714 => 1, 3562 => 1, 722 => 1, 491 => 1, 3792 => 1, 3789 => 1, 1477 => 1, 3959 => 0, 3845 => 1, 2717 => 1, 3923 => 1, 3607 => 1, 3836 => 1, 2159 => 1, 4075 => 0);
        $wmo = DB::Aowow()->select('SELECT *, worldMapAreaId AS ARRAY_KEY, Id AS ARRAY_KEY2 FROM dbc_worldmapoverlay WHERE textureString <> ""');
        $wma = DB::Aowow()->select('SELECT * FROM dbc_worldmaparea');
        if (!$wma || !$wmo) {
            $success = false;
            CLISetup::log(' - could not read required dbc files: WorldMapArea.dbc [' . count($wma) . ' entries]; WorldMapOverlay.dbc  [' . count($wmo) . ' entries]', CLISetup::LOG_ERROR);
            return;
        }
        // fixups...
        foreach ($wma as &$a) {
            if ($a['areaId']) {
                continue;
            }
            switch ($a['Id']) {
                case 13:
                    $a['areaId'] = -6;
                    break;
                    // Kalimdor
                // Kalimdor
                case 14:
                    $a['areaId'] = -3;
                    break;
                    // Eastern Kingdoms
                // Eastern Kingdoms
                case 466:
                    $a['areaId'] = -2;
                    break;
                    // Outland
                // Outland
                case 485:
                    $a['areaId'] = -5;
                    break;
                    // Northrend
            }
        }
        array_unshift($wma, ['Id' => -1, 'areaId' => -1, 'nameINT' => 'World'], ['Id' => -4, 'areaId' => -4, 'nameINT' => 'Cosmic']);
        $sumMaps = count(CLISetup::$localeIds) * count($wma);
        CLISetup::log('Processing ' . $sumMaps . ' files from WorldMap/ ...');
        foreach (CLISetup::$localeIds as $progressLoc => $l) {
            // create destination directories
            $dirError = false;
            foreach ($mapDirs as $md) {
                if (!CLISetup::writeDir($destDir . sprintf($md[0], strtolower(Util::$localeStrings[$l]) . '/'))) {
                    $dirError = true;
                }
            }
            if ($modeMask & 0x4) {
                if (!CLISetup::writeDir('setup/generated/alphaMaps')) {
                    $dirError = true;
                }
            }
            if ($dirError) {
                $success = false;
                CLISetup::log(' - complexImg: could not create map directories for locale ' . $l . '. skipping...', CLISetup::LOG_ERROR);
                continue;
            }
            // source for mapFiles
            $mapSrcDir = null;
            $locDirs = array_filter(CLISetup::$expectedPaths, function ($var) use($l) {
                return !$var || $var == $l;
            });
            foreach ($locDirs as $mapLoc => $__) {
                if ($mapLoc) {
                    // and trailing slash again
                    $mapLoc .= '/';
                }
                $p = sprintf($imgPath, $mapLoc) . $paths[0];
                if (CLISetup::fileExists($p)) {
                    CLISetup::log(' - using files from ' . ($mapLoc ?: '/') . ' for locale ' . Util::$localeStrings[$l], CLISetup::LOG_WARN);
                    $mapSrcDir = $p . '/';
                    break;
                }
            }
            if ($mapSrcDir === null) {
                $success = false;
                CLISetup::log(' - no suitable localized map files found for locale ' . $l, CLISetup::LOG_ERROR);
                continue;
            }
            foreach ($wma as $progressArea => $areaEntry) {
                $curMap = $progressArea + count($wma) * $progressLoc;
                $progress = ' - ' . str_pad($curMap . '/' . $sumMaps, 10) . str_pad('(' . number_format($curMap * 100 / $sumMaps, 2) . '%)', 9);
                $wmaId = $areaEntry['Id'];
                $zoneId = $areaEntry['areaId'];
                $textureStr = $areaEntry['nameINT'];
                $path = $mapSrcDir . $textureStr;
                if (!CLISetup::fileExists($path)) {
                    $success = false;
                    CLISetup::log('worldmap file ' . $path . ' missing for selected locale ' . Util::$localeStrings[$l], CLISetup::LOG_ERROR);
                    continue;
                }
                $fmt = array([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]);
                CLISetup::log($textureStr . " [" . $zoneId . "]");
                $overlay = $createAlphaImage($mapWidth, $mapHeight);
                // zone has overlays (is in open world; is not multiLeveled)
                if (isset($wmo[$wmaId])) {
                    CLISetup::log(' - area has ' . count($wmo[$wmaId]) . ' overlays');
                    foreach ($wmo[$wmaId] as &$row) {
                        $i = 1;
                        $y = 0;
                        while ($y < $row['h']) {
                            $x = 0;
                            while ($x < $row['w']) {
                                $img = $loadImageFile($path . '/' . $row['textureString'] . $i);
                                if (!$img) {
                                    CLISetup::log(' - complexImg: tile ' . $path . '/' . $row['textureString'] . $i . '.blp missing.', CLISetup::LOG_ERROR);
                                    break 2;
                                }
                                imagecopy($overlay, $img, $row['x'] + $x, $row['y'] + $y, 0, 0, imagesx($img), imagesy($img));
                                // prepare subzone image
                                if ($modeMask & 0x10) {
                                    if (!isset($row['maskimage'])) {
                                        $row['maskimage'] = $createAlphaImage($row['w'], $row['h']);
                                        $row['maskcolor'] = imagecolorallocatealpha($row['maskimage'], 255, 64, 192, 64);
                                    }
                                    for ($my = 0; $my < imagesy($img); $my++) {
                                        for ($mx = 0; $mx < imagesx($img); $mx++) {
                                            if (imagecolorat($img, $mx, $my) >> 24 < $threshold) {
                                                imagesetpixel($row['maskimage'], $x + $mx, $y + $my, $row['maskcolor']);
                                            }
                                        }
                                    }
                                }
                                imagedestroy($img);
                                $x += 256;
                                $i++;
                            }
                            $y += 256;
                        }
                    }
                    // create spawn-maps if wanted
                    if ($modeMask & 0x4) {
                        $createSpawnMap($overlay, $zoneId);
                    }
                }
                // check, if the current zone is multiLeveled
                // if there are also files present without layer-suffix assume them as layer: 0
                $multiLeveled = false;
                $multiLevel = 0;
                do {
                    if (!CLISetup::filesInPath('/' . $textureStr . '\\/' . $textureStr . ($multiLevel + 1) . '_\\d\\.blp/i', true)) {
                        break;
                    }
                    $multiLevel++;
                    $multiLeveled = true;
                } while ($multiLevel < 18);
                // Karazhan has 17 frickin floors
                // check if we can create base map anyway
                $file = $path . '/' . $textureStr . '1.blp';
                $hasBaseMap = CLISetup::fileExists($file);
                CLISetup::log(' - area has ' . ($multiLeveled ? $multiLevel . ' levels' : 'only base level'));
                $map = null;
                for ($i = 0; $i <= $multiLevel; $i++) {
                    ini_set('max_execution_time', 120);
                    // max 120sec per image
                    $file = $path . '/' . $textureStr;
                    if (!$i && !$hasBaseMap) {
                        continue;
                    }
                    // if $multiLeveled also suffix -0 to baseMap if it exists
                    if ($i && $multiLeveled) {
                        $file .= $i . '_';
                    }
                    $doSkip = 0x0;
                    $outFile = [];
                    foreach ($mapDirs as $idx => $info) {
                        $outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]) . '/') . $zoneId;
                        $floor = $i;
                        if ($zoneId == 4100) {
                            // ToCStratholme: map order fix
                            $floor += 1;
                        }
                        if ($multiLeveled && !(isset($baseLevelFix[$zoneId]) && $i == $baseLevelFix[$zoneId])) {
                            $outFile[$idx] .= '-' . $floor;
                        }
                        if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx] . '.' . $info[1])) {
                            CLISetup::log($progress . ' - file ' . $outFile[$idx] . '.' . $info[1] . ' was already processed');
                            $doSkip |= 1 << $idx;
                        }
                    }
                    if ($doSkip == 0xf) {
                        continue;
                    }
                    $map = $assembleImage($file, $fmt, $mapWidth, $mapHeight);
                    if (!$map) {
                        $success = false;
                        CLISetup::log(' - could not create image resource for map ' . $zoneId . ($multiLevel ? ' level ' . $i : ''));
                        continue;
                    }
                    if (!$multiLeveled) {
                        imagecopymerge($map, $overlay, 0, 0, 0, 0, imagesx($overlay), imagesy($overlay), 100);
                        imagedestroy($overlay);
                    }
                    // create map
                    if ($modeMask & 0x2) {
                        foreach ($mapDirs as $idx => $info) {
                            if ($doSkip & 1 << $idx) {
                                continue;
                            }
                            if (!$writeImage($outFile[$idx], $info[1], $map, $info[2] ?: $mapWidth, $info[3] ?: $mapHeight, $progress)) {
                                $success = false;
                            }
                        }
                    }
                }
                // also create subzone-maps
                if ($map && isset($wmo[$wmaId]) && $modeMask & 0x10) {
                    foreach ($wmo[$wmaId] as &$row) {
                        $doSkip = 0x0;
                        $outFile = [];
                        foreach ($mapDirs as $idx => $info) {
                            $outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]) . '/') . $row['areaTableId'];
                            if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx] . '.' . $info[1])) {
                                CLISetup::log($progress . ' - file ' . $outFile[$idx] . '.' . $info[1] . ' was already processed');
                                $doSkip |= 1 << $idx;
                            }
                        }
                        if ($doSkip == 0xf) {
                            continue;
                        }
                        $subZone = imagecreatetruecolor($mapWidth, $mapHeight);
                        imagecopy($subZone, $map, 0, 0, 0, 0, imagesx($map), imagesy($map));
                        imagecopy($subZone, $row['maskimage'], $row['x'], $row['y'], 0, 0, imagesx($row['maskimage']), imagesy($row['maskimage']));
                        foreach ($mapDirs as $idx => $info) {
                            if ($doSkip & 1 << $idx) {
                                continue;
                            }
                            if (!$writeImage($outFile[$idx], $info[1], $subZone, $info[2] ?: $mapWidth, $info[3] ?: $mapHeight, $progress)) {
                                $success = false;
                            }
                        }
                        imagedestroy($subZone);
                    }
                }
                if ($map) {
                    imagedestroy($map);
                }
            }
        }
    }
    /***********/
    /* Credits */
    /***********/
    if ($modeMask & 0x8) {
        if (CLISetup::writeDir($destDir . 'Interface/Glues/Credits/')) {
            // tile ordering
            $order = array(1 => array([1]), 2 => array([1], [2]), 4 => array([1, 2], [3, 4]), 6 => array([1, 2, 3], [4, 5, 6]), 8 => array([1, 2, 3, 4], [5, 6, 7, 8]));
            $imgGroups = [];
            $srcPath = sprintf($imgPath, $locStr) . 'Glues/Credits/';
            $files = CLISetup::filesInPath($srcPath);
            foreach ($files as $f) {
                if (preg_match('/([^\\/]+)(\\d).blp/i', $f, $m)) {
                    if ($m[1] && $m[2]) {
                        if (!isset($imgGroups[$m[1]])) {
                            $imgGroups[$m[1]] = $m[2];
                        } else {
                            if ($imgGroups[$m[1]] < $m[2]) {
                                $imgGroups[$m[1]] = $m[2];
                            }
                        }
                    }
                }
            }
            // errör-korrekt
            $imgGroups['Desolace'] = 4;
            $imgGroups['BloodElf_Female'] = 6;
            $total = count($imgGroups);
            $sum = 0;
            CLISetup::log('Processing ' . $total . ' files from Glues/Credits/...');
            foreach ($imgGroups as $file => $fmt) {
                ini_set('max_execution_time', 30);
                // max 30sec per image (loading takes the most time)
                $sum++;
                $done = ' - ' . str_pad($sum . '/' . $total, 8) . str_pad('(' . number_format($sum * 100 / $total, 2) . '%)', 9);
                $name = $destDir . 'Interface/Glues/Credits/' . $file;
                if (!isset(FileGen::$cliOpts['force']) && file_exists($name . '.png')) {
                    CLISetup::log($done . ' - file ' . $name . '.png was already processed');
                    continue;
                }
                if (!isset($order[$fmt])) {
                    CLISetup::log(' - pattern for file ' . $name . ' not set. skipping', CLISetup::LOG_WARN);
                    continue;
                }
                $im = $assembleImage($srcPath . $file, $order[$fmt], count($order[$fmt][0]) * 256, count($order[$fmt]) * 256);
                if (!$im) {
                    CLISetup::log(' - could not assemble file ' . $name, CLISetup::LOG_ERROR);
                    continue;
                }
                if (!$writeImage($name, 'png', $im, count($order[$fmt][0]) * 256, count($order[$fmt]) * 256, $done)) {
                    $success = false;
                }
            }
            ini_set('max_execution_time', $runTime);
        } else {
            $success = false;
        }
    }
    return $success;
}
Пример #18
0
 public static function generate($tableName, array $updateIds = [])
 {
     if (!isset(self::$tables[$tableName])) {
         CLISetup::log('SqlGen::generate - invalid table given', CLISetup::LOG_ERROR);
         return false;
     }
     if (!empty(self::$tables[$tableName][0])) {
         $tbl = self::$tables[$tableName];
         // shorthand
         CLISetup::log('SqlGen::generate() - copying ' . $tbl[0] . '.dbc into aowow_' . $tableName);
         $dbc = new DBC($tbl[0], CLISetup::$tmpDBC);
         if ($dbc->error) {
             return false;
         }
         $dbcData = $dbc->readArbitrary($tbl[1]);
         foreach ($dbcData as $row) {
             DB::Aowow()->query('REPLACE INTO ?_' . $tableName . ' (?#) VALUES (?a)', array_keys($row), array_values($row));
         }
         return !!$dbcData;
     } else {
         if (file_exists('setup/tools/sqlgen/' . $tableName . '.func.php')) {
             $customData = $reqDBC = [];
             CLISetup::log('SqlGen::generate() - filling aowow_' . $tableName . ' with data');
             require_once 'setup/tools/sqlgen/' . $tableName . '.func.php';
             if (function_exists($tableName)) {
                 // check for required auxiliary DBC files
                 foreach ($reqDBC as $req) {
                     if (!CLISetup::loadDBC($req)) {
                         return false;
                     }
                 }
                 $success = $tableName($updateIds);
                 // apply post generator custom data
                 foreach ($customData as $id => $data) {
                     if ($data) {
                         DB::Aowow()->query('UPDATE ?_' . $tableName . ' SET ?a WHERE id = ?d', $data, $id);
                     }
                 }
             } else {
                 CLISetup::log(' - subscript \'' . $tableName . '\' not defined in included file', CLISetup::LOG_ERROR);
             }
             return $success;
         } else {
             CLISetup::log(sprintf(ERR_MISSING_INCL, $tableName, 'setup/tools/sqlgen/' . $tableName . '.func.php'), CLISetup::LOG_ERROR);
         }
     }
 }
Пример #19
0
function spell()
{
    $ssQuery = '
        SELECT
            Id AS ARRAY_KEY,
            Id,
            0 AS category,
            Dispel,
            Mechanic,
            Attributes,         AttributesEx,       AttributesEx2,      AttributesEx3,      AttributesEx4,      AttributesEx5,      AttributesEx6,      AttributesEx7,
            Stances,            StancesNot,
            0 AS spellFocus,
            CastingTimeIndex,
            0 AS recoveryTime,  0 AS recoveryTimeCategory,
            ProcChance,         ProcCharges,
            MaxLevel,           BaseLevel,          SpellLevel,
            DurationIndex,
            0 AS powerType,
            0 AS powerCost,
            0 AS powerCostPerLevel,
            0 AS powerPerSecond,
            0 AS powerPerSecondPerLevel,
            RangeIndex,
            StackAmount,
            0 AS tool1,         0 AS tool2,
            0 AS reagent1,      0 AS reagent2,      0 AS reagent3,      0 AS reagent4,      0 AS reagent5,      0 AS reagent6,      0 AS reagent7,      0 AS reagent8,
            0 AS reagentCount1, 0 AS reagentCount2, 0 AS reagentCount3, 0 AS reagentCount4, 0 AS reagentCount5, 0 AS reagentCount6, 0 AS reagentCount7, 0 AS reagentCount8,
            EquippedItemClass,
            EquippedItemSubClassMask,
            EquippedItemInventoryTypeMask,
            Effect1,                                Effect2,                                Effect3,
            EffectDieSides1,                        EffectDieSides2,                        EffectDieSides3,
            EffectRealPointsPerLevel1,              EffectRealPointsPerLevel2,              EffectRealPointsPerLevel3,
            EffectBasePoints1,                      EffectBasePoints2,                      EffectBasePoints3,
            EffectMechanic1,                        EffectMechanic2,                        EffectMechanic3,
            EffectImplicitTargetA1,                 EffectImplicitTargetA2,                 EffectImplicitTargetA3,
            EffectImplicitTargetB1,                 EffectImplicitTargetB2,                 EffectImplicitTargetB3,
            EffectRadiusIndex1,                     EffectRadiusIndex2,                     EffectRadiusIndex3,
            EffectApplyAuraName1,                   EffectApplyAuraName2,                   EffectApplyAuraName3,
            EffectAmplitude1,                       EffectAmplitude2,                       EffectAmplitude3,
            EffectMultipleValue1,                   EffectMultipleValue2,                   EffectMultipleValue3,
            0 AS effect1ChainTarget,                0 AS effect2ChainTarget,                0 AS effect3ChainTarget,
            EffectItemType1,                        EffectItemType2,                        EffectItemType3,
            EffectMiscValue1,                       EffectMiscValue2,                       EffectMiscValue3,
            EffectMiscValueB1,                      EffectMiscValueB2,                      EffectMiscValueB3,
            EffectTriggerSpell1,                    EffectTriggerSpell2,                    EffectTriggerSpell3,
            0 AS effect1PointsPerComboPoint,        0 AS effect2PointsPerComboPoint,        0 AS effect3PointsPerComboPoint,
            EffectSpellClassMaskA1,                 EffectSpellClassMaskA2,                 EffectSpellClassMaskA3,
            EffectSpellClassMaskB1,                 EffectSpellClassMaskB2,                 EffectSpellClassMaskB3,
            EffectSpellClassMaskC1,                 EffectSpellClassMaskC2,                 EffectSpellClassMaskC3,
            0 AS iconId,                            0 AS iconIdActive,
            CONCAT("Serverside - ",Comment) AS name_loc0,CONCAT("Serverside - ",Comment) AS name_loc2,CONCAT("Serverside - ",Comment) AS name_loc3,CONCAT("Serverside - ",Comment) AS name_loc4,CONCAT("Serverside - ",Comment) AS name_loc6,CONCAT("Serverside - ",Comment) AS name_loc8,
            "" AS rank_loc0,                        "" AS rank_loc2,                        "" AS rank_loc3,                        "" AS rank_loc4,                        "" AS rank_loc6,                        "" AS rank_loc8,
            "" AS description_loc0,                 "" AS description_loc2,                 "" AS description_loc3,                 "" AS description_loc4,                 "" AS description_loc6,                 "" AS description_loc8,
            "" AS buff_loc0,                        "" AS buff_loc2,                        "" AS buff_loc3,                        "" AS buff_loc4,                        "" AS buff_loc6,                        "" AS buff_loc8,
            0 AS powerCostPercent,
            0 AS startRecoveryCategory,
            0 AS startRecoveryTime,
            MaxTargetLevel,
            SpellFamilyName,
            SpellFamilyFlags1,
            SpellFamilyFlags2,
            SpellFamilyFlags3,
            MaxAffectedTargets,
            DmgClass,
            DmgMultiplier1,                         DmgMultiplier2,                         DmgMultiplier3,
            0 AS toolCategory1,                     0 AS toolCategory2,
            SchoolMask,
            0 AS runeCostId,
            0 AS powerDisplayId,
            0 AS effect1BonusMultiplier,            0 AS effect2BonusMultiplier,            0 AS effect3BonusMultiplier,
            0 AS spellDescriptionVariable,
            0 AS spellDifficulty
        FROM
            spell_dbc
        LIMIT
            ?d, ?d';
    $baseQuery = '
        SELECT
            s.Id,
            category,
            dispelType,
            mechanic,
            attributes0,        attributes1,        attributes2,        attributes3,        attributes4,        attributes5,        attributes6,        attributes7,
            0 AS cuFlags,
            0 AS typeCat,
            stanceMask,         stanceMaskNot,
            spellFocus,
            IFNULL(sct.baseTime, 0) AS castTime,
            recoveryTime,       recoveryTimeCategory,
            startRecoveryTime,  startRecoveryCategory,
            procChance,         procCharges,
            0 AS procCustom,    0 AS procCooldown,
            maxLevel,           baseLevel,          spellLevel,         0 AS talentLevel,
            IF (sd.baseTime <> -1, ABS(sd.baseTime), -1) AS duration,
            IF (powerDisplayId, -powerDisplayId, powerType) AS powerType,
            powerCost,
            powerCostPerLevel,
            powerCostPercent,
            powerPerSecond,
            powerPerSecondPerLevel,
            IFNULL (src.runicPowerGain, 0) AS powerGainRunicPower,
            IF (src.Id IS NULL, 0, (src.costBlood << 8) | (src.costUnholy << 4) | src.costFrost) AS powerCostRunes,
            rangeId,
            stackAmount,
            tool1,              tool2,
            toolCategory1,      toolCategory2,
            reagent1,           reagent2,           reagent3,           reagent4,           reagent5,           reagent6,           reagent7,           reagent8,
            reagentCount1,      reagentCount2,      reagentCount3,      reagentCount4,      reagentCount5,      reagentCount6,      reagentCount7,      reagentCount8,
            equippedItemClass,
            equippedItemSubClassMask,
            equippedItemInventoryTypeMask,
            effect1Id,                              effect2Id,                              effect3Id,
            effect1DieSides,                        effect2DieSides,                        effect3DieSides,
            effect1RealPointsPerLevel,              effect2RealPointsPerLevel,              effect3RealPointsPerLevel,
            effect1BasePoints,                      effect2BasePoints,                      effect3BasePoints,
            effect1Mechanic,                        effect2Mechanic,                        effect3Mechanic,
            effect1ImplicitTargetA,                 effect2ImplicitTargetA,                 effect3ImplicitTargetA,
            effect1ImplicitTargetB,                 effect2ImplicitTargetB,                 effect3ImplicitTargetB,
                IFNULL (sr1.radiusMin, 0) AS effect1RadiusMin,      IFNULL (sr1.radiusMax, 0) AS effect1RadiusMax,
                IFNULL (sr2.radiusMin, 0) AS effect2RadiusMin,      IFNULL (sr2.radiusMax, 0) AS effect2RadiusMax,
                IFNULL (sr3.radiusMin, 0) AS effect3RadiusMin,      IFNULL (sr3.radiusMax, 0) AS effect3RadiusMax,
            effect1AuraId,                          effect2AuraId,                          effect3AuraId,
            effect1Periode,                         effect2Periode,                         effect3Periode,
            effect1ValueMultiplier,                 effect2ValueMultiplier,                 effect3ValueMultiplier,
            effect1ChainTarget,                     effect2ChainTarget,                     effect3ChainTarget,
            effect1CreateItemId,                    effect2CreateItemId,                    effect3CreateItemId,
            effect1MiscValue,                       effect2MiscValue,                       effect3MiscValue,
            effect1MiscValueB,                      effect2MiscValueB,                      effect3MiscValueB,
            effect1TriggerSpell,                    effect2TriggerSpell,                    effect3TriggerSpell,
            effect1PointsPerComboPoint,             effect2PointsPerComboPoint,             effect3PointsPerComboPoint,
            effect1SpellClassMaskA,                 effect2SpellClassMaskA,                 effect3SpellClassMaskA,
            effect1SpellClassMaskB,                 effect2SpellClassMaskB,                 effect3SpellClassMaskB,
            effect1SpellClassMaskC,                 effect2SpellClassMaskC,                 effect3SpellClassMaskC,
            effect1DamageMultiplier,                effect2DamageMultiplier,                effect3DamageMultiplier,
            effect1BonusMultiplier,                 effect2BonusMultiplier,                 effect3BonusMultiplier,
            iconId,                                 0 AS iconIdAlt,
            0 AS rankId,
            name_loc0,          name_loc2,          name_loc3,          name_loc4,          name_loc6,          name_loc8,
            rank_loc0,          rank_loc2,          rank_loc3,          rank_loc4,          rank_loc6,          rank_loc8,
            description_loc0,   description_loc2,   description_loc3,   description_loc4,   description_loc6,   description_loc8,
            buff_loc0,          buff_loc2,          buff_loc3,          buff_loc4,          buff_loc6,          buff_loc8,
            maxTargetLevel,
            spellFamilyId,
            spellFamilyFlags1,                      spellFamilyFlags2,                      spellFamilyFlags3,
            maxAffectedTargets,
            damageClass,
            0 AS skillLine1,
            0 AS skillLine2OrMask,
            0 AS reqRaceMask,
            0 AS reqClassMask,
            0 AS reqSpellId,
            0 AS reqSkillLevel,
            0 AS learnedAt,
            0 AS skillLevelGrey,
            0 AS skillLevelYellow,
            schoolMask,
            spellDescriptionVariable,
            0 AS trainingCost
        FROM
            dbc_spell s
        LEFT JOIN
            dbc_spellcasttimes sct ON s.castTimeId      = sct.Id
        LEFT JOIN
            dbc_spellrunecost  src ON s.runeCostId      = src.Id
        LEFT JOIN
            dbc_spellduration   sd ON s.durationId      = sd.Id
        LEFT JOIN
            dbc_spellradius    sr1 ON s.effect1RadiusId = sr1.Id
        LEFT JOIN
            dbc_spellradius    sr2 ON s.effect2RadiusId = sr2.Id
        LEFT JOIN
            dbc_spellradius    sr3 ON s.effect3RadiusId = sr3.Id
        LIMIT
            ?d, ?d';
    $serverside = [];
    // merge serverside spells into dbc_spell (should not affect other scripts)
    $offset = 0;
    CLISetup::log(' - merging serverside spells into spell.dbc');
    while ($spells = DB::World()->select($ssQuery, $offset, SqlGen::$stepSize)) {
        CLISetup::log(' * sets ' . ($offset + 1) . ' - ' . ($offset + count($spells)));
        $offset += SqlGen::$stepSize;
        foreach ($spells as $id => $spell) {
            $serverside[] = $id;
            DB::Aowow()->query('REPLACE INTO dbc_spell VALUES (?a)', array_values($spell));
        }
    }
    // merge everything into aowow_spell
    $offset = 0;
    CLISetup::log(' - filling aowow_spell');
    while ($spells = DB::Aowow()->select($baseQuery, $offset, SqlGen::$stepSize)) {
        CLISetup::log(' * sets ' . ($offset + 1) . ' - ' . ($offset + count($spells)));
        $offset += SqlGen::$stepSize;
        foreach ($spells as $spell) {
            DB::Aowow()->query('REPLACE INTO ?_spell VALUES (?a)', array_values($spell));
        }
    }
    // apply flag: CUSTOM_SERVERSIDE
    if ($serverside) {
        DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_SERVERSIDE, $serverside);
    }
    // apply flag: CUSTOM_DISABLED
    if ($disables = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 0 AND flags & 0xD')) {
        // 0xD: players (0x1), pets (0x4), general (0x8)
        DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_DISABLED, $disables);
    }
    // apply spell ranks (can't use skilllineability.dbc, as it does not contain ranks for non-player/pet spells)
    $ranks = DB::World()->selectCol('SELECT first_spell_id AS ARRAY_KEY, spell_id AS ARRAY_KEY2, rank FROM spell_ranks');
    foreach ($ranks as $firstSpell => $sets) {
        // apply flag: SPELL_CU_FIRST_RANK
        DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_FIRST_RANK, $firstSpell);
        foreach ($sets as $spell => $rank) {
            DB::Aowow()->query('UPDATE ?_spell SET rankNo = ?d WHERE id = ?d', $rank, $spell);
        }
        // apply flag: SPELL_CU_LAST_RANK
        end($sets);
        DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_LAST_RANK, key($sets));
    }
    /******
     * merge SkillLineAbility into Spell
     ******/
    /* acquireMethod
           ABILITY_LEARNED_ON_GET_PROFESSION_SKILL     = 1,        learnedAt = 1
           ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL  = 2         not used for now
       */
    $results = DB::Aowow()->select('SELECT spellId AS ARRAY_KEY, Id AS ARRAY_KEY2, skillLineId, reqRaceMask, reqClassMask, reqSkillLevel, acquireMethod, skillLevelGrey, skillLevelYellow FROM dbc_skilllineability sla');
    foreach ($results as $spellId => $sets) {
        $names = array_keys(current($sets));
        $lines = [];
        $trainer = false;
        $update = array('skillLine1' => 0, 'skillLine2OrMask' => 0, 'reqRaceMask' => 0, 'reqClassMask' => 0, 'reqSkillLevel' => 0, 'skillLevelGrey' => 0, 'skillLevelYellow' => 0);
        foreach ($sets as $set) {
            $i = 0;
            while (isset($names[$i])) {
                $field = $set[$names[$i]];
                switch ($names[$i]) {
                    case 'acquireMethod':
                        if ($field == 1) {
                            $trainer = true;
                        }
                        break;
                    case 'skillLineId':
                        // array
                        if (!in_array($field, $lines)) {
                            $lines[] = $field;
                        }
                        break;
                    case 'reqRaceMask':
                        // mask
                    // mask
                    case 'reqClassMask':
                        if (((int) $update[$names[$i]] & (int) $field) != $field) {
                            (int) ($update[$names[$i]] |= (int) $field);
                        }
                        break;
                    case 'reqSkillLevel':
                        // max
                    // max
                    case 'skillLevelYellow':
                    case 'skillLevelGrey':
                        if ($update[$names[$i]] < $field) {
                            $update[$names[$i]] = $field;
                        }
                        break;
                }
                $i++;
            }
        }
        if ($trainer) {
            DB::Aowow()->query('UPDATE ?_spell SET learnedAt = 1 WHERE id = ?d', $spellId);
        }
        // check skillLineId against mask
        switch (count($lines)) {
            case 2:
                $update['skillLine2OrMask'] = $lines[1];
            case 1:
                $update['skillLine1'] = $lines[0];
                break;
            default:
                for ($i = -count(Util::$skillLineMask); $i < 0; $i++) {
                    foreach (Util::$skillLineMask[$i] as $k => $pair) {
                        if (in_array($pair[1], $lines)) {
                            $update['skillLine1'] = $i;
                            $update['skillLine2OrMask'] |= 1 << $k;
                        }
                    }
                }
        }
        DB::Aowow()->query('UPDATE ?_spell SET ?a WHERE id = ?d', $update, $spellId);
    }
    // fill learnedAt, trainingCost from trainer
    if ($trainer = DB::World()->select('SELECT SpellID AS ARRAY_KEY, MIN(ReqSkillRank) AS reqSkill, MIN(MoneyCost) AS cost, COUNT(*) AS count FROM npc_trainer GROUP BY SpellID')) {
        $spells = DB::Aowow()->select('SELECT Id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE Id IN (?a)', array_keys($trainer));
        $links = [];
        // todo (med): this skips some spells (e.g. riding)
        foreach ($trainer as $spell => $tData) {
            if (!isset($spells[$spell])) {
                continue;
            }
            $triggered = false;
            $effects = $spells[$spell];
            for ($i = 1; $i <= 3; $i++) {
                if ($effects['effect' . $i . 'Id'] != 36) {
                    // effect: learnSpell
                    continue;
                }
                $triggered = true;
                $l =& $links[$effects['effect' . $i . 'TriggerSpell']];
                if (!isset($l)) {
                    $l = [$tData['reqSkill'], $tData['cost']];
                }
                if ($tData['reqSkill'] < $l[0]) {
                    $l[0] = $tData['reqSkill'];
                }
                if ($tData['cost'] < $l[1]) {
                    $l[1] = $tData['cost'];
                }
            }
            if (!$triggered) {
                $l =& $links[$spell];
                if (!isset($l)) {
                    $l = [$tData['reqSkill'], $tData['cost']];
                }
                if ($tData['reqSkill'] < $l[0]) {
                    $l[0] = $tData['reqSkill'];
                }
                if ($tData['cost'] < $l[1]) {
                    $l[1] = $tData['cost'];
                }
            }
        }
        foreach ($links as $spell => $link) {
            DB::Aowow()->query("UPDATE ?_spell s SET s.learnedAt = ?d, s.trainingCost = ?d WHERE s.id = ?d", $link[0], $link[1], $spell);
        }
    }
    // fill learnedAt from recipe-items
    $recipes = DB::World()->selectCol('SELECT IF(spelltrigger_2 = 6, spellid_2, spellid_1) AS ARRAY_KEY, MIN(RequiredSkillRank) FROM item_template WHERE `class` = 9 AND spelltrigger_1 <> 1 AND RequiredSkillRank > 0 GROUP BY ARRAY_KEY');
    foreach ($recipes as $spell => $reqSkill) {
        DB::Aowow()->query('UPDATE ?_spell SET learnedAt = IF(learnedAt = 0 OR learnedAt > ?d, ?d, learnedAt) WHERE id = ?d', $reqSkill, $reqSkill, $spell);
    }
    // fill learnedAt from Discovery
    // 61756: Northrend Inscription Research (FAST QA VERSION);
    // 64323: Book of Glyph Mastery (todo: get reqSkill from item [425])
    // 28571 - 28576: $element Protection Potion (todo: get reqSkill from teaching spell [360])
    $discovery = DB::World()->selectCol('
        SELECT spellId AS ARRAY_KEY,
                IF(reqSpell = ?d, ?d,
                    IF(reqSpell BETWEEN ?d AND ?d, ?d,
                        IF(reqSkillValue, reqSkillValue, 1)))
        FROM skill_discovery_template WHERE reqSpell NOT IN (?a)', 64323, 425, 28571, 28576, 360, [61756]);
    foreach ($discovery as $spell => $reqSkill) {
        DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell);
    }
    // calc reqSkill for gethering-passives (herbing, mining, skinning) (on second thought .. it is set in skilllineability >.<)
    $sets = DB::World()->selectCol('SELECT spell_id AS ARRAY_KEY, rank * 75 AS reqSkill FROM spell_ranks WHERE first_spell_id IN (?a)', [55428, 53120, 53125]);
    foreach ($sets as $spell => $reqSkill) {
        DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell);
    }
    /******************/
    /* talent related */
    /******************/
    for ($i = 1; $i < 6; $i++) {
        // classMask
        DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.reqClassMask = tt.classMask WHERE tt.creatureFamilyMask = 0 AND tt.id = t.tabId AND t.rank?d = s.id', $i);
        // talentLevel
        DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row *  5) + 10 + (?d * 1) WHERE tt.id = t.tabId AND tt.creatureFamilyMask  = 0 AND t.rank?d = s.id', $i - 1, $i);
        DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 12) + 20 + (?d * 4) WHERE tt.id = t.tabId AND tt.creatureFamilyMask <> 0 AND t.rank?d = s.id', $i - 1, $i);
    }
    // passive talent
    DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 0 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENT);
    // spell taught by talent
    DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 1 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENTSPELL);
    /*********/
    /* Other */
    /*********/
    // FU [FixUps]
    DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask  = ?d WHERE skillLine1 = ?d', 1 << 10, 760);
    // Draenai Racials
    DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask  = ?d WHERE skillLine1 = ?d', 1 << 9, 756);
    // Bloodelf Racials
    DB::Aowow()->query('UPDATE ?_spell SET reqClassMask = ?d WHERE id         = ?d', 1 << 7, 30449);
    // Mage - Spellsteal
    // triggered by spell
    DB::Aowow()->query('
        UPDATE
            ?_spell a
        JOIN (
            SELECT effect1TriggerSpell as id FROM ?_spell WHERE effect1Id NOT IN (36, 57, 133) AND effect1TriggerSpell <> 0 UNION
            SELECT effect2TriggerSpell as id FROM ?_spell WHERE effect2Id NOT IN (36, 57, 133) AND effect2TriggerSpell <> 0 UNION
            SELECT effect3TriggerSpell as id FROM ?_spell WHERE effect3Id NOT IN (36, 57, 133) AND effect3TriggerSpell <> 0
        ) as b
        SET
            cuFlags = cuFlags | ?d
        WHERE a.id = b.id', SPELL_CU_TRIGGERED);
    // altIcons and quality for craftSpells
    $itemSpells = DB::Aowow()->selectCol('
        SELECT    s.Id AS ARRAY_KEY, effect1CreateItemId
        FROM      dbc_spell s
        LEFT JOIN dbc_talent t1 ON t1.rank1 = s.id
        LEFT JOIN dbc_talent t2 ON t2.rank2 = s.id
        LEFT JOIN dbc_talent t3 ON t3.rank3 = s.id
        WHERE     effect1CreateItemId > 0 AND effect1Id <> 53 AND t1.id IS NULL AND t2.id IS NULL AND t3.id IS NULL
    ');
    // no enchant-spells & no talents!
    $itemInfo = DB::World()->select('SELECT entry AS ARRAY_KEY, displayId AS d, Quality AS q FROM item_template WHERE entry IN (?a)', $itemSpells);
    foreach ($itemSpells as $sId => $itemId) {
        if (isset($itemInfo[$itemId])) {
            DB::Aowow()->query('UPDATE ?_spell SET iconIdAlt = ?d, cuFlags = cuFlags | ?d WHERE id = ?d', -$itemInfo[$itemId]['d'], 7 - $itemInfo[$itemId]['q'] << 8, $sId);
        }
    }
    // apply specializations [trainerTemplate => reqSpell]
    $specs = array(201007 => 9788, 201008 => 9787, 201015 => 20222, 201016 => 20219, 201030 => 10660, 201031 => 10656, 201032 => 10658);
    foreach ($specs as $tt => $req) {
        if ($spells = DB::World()->selectCol('SELECT SpellID FROM npc_trainer WHERE ID = ?d', $tt)) {
            DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE id IN (?a)', $req, $spells);
        }
    }
    $itemReqs = DB::World()->selectCol('SELECT entry AS ARRAY_KEY, requiredSpell FROM item_template WHERE requiredSpell NOT IN (?a)', [0, 34090, 34091]);
    // not riding
    foreach ($itemReqs as $itemId => $req) {
        DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE skillLine1 IN (?a) AND effect1CreateItemId = ?d', $req, [164, 165, 197, 202], $itemId);
    }
    DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = id WHERE id IN (?a)', [9788, 9787, 20222, 20219, 10660, 10656, 10658, 26797, 26798, 26801, 17039, 17040, 17041]);
    /**************/
    /* Categories */
    /**************/
    // player talents (-2)
    DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -2 WHERE t.tabId NOT IN (409, 410, 411) AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3 OR s.Id = t.rank4 OR s.Id = t.rank5)');
    // pet spells (-3)
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -3 WHERE (s.cuFlags & 0x3) = 0 AND s.skillline1 IN (?a)', array_merge(array_column(Util::$skillLineMask[-1], 1), array_column(Util::$skillLineMask[-2], 1), [270, 782], [-1, -2]));
    // racials (-4)
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -4 WHERE s.skillLine1 IN (101, 124, 125, 126, 220, 733, 753, 754, 756, 760)');
    // mounts (-5)
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -5 WHERE s.effect1AuraId = 78 AND (s.skillLine1 IN (354, 594, 772, 777) OR (s.skillLine1 > 0 AND s.skillLine2OrMask = 777))');
    // companions (-6)
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -6 WHERE s.skillLine1 = 778');
    // pet talents (-7)
    DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x10 WHERE t.tabId = 409 AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3)');
    DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x08 WHERE t.tabId = 410 AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3)');
    DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x20 WHERE t.tabId = 411 AND (s.Id = t.rank1 OR s.Id = t.rank2 OR s.Id = t.rank3)');
    // internal (-9) by faaaaaar not complete
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.skillLine1 = 769');
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.typeCat = 0 AND s.cuFlags = 0 AND (
        s.name_loc0 LIKE "%qa%"       OR
        s.name_loc0 LIKE "%debug%"    OR
        s.name_loc0 LIKE "%internal%" OR
        s.name_loc0 LIKE "%(NYI)%"    OR
        s.name_loc0 LIKE "%(TEST)%"   OR
        s.name_loc0 LIKE "%(OLD)%")');
    // proficiencies (-11)
    DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = -11 WHERE s.skillLine1 = sl.id AND sl.categoryId IN (6, 8, 10)');
    // glyphs (-13)
    DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.cuFlags = s.cuFlags | IF(gp.typeFlags, ?d, ?d), s.typeCat = -13 WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74', SPELL_CU_GLYPH_MINOR, SPELL_CU_GLYPH_MAJOR);
    $glyphs = DB::World()->selectCol('SELECT it.spellid_1 AS ARRAY_KEY, it.AllowableClass FROM item_template it WHERE it.class = 16');
    foreach ($glyphs as $spell => $classMask) {
        DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.reqClassMask = ?d WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74 AND s.id = ?d', $classMask, $spell);
    }
    // class Spells (7)
    DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = 7 WHERE s.typeCat = 0 AND s.skillLine1 = sl.id AND sl.categoryId = 7');
    // hide some internal class stuffs
    DB::Aowow()->query('UPDATE ?_spell s SET s.cuFlags = ?d WHERE s.typeCat = 7 AND (
        s.name_loc0 LIKE "%passive%" OR s.name_loc0 LIKE "%effect%" OR s.name_loc0 LIKE "%improved%" OR s.name_loc0 LIKE "%prototype%" OR                                       -- can probably be extended
        (s.id NOT IN (47241, 59879, 59671) AND s.baseLevel <= 1 AND s.reqclassMask = 0)  OR                                                                                     -- can probably still be extended
        (s.SpellFamilyId = 15 AND s.SpellDescriptionVariableId <> 84) OR                                                                                                        -- DK: Skill Coil
        (s.SpellFamilyId = 10 AND s.SpellFamilyFlags2 & 0x1000000 AND s.attributes1 = 0) OR                                                                                     -- Paladin: Bacon of Light hmm.. Bacon.... :]
        (s.SpellFamilyId = 6  AND s.SpellFamilyFlags3 & 0x4000) OR                                                                                                              -- Priest: Lolwell Renew
        (s.SpellFamilyId = 6  AND s.SpellFamilyFlags1 & 0x8000000 AND s.rank_loc0 <> "") OR                                                                                     -- Priest: Bling Bling
        (s.SpellFamilyId = 8  AND s.attributes0 = 0x50 AND s.attributes1 & 0x400) OR                                                                                            -- Rogue: Intuition (dropped Talent..? looks nice though)
        (s.SpellfamilyId = 11 AND s.SpellFamilyFlags1 & 3 AND s.attributes1 = 1024) OR                                                                                          -- Shaman: Lightning Overload procs
        (s.attributes0 = 0x20000000 AND s.attributes3 = 0x10000000) OR                                                                                                          -- Master Demonologist (FamilyId = 0)
        s.id IN (47633, 22845, 29442, 31643, 44450, 32841, 20154, 34919, 27813, 27817, 27818, 30708, 30874, 379, 21169, 19483, 29886, 58889, 23885, 29841, 29842, 64380, 58427) -- Misc
    )', CUSTOM_EXCLUDE_FOR_LISTVIEW);
    foreach ([1, 2, 3, 4, 5, 6, 7, 8, 9, 11] as $classId) {
        DB::Aowow()->query('
            UPDATE
                ?_spell s,
                dbc_skillline sl,
                dbc_skillraceclassinfo srci
            SET
                s.reqClassMask = srci.classMask
            WHERE
                s.typeCat IN (-2, 7) AND
                (s.attributes0 & 0x80) = 0 AND
                s.skillLine1 = srci.skillLine AND
                sl.categoryId = 7 AND
                srci.skillline <> 769 AND
                srci.skillline = sl.id AND
                srci.flags & 0x90 AND
                srci.classMask & ?d', 1 << $classId - 1);
    }
    // secondary Skills (9)
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 9 WHERE s.typeCat = 0 AND (s.skillLine1 IN (129, 185, 356, 762) OR (s.skillLine1 > 0 AND s.skillLine2OrMask IN (129, 185, 356, 762)))');
    // primary Skills (11)
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 11 WHERE s.typeCat = 0 AND s.skillLine1 IN (164, 165, 171, 182, 186, 197, 202, 333, 393, 755, 773)');
    // npc spells (-8) (run as last! .. missing from npc_scripts? "enum Spells { \s+(\w\d_)+\s+=\s(\d+) }" and "#define SPELL_(\d\w_)+\s+(\d+)") // RAID_MODE(1, 2[, 3, 4]) - macro still not considered
    $world = DB::World()->selectCol('
        SELECT ss.action_param1 FROM smart_scripts ss WHERE ss.action_type IN (11, 75, 85, 86) UNION
        SELECT ct.spell1 FROM creature_template ct WHERE ct.spell1 <> 0                        UNION
        SELECT ct.spell2 FROM creature_template ct WHERE ct.spell2 <> 0                        UNION
        SELECT ct.spell3 FROM creature_template ct WHERE ct.spell3 <> 0                        UNION
        SELECT ct.spell4 FROM creature_template ct WHERE ct.spell4 <> 0                        UNION
        SELECT ct.spell5 FROM creature_template ct WHERE ct.spell5 <> 0                        UNION
        SELECT ct.spell6 FROM creature_template ct WHERE ct.spell6 <> 0                        UNION
        SELECT ct.spell7 FROM creature_template ct WHERE ct.spell7 <> 0                        UNION
        SELECT ct.spell8 FROM creature_template ct WHERE ct.spell8 <> 0');
    $auras = DB::World()->selectCol('SELECT cta.auras FROM creature_template_addon cta WHERE auras <> ""');
    foreach ($auras as $a) {
        foreach (explode(' ', $a) as $spell) {
            $world[] = $spell;
        }
    }
    DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -8 WHERE s.typeCat = 0 AND s.id In (?a)', $world);
    /**********/
    /* Glyphs */
    /**********/
    // glyphSpell => affectedSpell
    $glyphAffects = array(63959 => 50842, 58723 => 55090, 58721 => 46584, 58711 => 52375, 54857 => 33876, 56881 => 13165, 56598 => 27101, 63871 => 1038, 55003 => 53407, 63873 => 47788, 58258 => 2983, 55535 => 52127, 55558 => 16190, 56302 => 697, 56299 => 712, 58272 => 126, 56292 => 688, 56286 => 691, 56285 => 30146, 58275 => 29893, 63941 => 1454, 56289 => 5699, 56297 => 693, 58271 => 1120, 58281 => 34428, 58397 => 23922, 63949 => 50720);
    $queryIcons = '
        SELECT    s.id, s.name_loc0, s.skillLine1 as skill, s.iconId as icon, s.typeCat * s.typeCat AS prio
        FROM      ?_spell s
        WHERE     [WHERE] AND (s.cuFlags & ?d) = 0 AND s.typeCat IN (0, 7, -2)  -- not triggered; class spells first, talents second, unk last
        ORDER BY  prio DESC
    ';
    $effects = DB::Aowow()->select('
        SELECT
             s2.Id AS ARRAY_KEY,
             s1.Id,
             s1.name_loc0,
             s1.spellFamilyId,
             s1.spellFamilyFlags1,      s1.spellFamilyFlags2,       s1.spellFamilyFlags3,
             s1.effect1Id,              s1.effect2Id,               s1.effect3Id,
             s1.effect1SpellClassMaskA, s1.effect1SpellClassMaskB,  s1.effect1SpellClassMaskC,
             s1.effect2SpellClassMaskA, s1.effect2SpellClassMaskB,  s1.effect2SpellClassMaskC,
             s1.effect3SpellClassMaskA, s1.effect3SpellClassMaskB,  s1.effect3SpellClassMaskC
        FROM
            dbc_glyphproperties gp
        JOIN
            ?_spell s1 ON s1.Id = gp.spellId
        JOIN
            ?_spell s2 ON s2.effect1MiscValue = gp.id AND s2.effect1Id = 74
        WHERE
            gp.typeFlags IN (0, 1) -- AND s2.Id In (58271, 56297, 56289, 63941, 58275)
    ');
    foreach ($effects as $applyId => $glyphEffect) {
        $l = [null, 'A', 'B', 'C'];
        $i = 0;
        $icons = [];
        $fam = $glyphEffect['spellFamilyId'];
        // first: manuall replace
        if ($applyId == 57144) {
            $icons = ['skill' => 253, 'icon' => 163];
        }
        // second: search by name and Family equality
        if (!$icons) {
            $search = !empty($glyphAffects[$applyId]) ? $glyphAffects[$applyId] : str_replace('Glyph of ', '', $glyphEffect['name_loc0']);
            if (is_int($search)) {
                $where = "?d AND s.id = ?d";
            } else {
                $where = "s.SpellFamilyId = ?d AND s.name_loc0 LIKE ?";
            }
            $qry = str_replace('[WHERE]', $where, $queryIcons);
            $icons = DB::Aowow()->selectRow($qry, $fam ?: 1, $search, SPELL_CU_TRIGGERED);
        }
        // third: match by SpellFamily affect mask
        while (empty($icons) && $i < 3) {
            $i++;
            $m1 = $glyphEffect['effect1SpellClassMask' . $l[$i]];
            $m2 = $glyphEffect['effect2SpellClassMask' . $l[$i]];
            $m3 = $glyphEffect['effect3SpellClassMask' . $l[$i]];
            if ($glyphEffect['effect' . $i . 'Id'] != 6 || !$m1 && !$m2 && !$m3) {
                continue;
            }
            $where = "s.SpellFamilyId = ?d AND (s.SpellFamilyFlags1 & ?d OR s.SpellFamilyFlags2 & ?d OR s.SpellFamilyFlags3 & ?d)";
            $icons = DB::Aowow()->selectRow(str_replace('[WHERE]', $where, $queryIcons), $fam, $m1, $m2, $m3, SPELL_CU_TRIGGERED);
        }
        if ($icons) {
            DB::Aowow()->query('UPDATE ?_spell s SET s.skillLine1 = ?d, s.iconIdAlt = ?d WHERE s.id = ?d', $icons['skill'], $icons['icon'], $applyId);
        } else {
            CLISetup::log('could not match ' . $glyphEffect['name_loc0'] . ' (' . $glyphEffect['Id'] . ') with affected spells', CLISetup::LOG_WARN);
        }
    }
    // hide unused glyphs
    DB::Aowow()->query('UPDATE ?_spell SET skillLine1 = 0, iconIdAlt = 0, cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [60460, 58166, 58239, 58240, 58261, 58262, 54910]);
    return true;
}
Пример #20
0
 public static function generate($key, array $updateIds = [])
 {
     $success = false;
     $reqDBC = [];
     if (file_exists('setup/tools/filegen/' . $key . '.func.php')) {
         require_once 'setup/tools/filegen/' . $key . '.func.php';
     } else {
         if (empty(self::$tplFiles[$key])) {
             CLISetup::log(sprintf(ERR_MISSING_INCL, $key, 'setup/tools/filegen/' . $key . '.func.php', CLISetup::LOG_ERROR));
             return false;
         }
     }
     CLISetup::log('FileGen::generate() - gathering data for ' . $key);
     if (!empty(self::$tplFiles[$key])) {
         list($file, $destPath, $deps) = self::$tplFiles[$key];
         if ($content = file_get_contents(FileGen::$tplPath . $file . '.in')) {
             if ($dest = @fOpen($destPath . $file, "w")) {
                 // replace constants
                 $content = strtr($content, FileGen::$txtConstants);
                 // check for required auxiliary DBC files
                 foreach ($reqDBC as $req) {
                     if (!CLISetup::loadDBC($req)) {
                         continue 2;
                     }
                 }
                 // must generate content
                 // PH format: /*setup:<setupFunc>*/
                 $funcOK = true;
                 if (preg_match_all('/\\/\\*setup:([\\w\\-_]+)\\*\\//i', $content, $m)) {
                     foreach ($m[1] as $func) {
                         if (function_exists($func)) {
                             $content = str_replace('/*setup:' . $func . '*/', $func(), $content);
                         } else {
                             $funcOK = false;
                             CLISetup::log('No function for was registered for placeholder ' . $func . '().', CLISetup::LOG_ERROR);
                             if (!array_reduce(get_included_files(), function ($inArray, $itr) use($func) {
                                 return $inArray || false !== strpos($itr, $func);
                             }, false)) {
                                 CLISetup::log('Also, expected include setup/tools/filegen/' . $name . '.func.php was not found.');
                             }
                         }
                     }
                 }
                 if (fWrite($dest, $content)) {
                     CLISetup::log(sprintf(ERR_NONE, CLISetup::bold($destPath . $file)), CLISetup::LOG_OK);
                     if ($content && $funcOK) {
                         $success = true;
                     }
                 } else {
                     CLISetup::log(sprintf(ERR_WRITE_FILE, CLISetup::bold($destPath . $file)), CLISetup::LOG_ERROR);
                 }
                 fClose($dest);
             } else {
                 CLISetup::log(sprintf(ERR_CREATE_FILE, CLISetup::bold($destPath . $file)), CLISetup::LOG_ERROR);
             }
         } else {
             CLISetup::log(sprintf(ERR_READ_FILE, CLISetup::bold(FileGen::$tplPath . $file . '.in')), CLISetup::LOG_ERROR);
         }
     } else {
         if (!empty(self::$datasets[$key])) {
             if (function_exists($key)) {
                 // check for required auxiliary DBC files
                 foreach ($reqDBC as $req) {
                     if (!CLISetup::loadDBC($req)) {
                         return false;
                     }
                 }
                 $success = $key($updateIds);
             } else {
                 CLISetup::log(' - subscript \'' . $key . '\' not defined in included file', CLISetup::LOG_ERROR);
             }
         }
     }
     set_time_limit(FileGen::$defaultExecTime);
     // reset to default for the next script
     return $success;
 }
Пример #21
0
function siteconfig()
{
    if (!DB::isConnected(DB_AOWOW)) {
        CLISetup::log();
        CLISetup::log("database not yet set up!\n        Please use --dbconfig for setup", CLISetup::LOG_WARN);
        return;
    }
    while (true) {
        CLISetup::log();
        CLISetup::log('select a numerical index to use the corresponding entry');
        $results = DB::Aowow()->select('SELECT *, (flags & ?d) AS php FROM ?_config ORDER BY php ASC', CON_FLAG_PHP);
        $hasEmpty = false;
        foreach ($results as $idx => $data) {
            if (!($data['flags'] & CON_FLAG_PHP) && $data['value'] === '') {
                $hasEmpty = true;
            }
            $php = $data['flags'] & CON_FLAG_PHP;
            $buff = "[" . CLISetup::bold($idx) . "] " . ($idx > 9 ? '' : ' ') . ($php ? '  PHP   ' : ' AOWOW  ');
            $buff .= str_pad($php ? strtolower($data['key']) : strtoupper('cfg_' . $data['key']), 35);
            if ($data['value'] === '') {
                $buff .= CLISetup::red('<empty>');
            } else {
                $info = explode(' - ', $data['comment']);
                if ($data['flags'] & CON_FLAG_TYPE_BOOL) {
                    $buff .= '[bool] ' . ($data['value'] ? '<Enabled>' : '<Disabled>');
                } else {
                    if ($data['flags'] & CON_FLAG_OPT_LIST && !empty($info[2])) {
                        $buff .= "[opt]  ";
                        foreach (explode(', ', $info[2]) as $option) {
                            $opt = explode(':', $option);
                            $buff .= '[' . ($data['value'] == $opt[0] ? 'x' : ' ') . ']' . $opt[1] . ' ';
                        }
                    } else {
                        if ($data['flags'] & CON_FLAG_BITMASK && !empty($info[2])) {
                            $buff .= "[mask] ";
                            foreach (explode(', ', $info[2]) as $option) {
                                $opt = explode(':', $option);
                                $buff .= '[' . ($data['value'] & 1 << $opt[0] ? 'x' : ' ') . ']' . $opt[1] . ' ';
                            }
                        } else {
                            if ($data['flags'] & CON_FLAG_TYPE_STRING) {
                                $buff .= "[str]  " . $data['value'];
                            } else {
                                if ($data['flags'] & CON_FLAG_TYPE_FLOAT) {
                                    $buff .= "[float] " . floatVal($data['value']);
                                } else {
                                    /* if ($data['flags'] & CON_FLAG_TYPE_INT) */
                                    $buff .= "[int]  " . intVal($data['value']);
                                }
                            }
                        }
                    }
                }
            }
            CLISetup::log($buff);
        }
        CLISetup::log(str_pad("[" . CLISetup::bold(count($results)) . "]", 21) . "add another php configuration");
        if ($hasEmpty) {
            CLISetup::log();
            CLISetup::log("please configure the required empty setings", CLISetup::LOG_WARN);
        }
        $inp = ['idx' => ['', false, '/\\d/']];
        if (CLISetup::readInput($inp) && $inp && $inp['idx'] !== '') {
            // add new php setting
            if ($inp['idx'] == count($results)) {
                CLISetup::log();
                CLISetup::log("Adding additional php configuration.");
                while (true) {
                    $setting = array('key' => ['option name', false, '/[\\w_\\.\\-]/i'], 'val' => ['value']);
                    if (CLISetup::readInput($setting) && $setting) {
                        CLISetup::log();
                        $key = strtolower($setting['key']);
                        if (ini_get($key) === false || ini_set($key, $setting['val']) === false) {
                            CLISetup::log("this configuration option cannot be set", CLISetup::LOG_ERROR);
                            sleep(1);
                        } else {
                            if (DB::Aowow()->selectCell('SELECT 1 FROM ?_config WHERE `flags` & ?d AND `key` = ?', CON_FLAG_PHP, $key)) {
                                CLISetup::log("this configuration option is already in use", CLISetup::LOG_ERROR);
                                sleep(1);
                            } else {
                                DB::Aowow()->query('INSERT IGNORE INTO ?_config (`key`, `value`, `flags`) VALUES (?, ?, ?d)', $key, $setting['val'], CON_FLAG_TYPE_STRING | CON_FLAG_PHP);
                                CLISetup::log("new php configuration added", CLISetup::LOG_OK);
                                sleep(1);
                            }
                        }
                        break;
                    } else {
                        CLISetup::log();
                        CLISetup::log("edit canceled! returning to list...", CLISetup::LOG_WARN);
                        sleep(1);
                        break;
                    }
                }
            } else {
                if ($inp['idx'] >= 0 && $inp['idx'] < count($results)) {
                    $conf = $results[$inp['idx']];
                    $info = explode(' - ', $conf['comment']);
                    $buff = '';
                    CLISetup::log();
                    $buff .= $conf['flags'] & CON_FLAG_PHP ? "  PHP: " : "AOWOW: ";
                    $buff .= $conf['flags'] & CON_FLAG_PHP ? strtolower($conf['key']) : strtoupper('cfg_' . $conf['key']);
                    if (!empty($info[1])) {
                        $buff .= " - " . $info[1];
                    }
                    CLISetup::log($buff);
                    $buff = "VALUE: ";
                    if ($conf['flags'] & CON_FLAG_TYPE_BOOL) {
                        $buff .= $conf['value'] ? '<Enabled>' : '<Disabled>';
                    } else {
                        if ($conf['flags'] & CON_FLAG_OPT_LIST && !empty($info[2])) {
                            foreach (explode(', ', $info[2]) as $option) {
                                $opt = explode(':', $option);
                                $buff .= '[' . ($conf['value'] == $opt[0] ? 'x' : ' ') . '] ' . $opt[1] . ' ';
                            }
                        } else {
                            if ($conf['flags'] & CON_FLAG_BITMASK && !empty($info[2])) {
                                foreach (explode(', ', $info[2]) as $option) {
                                    $opt = explode(':', $option);
                                    $buff .= '[' . ($conf['value'] & 1 << $opt[0] ? 'x' : ' ') . '] ' . $opt[1] . ' ';
                                }
                            } else {
                                if ($conf['flags'] & CON_FLAG_TYPE_STRING) {
                                    $buff .= $conf['value'];
                                } else {
                                    if ($conf['flags'] & CON_FLAG_TYPE_FLOAT) {
                                        $buff .= floatVal($conf['value']);
                                    } else {
                                        /* if ($conf['flags'] & CON_FLAG_TYPE_INT) */
                                        $buff .= intVal($conf['value']);
                                    }
                                }
                            }
                        }
                    }
                    CLISetup::log($buff);
                    CLISetup::log();
                    CLISetup::log("[" . CLISetup::bold('E') . "]dit");
                    if (!($conf['flags'] & CON_FLAG_PERSISTENT)) {
                        CLISetup::log("[" . CLISetup::bold('D') . "]elete");
                    }
                    if (strstr($info[0], 'default:')) {
                        CLISetup::log("[" . CLISetup::bold('R') . "]estore Default - " . trim(explode('default:', $info[0])[1]));
                    }
                    while (true) {
                        $action = ['idx' => ['', true, '/[edr]/i']];
                        if (CLISetup::readInput($action, true) && $action) {
                            switch (strtoupper($action['idx'])) {
                                case 'E':
                                    // edit value
                                    $pattern = false;
                                    $single = false;
                                    $value = ['idx' => ['Select new value', false, &$pattern]];
                                    if ($conf['flags'] & CON_FLAG_OPT_LIST) {
                                        $_valid = [];
                                        foreach (explode(', ', $info[2]) as $option) {
                                            $opt = explode(':', $option);
                                            $_valid[] = $opt[0];
                                            CLISetup::log('[' . CLISetup::bold($opt[0]) . '] ' . $opt[1]);
                                        }
                                        $single = true;
                                        $pattern = '/\\d/';
                                        $validate = function ($v) use($_valid) {
                                            return in_array($v, $_valid);
                                        };
                                    } else {
                                        if ($conf['flags'] & CON_FLAG_BITMASK) {
                                            CLISetup::log('Bitmask: sum fields to select multiple options');
                                            $_valid = 0x0;
                                            foreach (explode(', ', $info[2]) as $option) {
                                                $opt = explode(':', $option);
                                                $_valid |= 1 << $opt[0];
                                                CLISetup::log('[' . CLISetup::bold(1 << $opt[0]) . ']' . str_pad('', 4 - strlen(1 << $opt[0])) . $opt[1]);
                                            }
                                            $pattern = '/\\d+/';
                                            $validate = function ($v) use($_valid) {
                                                $v = $v & $_valid;
                                                return $v;
                                            };
                                        } else {
                                            if ($conf['flags'] & CON_FLAG_TYPE_BOOL) {
                                                CLISetup::log('[' . CLISetup::bold(0) . '] Disabled');
                                                CLISetup::log('[' . CLISetup::bold(1) . '] Enabled');
                                                $single = true;
                                                $pattern = '/[01]/';
                                                $validate = function ($v) {
                                                    return true;
                                                };
                                            } else {
                                                if ($conf['flags'] & CON_FLAG_TYPE_INT) {
                                                    $validate = function ($v) {
                                                        return preg_match('/^-?\\d+$/i', $v);
                                                    };
                                                } else {
                                                    if ($conf['flags'] & CON_FLAG_TYPE_FLOAT) {
                                                        $validate = function ($v) {
                                                            return preg_match('/^-?\\d*(,|.)?\\d+$/i', $v);
                                                        };
                                                    } else {
                                                        // string
                                                        $validate = function ($v) {
                                                            return true;
                                                        };
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    while (true) {
                                        $use = $value;
                                        if (CLISetup::readInput($use, $single) && $use) {
                                            CLISetup::log();
                                            if (!$validate($use['idx'])) {
                                                CLISetup::log("value not in range", CLISetup::LOG_ERROR);
                                                sleep(1);
                                                continue;
                                            } else {
                                                DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $use['idx'], strtolower($conf['key']));
                                                CLISetup::log("setting updated", CLISetup::LOG_OK);
                                                sleep(1);
                                                break 3;
                                            }
                                        } else {
                                            CLISetup::log("edit canceled! returning to selection...", CLISetup::LOG_WARN);
                                            sleep(1);
                                            break;
                                        }
                                    }
                                    break 2;
                                case 'R':
                                    // restore default
                                    if (!strstr($info[0], 'default:')) {
                                        continue 2;
                                    }
                                    // @eval .. some dafault values are supplied as bitmask or the likes
                                    if (DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', @eval('return (' . trim(explode('default:', $info[0])[1]) . ');'), strtolower($conf['key']))) {
                                        CLISetup::log("default value restored", CLISetup::LOG_OK);
                                        sleep(1);
                                    }
                                    break 2;
                                case 'D':
                                    // delete config pair
                                    if ($conf['flags'] & CON_FLAG_PERSISTENT) {
                                        continue 2;
                                    }
                                    if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', strtolower($conf['key']), CON_FLAG_PERSISTENT)) {
                                        CLISetup::log("php setting deleted ['" . $conf['key'] . "': '" . $conf['value'] . "']", CLISetup::LOG_OK);
                                        sleep(1);
                                    }
                                    break 2;
                            }
                        } else {
                            CLISetup::log();
                            CLISetup::log("edit canceled! returning to list...", CLISetup::LOG_WARN);
                            sleep(1);
                            break;
                        }
                    }
                } else {
                    CLISetup::log();
                    CLISetup::log("invalid selection", CLISetup::LOG_ERROR);
                    sleep(1);
                }
            }
        } else {
            CLISetup::log();
            CLISetup::log("site configuration aborted", CLISetup::LOG_WARN);
            break;
        }
    }
}
Пример #22
0
function emotes()
{
    $globStrPath = CLISetup::$srcDir . '%sInterface/FrameXML/GlobalStrings.lua';
    $allOK = true;
    $locPath = [];
    DB::Aowow()->query('TRUNCATE ?_emotes_aliasses');
    foreach (CLISetup::$localeIds as $lId) {
        foreach (CLISetup::$expectedPaths as $xp => $locId) {
            if ($lId != $locId) {
                continue;
            }
            if ($xp) {
                // if in subDir add trailing slash
                $xp .= '/';
            }
            $path = sprintf($globStrPath, $xp);
            if (CLISetup::fileExists($path)) {
                $locPath[$lId] = $path;
                continue 2;
            }
        }
        CLISetup::log('GlobalStrings.lua not found for selected locale ' . CLISetup::bold(Util::$localeStrings[$lId]), CLISetup::LOG_WARN);
        $allOK = false;
    }
    $_ = DB::Aowow()->query('REPLACE INTO ?_emotes SELECT
            et.Id,
            LOWER(et.command),
            IF(e.animationId, 1, 0),
            0,                                              -- cuFlags
            etdT.text_loc0,  etdT.text_loc2,  etdT.text_loc3,  etdT.text_loc6,  etdT.text_loc8,
            etdNT.text_loc0, etdNT.text_loc2, etdNT.text_loc3, etdNT.text_loc6, etdNT.text_loc8,
            etdS.text_loc0,  etdS.text_loc2,  etdS.text_loc3,  etdS.text_loc6,  etdS.text_loc8
        FROM
            dbc_emotestext et
        LEFT JOIN
            dbc_emotes e ON e.Id = et.emoteId
        LEFT JOIN
            dbc_emotestextdata etdT  ON etdT.Id  = et.targetId
        LEFT JOIN
            dbc_emotestextdata etdNT ON etdNT.Id = et.noTargetId
        LEFT JOIN
            dbc_emotestextdata etdS  ON etdS.Id  = et.selfId');
    if (!$_) {
        $allOK = false;
    }
    // i have no idea, how the indexing in this file works.
    // sometimes the \d+ after EMOTE is the emoteTextId, but not nearly often enough
    $aliasses = [];
    foreach ($locPath as $lId => $path) {
        foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
            if (preg_match('/^EMOTE(\\d+)_CMD\\d+\\s=\\s\\"\\/([^"]+)\\";$/', $line, $m)) {
                $aliasses[$m[1]][] = [$lId, $m[2]];
            }
        }
    }
    $emotes = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, cmd FROM ?_emotes');
    foreach ($emotes as $eId => $cmd) {
        foreach ($aliasses as $gsId => $data) {
            if (in_array($cmd, array_column($data, 1))) {
                foreach ($data as $d) {
                    DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_aliasses VALUES (?d, ?d, ?) ON DUPLICATE KEY UPDATE locales = locales | ?d', $eId, 1 << $d[0], strtolower($d[1]), 1 << $d[0]);
                }
                break;
            }
        }
    }
    return $allOK;
}
Пример #23
0
function simpleImg()
{
    // prefer manually converted PNG files (as the imagecreatefromblp-script has issues with some formats)
    // see: https://github.com/Kanma/BLPConverter
    $loadImageFile = function ($path) {
        $result = null;
        if (in_array(mb_substr($path, -4, 4), ['.png', '.blp', '.BLP', '.PNG'])) {
            $path = mb_substr($path, 0, mb_strlen($path) - 4);
        }
        $file = $path . '.png';
        if (CLISetup::fileExists($file)) {
            CLISetup::log('manually converted png file present for ' . $path . '.', CLISetup::LOG_INFO);
            $result = imagecreatefrompng($file);
        }
        if (!$result) {
            $file = $path . '.blp';
            if (CLISetup::fileExists($file)) {
                $result = imagecreatefromblp($file);
            }
        }
        return $result;
    };
    if (isset(FileGen::$cliOpts['help'])) {
        echo "\n";
        echo "available options for subScript 'simpleImg':\n";
        echo " --icons          (generates square icons that are used for basicly everything)\n";
        echo " --glyphs         (decorative tidbit displayed on Infobox for Glyph Spells)\n";
        echo " --pagetexts      (imagery contained in PageTexts on readable GameObjects or Items)\n";
        echo " --loadingscreens (loading screens (not used, skipped by default))\n";
        return true;
    }
    $locStr = null;
    $groups = [];
    $dbcPath = CLISetup::$srcDir . '%sDBFilesClient/';
    $imgPath = CLISetup::$srcDir . '%sInterface/';
    $destDir = 'static/images/wow/';
    $success = true;
    $iconDirs = array(['icons/large/', 'jpg', 0, 56, 4], ['icons/medium/', 'jpg', 0, 36, 4], ['icons/small/', 'jpg', 0, 18, 4], ['icons/tiny/', 'gif', 0, 15, 4]);
    $calendarDirs = array(['icons/large/', 'jpg', 90, 56, 4], ['icons/medium/', 'jpg', 90, 36, 4], ['icons/small/', 'jpg', 90, 18, 4], ['icons/tiny/', 'gif', 90, 15, 4]);
    $loadScreenDirs = array(['loadingscreens/large/', 'jpg', 0, 1024, 0], ['loadingscreens/medium/', 'jpg', 0, 488, 0], ['loadingscreens/original/', 'png', 0, 0, 0], ['loadingscreens/small/', 'jpg', 0, 244, 0]);
    $paths = array(0 => ['Icons/', $iconDirs, '/*.[bB][lL][pP]', true, 0], 1 => ['Spellbook/', [['Interface/Spellbook/', 'png', 0, 0, 0]], '/UI-Glyph-Rune*.blp', true, 0], 2 => ['PaperDoll/', array_slice($iconDirs, 0, 3), '/UI-{Backpack,PaperDoll}-*.blp', true, 0], 3 => ['GLUES/CHARACTERCREATE/UI-CharacterCreate-Races.blp', $iconDirs, '', true, 64], 4 => ['GLUES/CHARACTERCREATE/UI-CharacterCreate-CLASSES.blp', $iconDirs, '', true, 64], 5 => ['GLUES/CHARACTERCREATE/UI-CharacterCreate-Factions.blp', $iconDirs, '', true, 64], 7 => ['FlavorImages/', [['Interface/FlavorImages/', 'png', 0, 0, 0]], '/*.[bB][lL][pP]', false, 0], 8 => ['Pictures/', [['Interface/Pictures/', 'png', 0, 0, 0]], '/*.[bB][lL][pP]', false, 0], 9 => ['PvPRankBadges/', [['Interface/PvPRankBadges/', 'png', 0, 0, 0]], '/*.[bB][lL][pP]', false, 0], 10 => ['Calendar/Holidays/', $calendarDirs, '/*{rt,a,y,h,s}.[bB][lL][pP]', true, 0], 11 => ['GLUES/LOADINGSCREENS/', $loadScreenDirs, '/[lL][oO]*.[bB][lL][pP]', false, 0]);
    // textures are composed of 64x64 icons
    // numeric indexed arrays mimick the position on the texture
    $cuNames = array(2 => array('ui-paperdoll-slot-chest' => 'inventoryslot_chest', 'ui-backpack-emptyslot' => 'inventoryslot_empty', 'ui-paperdoll-slot-feet' => 'inventoryslot_feet', 'ui-paperdoll-slot-finger' => 'inventoryslot_finger', 'ui-paperdoll-slot-hands' => 'inventoryslot_hands', 'ui-paperdoll-slot-head' => 'inventoryslot_head', 'ui-paperdoll-slot-legs' => 'inventoryslot_legs', 'ui-paperdoll-slot-mainhand' => 'inventoryslot_mainhand', 'ui-paperdoll-slot-neck' => 'inventoryslot_neck', 'ui-paperdoll-slot-secondaryhand' => 'inventoryslot_offhand', 'ui-paperdoll-slot-ranged' => 'inventoryslot_ranged', 'ui-paperdoll-slot-relic' => 'inventoryslot_relic', 'ui-paperdoll-slot-shirt' => 'inventoryslot_shirt', 'ui-paperdoll-slot-shoulder' => 'inventoryslot_shoulder', 'ui-paperdoll-slot-tabard' => 'inventoryslot_tabard', 'ui-paperdoll-slot-trinket' => 'inventoryslot_trinket', 'ui-paperdoll-slot-waist' => 'inventoryslot_waist', 'ui-paperdoll-slot-wrists' => 'inventoryslot_wrists'), 3 => array(['race_human_male', 'race_dwarf_male', 'race_gnome_male', 'race_nightelf_male', 'race_draenei_male'], ['race_tauren_male', 'race_scourge_male', 'race_troll_male', 'race_orc_male', 'race_bloodelf_male'], ['race_human_female', 'race_dwarf_female', 'race_gnome_female', 'race_nightelf_female', 'race_draenei_female'], ['race_tauren_female', 'race_scourge_female', 'race_troll_female', 'race_orc_female', 'race_bloodelf_female']), 4 => array(['class_warrior', 'class_mage', 'class_rogue', 'class_druid'], ['class_hunter', 'class_shaman', 'class_priest', 'class_warlock'], ['class_paladin', 'class_deathknight']), 5 => array(['faction_alliance', 'faction_horde']), 6 => array([], [null, 'quest_start', 'quest_end', 'quest_start_daily', 'quest_end_daily']), 10 => array('calendar_winterveilstart' => 'calendar_winterveilstart', 'calendar_noblegardenstart' => 'calendar_noblegardenstart', 'calendar_childrensweekstart' => 'calendar_childrensweekstart', 'calendar_fishingextravaganza' => 'calendar_fishingextravaganzastart', 'calendar_harvestfestivalstart' => 'calendar_harvestfestivalstart', 'calendar_hallowsendstart' => 'calendar_hallowsendstart', 'calendar_lunarfestivalstart' => 'calendar_lunarfestivalstart', 'calendar_loveintheairstart' => 'calendar_loveintheairstart', 'calendar_midsummerstart' => 'calendar_midsummerstart', 'calendar_brewfeststart' => 'calendar_brewfeststart', 'calendar_darkmoonfaireelwynnstart' => 'calendar_darkmoonfaireelwynnstart', 'calendar_darkmoonfairemulgorestart' => 'calendar_darkmoonfairemulgorestart', 'calendar_darkmoonfaireterokkarstart' => 'calendar_darkmoonfaireterokkarstart', 'calendar_piratesday' => 'calendar_piratesdaystart', 'calendar_wotlklaunch' => 'calendar_wotlklaunchstart', 'calendar_dayofthedeadstart' => 'calendar_dayofthedeadstart', 'calendar_fireworks' => 'calendar_fireworksstart'));
    $writeImage = function ($name, $ext, $src, $srcDims, $destDims, $done) {
        $ok = false;
        $dest = imagecreatetruecolor($destDims['w'], $destDims['h']);
        imagesavealpha($dest, true);
        if ($ext == 'png') {
            imagealphablending($dest, false);
        }
        imagecopyresampled($dest, $src, $destDims['x'], $destDims['x'], $srcDims['x'], $srcDims['y'], $destDims['w'], $destDims['h'], $srcDims['w'], $srcDims['h']);
        switch ($ext) {
            case 'jpg':
                $ok = imagejpeg($dest, $name . '.' . $ext, 85);
                break;
            case 'gif':
                $ok = imagegif($dest, $name . '.' . $ext);
                break;
            case 'png':
                $ok = imagepng($dest, $name . '.' . $ext);
                break;
            default:
                CLISetup::log($done . ' - unsupported file fromat: ' . $ext, CLISetup::LOG_WARN);
        }
        imagedestroy($dest);
        if ($ok) {
            chmod($name . '.' . $ext, Util::FILE_ACCESS);
            CLISetup::log($done . ' - image ' . $name . '.' . $ext . ' written', CLISetup::LOG_OK);
        } else {
            CLISetup::log($done . ' - could not create image ' . $name . '.' . $ext, CLISetup::LOG_ERROR);
        }
        return $ok;
    };
    $checkSourceDirs = function ($sub, &$missing = []) use($imgPath, $dbcPath, $paths) {
        $hasMissing = false;
        foreach (array_column($paths, 0) as $subDir) {
            $p = sprintf($imgPath, $sub) . $subDir;
            if (!CLISetup::fileExists($p)) {
                $hasMissing = true;
                $missing[] = $p;
            }
        }
        $p = sprintf($dbcPath, $sub);
        if (!CLISetup::fileExists($p)) {
            $hasMissing = true;
            $missing[] = $p;
        }
        return !$hasMissing;
    };
    if (isset(FileGen::$cliOpts['icons'])) {
        array_push($groups, 0, 2, 3, 4, 5, 10);
    }
    if (isset(FileGen::$cliOpts['glyphs'])) {
        $groups[] = 1;
    }
    if (isset(FileGen::$cliOpts['pagetexts'])) {
        array_push($groups, 7, 8, 9);
    }
    if (isset(FileGen::$cliOpts['loadingscreens'])) {
        $groups[] = 11;
    }
    // filter by pasaed options
    if (!$groups) {
        // by default do not generate loadingscreens
        unset($paths[11]);
    } else {
        foreach (array_keys($paths) as $k) {
            if (!in_array($k, $groups)) {
                unset($paths[$k]);
            }
        }
    }
    foreach (CLISetup::$expectedPaths as $xp => $__) {
        if ($xp) {
            // if in subDir add trailing slash
            $xp .= '/';
        }
        if ($checkSourceDirs($xp, $missing)) {
            $locStr = $xp;
            break;
        }
    }
    // if no subdir had sufficient data, diaf
    if ($locStr === null) {
        CLISetup::log('one or more required directories are missing:', CLISetup::LOG_ERROR);
        foreach ($missing as $m) {
            CLISetup::log(' - ' . $m, CLISetup::LOG_ERROR);
        }
        return;
    }
    // init directories
    foreach (array_column($paths, 1) as $subDirs) {
        foreach ($subDirs as $sd) {
            if (!CLISetup::writeDir($destDir . $sd[0])) {
                $success = false;
            }
        }
    }
    // ok, departure from std::procedure here
    // scan ItemDisplayInfo.dbc and SpellIcon.dbc for expected images and save them to an array
    // load all icon paths into another array and xor these two
    // excess entries for the directory are fine, excess entries for the dbc's are not
    $dbcEntries = [];
    if (isset($paths[0]) || isset($paths[1])) {
        if (isset($paths[0]) && !isset($paths[1])) {
            $siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon WHERE iconPath NOT LIKE "%glyph-rune%"');
        } else {
            if (!isset($paths[0]) && isset($paths[1])) {
                $siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon WHERE iconPath LIKE "%glyph-rune%"');
            } else {
                $siRows = DB::Aowow()->selectCol('SELECT iconPath FROM dbc_spellicon');
            }
        }
        foreach ($siRows as $icon) {
            $dbcEntries[] = strtolower(sprintf('setup/mpqdata/%s', $locStr) . strtr($icon, ['\\' => '/']) . '.blp');
        }
    }
    if (isset($paths[0])) {
        $itemIcons = DB::Aowow()->selectCol('SELECT inventoryIcon1 FROM dbc_itemdisplayinfo WHERE inventoryIcon1 <> ""');
        foreach ($itemIcons as $icon) {
            $dbcEntries[] = strtolower(sprintf($imgPath, $locStr) . 'Icons/' . $icon . '.blp');
        }
        $eventIcons = DB::Aowow()->selectCol('SELECT textureString FROM dbc_holidays WHERE textureString <> ""');
        foreach ($eventIcons as $icon) {
            $dbcEntries[] = strtolower(sprintf($imgPath, $locStr) . 'Calendar/Holidays/' . $icon . 'Start.blp');
        }
    }
    // case-insensitive array_unique *vomits silently into a corner*
    $dbcEntries = array_intersect_key($dbcEntries, array_unique($dbcEntries));
    $allPaths = [];
    foreach ($paths as $i => $p) {
        $path = sprintf($imgPath, $locStr) . $p[0];
        if (!CLISetup::fileExists($path)) {
            continue;
        }
        $files = glob($path . $p[2], GLOB_BRACE);
        $allPaths = array_merge($allPaths, $files);
        CLISetup::log('processing ' . count($files) . ' files in ' . $path . '...');
        $j = 0;
        foreach ($files as $f) {
            ini_set('max_execution_time', 30);
            // max 30sec per image (loading takes the most time)
            $src = null;
            $img = explode('.', array_pop(explode('/', $f)));
            array_pop($img);
            // there are a hand full of images with multiple file endings or random dots in the name
            $img = implode('.', $img);
            // file not from dbc -> name from array or skip file
            if (!empty($cuNames[$i])) {
                if (!empty($cuNames[$i][strtolower($img)])) {
                    $img = $cuNames[$i][strtolower($img)];
                } else {
                    if (!$p[4]) {
                        $j += count($p[1]);
                        CLISetup::log('skipping extraneous file ' . $img . ' (+' . count($p[1]) . ')');
                        continue;
                    }
                }
            }
            $nFiles = count($p[1]) * ($p[4] ? array_sum(array_map('count', $cuNames[$i])) : count($files));
            foreach ($p[1] as $info) {
                if ($p[4]) {
                    foreach ($cuNames[$i] as $y => $row) {
                        foreach ($row as $x => $name) {
                            $j++;
                            $img = $p[3] ? strtolower($name) : $name;
                            $done = ' - ' . str_pad($j . '/' . $nFiles, 12) . str_pad('(' . number_format($j * 100 / $nFiles, 2) . '%)', 9);
                            if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir . $info[0] . $img . '.' . $info[1])) {
                                CLISetup::log($done . ' - file ' . $info[0] . $img . '.' . $info[1] . ' was already processed');
                                continue;
                            }
                            if (!$src) {
                                $src = $loadImageFile($f);
                            }
                            if (!$src) {
                                // error should be created by imagecreatefromblp
                                continue;
                            }
                            $from = array('x' => $info[4] + $p[4] * $x, 'y' => $info[4] + $p[4] * $y, 'w' => $p[4] - $info[4] * 2, 'h' => $p[4] - $info[4] * 2);
                            $to = array('x' => 0, 'y' => 0, 'w' => $info[3], 'h' => $info[3]);
                            if (!$writeImage($destDir . $info[0] . $img, $info[1], $src, $from, $to, $done)) {
                                $success = false;
                            }
                        }
                    }
                    // custom handle for combined icon 'quest_startend'
                    /* not used due to alphaChannel issues
                                            if ($p[4] == 32)
                                            {
                                                $dest = imagecreatetruecolor(19, 16);
                                                imagesavealpha($dest, true);
                                                imagealphablending($dest, true);
                    
                                                // excalmationmark, questionmark
                                                imagecopyresampled($dest, $src, 0, 1, 32 + 5, 32 + 2,  8, 15, 18, 30);
                                                imagecopyresampled($dest, $src, 5, 0, 64 + 1, 32 + 1, 10, 16, 18, 28);
                    
                                                if (imagegif($dest, $destDir.$info[0].'quest_startend.gif'))
                                                    CLISetup::log('                extra - image '.$destDir.$info[0].'quest_startend.gif written', CLISetup::LOG_OK);
                                                else
                                                {
                                                    CLISetup::log('                extra - could not create image '.$destDir.$info[0].'quest_startend.gif', CLISetup::LOG_ERROR);
                                                    $success = false;
                                                }
                    
                                                imagedestroy($dest);
                                            }
                                            */
                } else {
                    // icon -> lowercase
                    if ($p[3]) {
                        $img = strtolower($img);
                    }
                    $j++;
                    $done = ' - ' . str_pad($j . '/' . $nFiles, 12) . str_pad('(' . number_format($j * 100 / $nFiles, 2) . '%)', 9);
                    if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir . $info[0] . $img . '.' . $info[1])) {
                        CLISetup::log($done . ' - file ' . $info[0] . $img . '.' . $info[1] . ' was already processed');
                        continue;
                    }
                    if (!$src) {
                        $src = $loadImageFile($f);
                    }
                    if (!$src) {
                        // error should be created by imagecreatefromblp
                        continue;
                    }
                    $from = array('x' => $info[4], 'y' => $info[4], 'w' => ($info[2] ?: imagesx($src)) - $info[4] * 2, 'h' => ($info[2] ?: imagesy($src)) - $info[4] * 2);
                    $to = array('x' => 0, 'y' => 0, 'w' => $info[3] ?: imagesx($src), 'h' => $info[3] ?: imagesy($src));
                    if (!$writeImage($destDir . $info[0] . $img, $info[1], $src, $from, $to, $done)) {
                        $success = false;
                    }
                }
            }
            unset($src);
        }
    }
    // reset execTime
    ini_set('max_execution_time', FileGen::$defaultExecTime);
    if ($missing = array_diff(array_map('strtolower', $dbcEntries), array_map('strtolower', $allPaths))) {
        asort($missing);
        CLISetup::log('the following ' . count($missing) . ' images where referenced by DBC but not in the mpqData directory. They may need to be converted by hand later on.', CLISetup::LOG_WARN);
        foreach ($missing as $m) {
            CLISetup::log(' - ' . $m);
        }
    }
    return $success;
}
Пример #24
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;
            }
        }
    }
}
Пример #25
0
function item_stats(array $ids = [])
{
    $offset = 0;
    CLISetup::log(' - applying stats for enchantments');
    $enchStats = enchantment_stats();
    CLISetup::log('   ' . count($enchStats) . ' enchantments parsed');
    CLISetup::log(' - applying stats for items');
    while (true) {
        $items = new ItemStatSetup($offset, SqlGen::$stepSize, $ids, $enchStats);
        if ($items->error) {
            break;
        }
        $max = max($items->getFoundIDs());
        $num = count($items->getFoundIDs());
        CLISetup::log(' * sets ' . ($offset + 1) . ' - ' . $max);
        $offset = $max;
        $items->writeStatsTable();
    }
    return true;
}
Пример #26
0
function quests(array $ids = [])
{
    $baseQuery = '
        SELECT
            q.ID,
            QuestType,                                      -- Method
            QuestLevel,
            MinLevel,
            MaxLevel,
            QuestSortID,
            QuestSortID AS zoneOrSortBak,                   -- ZoneOrSortBak
            QuestInfoID,                                    -- QuestType
            SuggestedGroupNum,
            TimeAllowed,
            IFNULL(gesqr.eventEntry, 0) AS eventId,
            PrevQuestId,
            NextQuestId,
            ExclusiveGroup,
            RewardNextQuest,
            Flags,
            SpecialFlags,
            0 AS cuFlags,                                   -- cuFlags
            AllowableClasses,
            AllowableRaces,
            RequiredSkillId,            RequiredSkillPoints,
            RequiredFactionId1,         RequiredFactionId2,
            RequiredFactionValue1,      RequiredFactionValue2,
            RequiredMinRepFaction,      RequiredMaxRepFaction,
            RequiredMinRepValue,        RequiredMaxRepValue,
            RequiredPlayerKills,
            StartItem,
            ProvidedItemCount,
            SourceSpellId,
            RewardXPDifficulty,                             -- QuestXP.dbc x level
            RewardMoney,
            RewardBonusMoney,
            RewardDisplaySpell,         RewardSpell,
            RewardHonor * 124 * RewardKillHonor,            -- alt calculation in QuestDef.cpp -> Quest::CalculateHonorGain(playerLevel)
            RewardMailTemplateId,       RewardMailDelay,
            RewardTitle,
            RewardTalents,
            RewardArenaPoints,
            RewardItem1,                RewardItem2,                RewardItem3,                RewardItem4,
            RewardAmount1,              RewardAmount2,              RewardAmount3,              RewardAmount4,
            RewardChoiceItemID1,        RewardChoiceItemID2,        RewardChoiceItemID3,        RewardChoiceItemID4,        RewardChoiceItemID5,        RewardChoiceItemID6,
            RewardChoiceItemQuantity1,  RewardChoiceItemQuantity2,  RewardChoiceItemQuantity3,  RewardChoiceItemQuantity4,  RewardChoiceItemQuantity5,  RewardChoiceItemQuantity6,
            RewardFactionID1,           RewardFactionID2,           RewardFactionID3,           RewardFactionID4,           RewardFactionID5,
            IF (RewardFactionOverride1 <> 0, RewardFactionOverride1 / 100, RewardFactionValue1),
            IF (RewardFactionOverride2 <> 0, RewardFactionOverride2 / 100, RewardFactionValue2),
            IF (RewardFactionOverride3 <> 0, RewardFactionOverride3 / 100, RewardFactionValue3),
            IF (RewardFactionOverride4 <> 0, RewardFactionOverride4 / 100, RewardFactionValue4),
            IF (RewardFactionOverride5 <> 0, RewardFactionOverride5 / 100, RewardFactionValue5),
            LogTitle,                   Title_loc2,                 Title_loc3,                 Title_loc4,                 Title_loc6,                 Title_loc8,
            LogDescription,             Objectives_loc2,            Objectives_loc3,            Objectives_loc4,            Objectives_loc6,            Objectives_loc8,
            QuestDescription,           Details_loc2,               Details_loc3,               Details_loc4,               Details_loc6,               Details_loc8,
            AreaDescription,            EndText_loc2,               EndText_loc3,               EndText_loc4,               EndText_loc6,               EndText_loc8,
            qor.RewardText,             OfferRewardText_loc2,       OfferRewardText_loc3,       OfferRewardText_loc4,       OfferRewardText_loc6,       OfferRewardText_loc8,
            qri.CompletionText,         RequestItemsText_loc2,      RequestItemsText_loc3,      RequestItemsText_loc4,      RequestItemsText_loc6,      RequestItemsText_loc8,
            QuestCompletionLog,         CompletedText_loc2,         CompletedText_loc3,         CompletedText_loc4,         CompletedText_loc6,         CompletedText_loc8,
            RequiredNpcOrGo1,           RequiredNpcOrGo2,           RequiredNpcOrGo3,           RequiredNpcOrGo4,
            RequiredNpcOrGoCount1,      RequiredNpcOrGoCount2,      RequiredNpcOrGoCount3,      RequiredNpcOrGoCount4,
            ItemDrop1,                  ItemDrop2,                  ItemDrop3,                  ItemDrop4,
            ItemDropQuantity1,          ItemDropQuantity2,          ItemDropQuantity3,          ItemDropQuantity4,
            RequiredItemId1,            RequiredItemId2,            RequiredItemId3,            RequiredItemId4,            RequiredItemId5,            RequiredItemId6,
            RequiredItemCount1,         RequiredItemCount2,         RequiredItemCount3,         RequiredItemCount4,         RequiredItemCount5,         RequiredItemCount6,
            ObjectiveText1,             ObjectiveText1_loc2,        ObjectiveText1_loc3,        ObjectiveText1_loc4,        ObjectiveText1_loc6,        ObjectiveText1_loc8,
            ObjectiveText2,             ObjectiveText2_loc2,        ObjectiveText2_loc3,        ObjectiveText2_loc4,        ObjectiveText2_loc6,        ObjectiveText2_loc8,
            ObjectiveText3,             ObjectiveText3_loc2,        ObjectiveText3_loc3,        ObjectiveText3_loc4,        ObjectiveText3_loc6,        ObjectiveText3_loc8,
            ObjectiveText4,             ObjectiveText4_loc2,        ObjectiveText4_loc3,        ObjectiveText4_loc4,        ObjectiveText4_loc6,        ObjectiveText4_loc8
        FROM
            quest_template q
        LEFT JOIN
            quest_template_addon qa ON q.ID = qa.ID
        LEFT JOIN
            quest_offer_reward qor ON q.ID = qor.ID
        LEFT JOIN
            quest_request_items qri ON q.ID = qri.ID
        LEFT JOIN
            locales_quest lq ON q.ID = lq.Id
        LEFT JOIN
            game_event_seasonal_questrelation gesqr ON gesqr.questId = q.ID
        {
        WHERE
            q.ID IN (?a)
        }
        LIMIT
            ?d, ?d';
    $xpQuery = '
        UPDATE
            ?_quests q,
            dbc_questxp xp
        SET
            rewardXP = (CASE rewardXP
                WHEN 0 THEN xp.Field1   WHEN 1 THEN xp.Field2   WHEN 2 THEN xp.Field3   WHEN 3 THEN xp.Field4   WHEN 4 THEN xp.Field5
                WHEN 5 THEN xp.Field6   WHEN 6 THEN xp.Field7   WHEN 7 THEN xp.Field8   WHEN 8 THEN xp.Field9   WHEN 9 THEN xp.Field10
                ELSE 0
            END)
        WHERE
            xp.id = q.level { AND
            q.id IN(?a)
            }';
    $repQuery = '
        UPDATE
            ?_quests q
        LEFT JOIN
            dbc_questfactionreward rep ON rep.Id = IF(rewardFactionValue?d > 0, 1, 2)
        SET
            rewardFactionValue?d = (CASE ABS(rewardFactionValue?d)
                WHEN 0 THEN rep.Field1   WHEN 1 THEN rep.Field2   WHEN 2 THEN rep.Field3   WHEN 3 THEN rep.Field4   WHEN 4 THEN rep.Field5
                WHEN 5 THEN rep.Field6   WHEN 6 THEN rep.Field7   WHEN 7 THEN rep.Field8   WHEN 8 THEN rep.Field9   WHEN 9 THEN rep.Field10
                ELSE 0
            END)
        WHERE
            ABS(rewardFactionValue?d) BETWEEN 1 AND 10 { AND
            q.id IN(?a)
            }';
    $offset = 0;
    while ($quests = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, $offset, SqlGen::$stepSize)) {
        CLISetup::log(' * sets ' . ($offset + 1) . ' - ' . ($offset + count($quests)));
        $offset += SqlGen::$stepSize;
        foreach ($quests as $q) {
            DB::Aowow()->query('REPLACE INTO ?_quests VALUES (?a)', array_values($q));
        }
    }
    /*
        just some random thoughts here ..
        quest-custom-flags are derived from flags and specialFlags
        since they are not used further than being sent to JS as wFlags this is fine..
        should they be saved to db anyway..?
        same with QUEST_FLAG_UNAVAILABLE => CUSTOM_EXCLUDE_FOR_LISTVIEW
    */
    // unpack XP-reward
    DB::Aowow()->query($xpQuery, $ids ?: DBSIMPLE_SKIP);
    // unpack Rep-rewards
    for ($i = 1; $i < 6; $i++) {
        DB::Aowow()->query($repQuery, $i, $i, $i, $i, $ids ?: DBSIMPLE_SKIP);
    }
    // update zoneOrSort/QuestSortID .. well .. now "not documenting" bites me in the ass .. ~700 quests were changed, i don't know by what method
    $eventSet = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday <> 0');
    $holidaySorts = array(141 => -1001, 181 => -374, 201 => -1002, 301 => -101, 321 => -1005, 324 => -1003, 327 => -366, 341 => -369, 372 => -370, 374 => -364, 376 => -364, 404 => -375, 409 => -41, 423 => -376, 424 => -101);
    foreach ($holidaySorts as $hId => $sort) {
        if (!empty($eventSet[$hId])) {
            DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE eventId = ?d{ AND id IN (?a)}', $sort, $eventSet[$hId], $ids ?: DBSIMPLE_SKIP);
        }
    }
    /*
        zoneorsort for quests will need updating
        points non-instanced area with identic name for instance quests
    
        SELECT
            DISTINCT CONCAT('[',q.zoneorsort,',"',a.name_loc0,'"],')
        FROM
            dbc_map m,
            ?_quests q,
            dbc_areatable a
        WHERE
            a.id = q.zoneOrSort AND
            q.zoneOrSort > 0 AND
            a.mapId = m.id AND
            m.areaType = 1
        ORDER BY
            a.name_loc0
        ASC;
    */
    // 'special' special cases
    // fishing quests to stranglethorn extravaganza
    DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE id IN (?a){ AND id IN (?a)}', -101, [8228, 8229], $ids ?: DBSIMPLE_SKIP);
    // dungeon quests to Misc/Dungeon Finder
    DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE (specialFlags & ?d OR id IN (?a)){ AND id IN (?a)}', -1010, QUEST_FLAG_SPECIAL_DUNGEON_FINDER, [24789, 24791, 24923], $ids ?: DBSIMPLE_SKIP);
    return true;
}
Пример #27
0
function source(array $ids = [])
{
    $insBasic = 'INSERT INTO ?_source (`type`, typeId, src?d)                       VALUES [V] ON DUPLICATE KEY UPDATE moreType = NULL, moreTypeId = NULL, src?d = VALUES(src?d)';
    $insMore = 'INSERT INTO ?_source (`type`, typeId, src?d, moreType, moreTypeId) VALUES [V] ON DUPLICATE KEY UPDATE moreType = NULL, moreTypeId = NULL, src?d = VALUES(src?d)';
    $insSub = 'INSERT INTO ?_source (`type`, typeId, src?d, moreType, moreTypeId) ?s         ON DUPLICATE KEY UPDATE moreType = NULL, moreTypeId = NULL, src?d = VALUES(src?d)';
    // please note, this workes without checks, because we do not use strings here
    function queryfy($ph, array $data, $query)
    {
        $buff = [];
        array_walk_recursive($data, function (&$item) {
            if ($item === null) {
                $item = 'NULL';
            }
        });
        foreach ($data as $d) {
            $buff[] = '(' . implode(', ', $d ?: 'NULL') . ')';
        }
        return str_replace($ph, implode(', ', $buff), $query);
    }
    function pushBuffer(&$buff, $type, $typeId, $mType = 0, $mTypeId = 0, $src = 1)
    {
        $b =& $buff[$typeId];
        if (isset($b) && $b[3] === null) {
            return;
        } else {
            if (isset($b) && $b[1] != $typeId) {
                $b[3] = $b[4] = null;
                $b[2] |= $src;
                // only quests atm
            } else {
                if ($mType && $mTypeId) {
                    $b = [$type, $typeId, $src, $mType, $mTypeId];
                } else {
                    $b = [$type, $typeId, $src, null, null];
                }
            }
        }
    }
    function taughtSpell($item)
    {
        # spelltrigger_X (0: onUse; 6: onLearnSpell)
        # spell: 483 & 55884 are learn spells
        // should not be able to teach spells (recipe || mount || vanityPet)
        if ($item['class'] != ITEM_CLASS_RECIPE && ($item['class'] != ITEM_CLASS_MISC || $item['subclass'] != 2 && $item['subclass'] != 5)) {
            return 0;
        }
        // wotlk system
        if (($item['spellid_1'] == 483 || $item['spellid_1'] == 55884) && $item['spelltrigger_1'] == 0 && $item['spellid_2'] > 0 && $item['spelltrigger_2'] == 6) {
            return $item['spellid_2'];
        }
        // deprecated system
        if ($item['spellid_1'] != 483 && $item['spellid_1'] != 55884 && $item['spellid_1'] > 0 && $item['spelltrigger_1'] == 0) {
            return $item['spellid_1'];
        }
        return 0;
    }
    // cant update existing rows
    if ($ids) {
        DB::Aowow()->query('DELETE FROM ?_source WHERE `type` = ?d AND typeId IN (?a)', $well, $wellll);
    } else {
        DB::Aowow()->query('TRUNCATE TABLE ?_source');
    }
    /***************************/
    /* Item & inherited Spells */
    /***************************/
    CLISetup::log(' - Items & Spells [inherited]');
    # also everything from items that teach spells, is src of spell
    # todo: check if items have learn-spells (effect: 36)
    CLISetup::log('   * resolve ref-loot tree');
    $refLoot = DB::World()->select('
        SELECT
            rlt.Entry AS ARRAY_KEY,
            IF(Reference, -Reference, Item) AS ARRAY_KEY2,
            it.entry, it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            COUNT(1) AS qty
        FROM
            reference_loot_template rlt
        LEFT JOIN
            item_template it ON rlt.Reference = 0 AND rlt.Item = it.entry
        GROUP BY
            ARRAY_KEY, ARRAY_KEY2
    ');
    $hasChanged = true;
    while ($hasChanged) {
        $hasChanged = false;
        foreach ($refLoot as $entry => &$refData) {
            foreach ($refData as $itemOrRef => $data) {
                if ($itemOrRef > 0) {
                    continue;
                }
                if (!empty($refLoot[-$itemOrRef])) {
                    foreach ($refLoot[-$itemOrRef] as $key => $data) {
                        if (!empty($refData[$key])) {
                            $refData[$key]['qty'] += $data['qty'];
                        } else {
                            $refLoot[-$itemOrRef][$key] = $data;
                        }
                    }
                }
                unset($refData[$itemOrRef]);
                $hasChanged = true;
            }
        }
    }
    ###############
    #  1: Crafted #
    ###############
    CLISetup::log('   * #1  Crafted');
    $spellBuff = [];
    $itemBuff = [];
    $itemSpells = DB::Aowow()->selectCol('
        SELECT
            effect1CreateItemId AS ARRAY_KEY, s.id AS spell
        FROM
            dbc_spell s JOIN dbc_skilllineability sla ON s.id = sla.spellId
        WHERE
            effect1CreateItemId > 0 AND sla.skillLineId IN (?a)
        GROUP BY
            ARRAY_KEY', [164, 165, 171, 182, 186, 197, 202, 333, 393, 755, 773, 129, 185, 356, 762]);
    $spellItems = DB::World()->select('SELECT entry AS ARRAY_KEY, class, subclass, spellid_1, spelltrigger_1, spellid_2, spelltrigger_2 FROM item_template WHERE entry IN (?a)', array_keys($itemSpells));
    foreach ($spellItems as $iId => $si) {
        if ($_ = taughtSpell($si)) {
            $spellBuff[$_] = [TYPE_SPELL, $_, 1, TYPE_SPELL, $itemSpells[$iId]];
        }
        $itemBuff[$iId] = [TYPE_ITEM, $iId, 1, TYPE_SPELL, $itemSpells[$iId]];
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 1, 1, 1);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 1, 1, 1);
    }
    ############
    #  2: Drop #
    ############
    CLISetup::log('   * #2  Drop');
    $spellBuff = [];
    $itemBuff = [];
    $creatureLoot = DB::World()->select('
        SELECT
            IF(clt.Reference > 0, -clt.Reference, clt.Item) AS ARRAY_KEY,
            ct.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            count(1) AS qty
        FROM
            creature_loot_template clt
        JOIN
            creature_template ct ON clt.entry = ct.lootid
        LEFT JOIN
            item_template it ON it.entry = clt.Item AND clt.Reference <= 0
        WHERE
            ct.lootid > 0
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($creatureLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
    }
    $objectOT = [];
    $exclLocks = DB::Aowow()->selectCol('SELECT id FROM dbc_lock WHERE properties1 IN (2, 3)');
    $objectLoot = DB::World()->select('
        SELECT
            IF(glt.Reference > 0, -glt.Reference, glt.Item) AS ARRAY_KEY,
            gt.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            count(1) AS qty
        FROM
            gameobject_loot_template glt
        JOIN
            gameobject_template gt ON glt.entry = gt.Data1
        LEFT JOIN
            item_template it ON it.entry = glt.Item AND glt.Reference <= 0
        WHERE
            `type` = 3 AND gt.Data1 > 0 AND gt.Data0 NOT IN (?a)
        GROUP BY
            ARRAY_KEY', $exclLocks);
    foreach ($objectLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
                }
                $objectOT[] = $iId;
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
        }
        $objectOT[] = $roi;
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
    }
    $itemOT = [];
    $itemLoot = DB::World()->select('
        SELECT
            IF(ilt.Reference > 0, -ilt.Reference, ilt.Item) AS ARRAY_KEY,
            itA.entry,
            itB.class, itB.subclass, itB.spellid_1, itB.spelltrigger_1, itB.spellid_2, itB.spelltrigger_2,
            count(1) AS qty
        FROM
            item_loot_template ilt
        JOIN
            item_template itA ON ilt.entry = itA.entry
        LEFT JOIN
            item_template itB ON itB.entry = ilt.Item AND ilt.Reference <= 0
        WHERE
            itA.flags & 0x4
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($itemLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']);
                }
                $itemOT[] = $iId;
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']);
        }
        $itemOT[] = $roi;
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 2, 2, 2);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 2, 2, 2);
    }
    DB::Aowow()->query('UPDATE ?_items SET cuFLags = cuFlags | ?d WHERE id IN (?a)', ITEM_CU_OT_ITEMLOOT, $itemOT);
    DB::Aowow()->query('UPDATE ?_items SET cuFLags = cuFlags | ?d WHERE id IN (?a)', ITEM_CU_OT_OBJECTLOOT, $objectOT);
    ###########
    #  3: PvP # (Vendors w/ xCost Arena/Honor)
    ###########
    CLISetup::log('   * #3  PvP');
    // var g_sources_pvp = {
    // 1: 'Arena',
    // 2: 'Battleground',
    // 4: 'World'               basicly the tokens you get for openPvP .. manual data
    // };
    $spellBuff = [];
    $itemBuff = [];
    $xCostH = DB::Aowow()->selectCol('SELECT Id FROM dbc_itemextendedcost WHERE reqHonorPoints > 0 AND reqArenaPoints = 0');
    $xCostA = DB::Aowow()->selectCol('SELECT Id FROM dbc_itemextendedcost WHERE reqArenaPoints > 0');
    $vendorQuery = 'SELECT n.item AS ARRAY_KEY, SUM(n.qty) AS qty, it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2 FROM (
                        SELECT item, COUNT(1) AS qty FROM npc_vendor WHERE ExtendedCost IN (?a) GROUP BY item
                        UNION
                        SELECT item, COUNT(1) AS qty FROM game_event_npc_vendor genv JOIN creature c ON c.guid = genv.guid WHERE ExtendedCost IN (?a) GROUP BY item
                    ) n JOIN item_template it ON it.entry = n.item
                    GROUP BY item';
    foreach (DB::World()->select($vendorQuery, $xCostA, $xCostA) as $iId => $v) {
        if ($_ = taughtSpell($v)) {
            $spellBuff[$_] = [TYPE_SPELL, $_, 1];
        }
        $itemBuff[$iId] = [TYPE_ITEM, $iId, 1];
    }
    foreach (DB::World()->select($vendorQuery, $xCostH, $xCostH) as $iId => $v) {
        if ($_ = taughtSpell($v)) {
            $spellBuff[$_] = [TYPE_SPELL, $_, 2];
        }
        $itemBuff[$iId] = [TYPE_ITEM, $iId, 2];
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insBasic), 3, 3, 3);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insBasic), 3, 3, 3);
    }
    #############
    #  4: Quest #
    #############
    CLISetup::log('   * #4  Quest');
    $spellBuff = [];
    $itemBuff = [];
    $quests = DB::World()->select('SELECT n.item AS ARRAY_KEY, n.ID AS quest, SUM(n.qty) AS qty, BIT_OR(n.side) AS side, it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2 FROM (
            SELECT RewardChoiceItemID1 AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardChoiceItemID1 > 0 GROUP BY item UNION
            SELECT RewardChoiceItemID2 AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardChoiceItemID2 > 0 GROUP BY item UNION
            SELECT RewardChoiceItemID3 AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardChoiceItemID3 > 0 GROUP BY item UNION
            SELECT RewardChoiceItemID4 AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardChoiceItemID4 > 0 GROUP BY item UNION
            SELECT RewardChoiceItemID5 AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardChoiceItemID5 > 0 GROUP BY item UNION
            SELECT RewardChoiceItemID6 AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardChoiceItemID6 > 0 GROUP BY item UNION
            SELECT RewardItem1         AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardItem1         > 0 GROUP BY item UNION
            SELECT RewardItem2         AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardItem2         > 0 GROUP BY item UNION
            SELECT RewardItem3         AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardItem3         > 0 GROUP BY item UNION
            SELECT RewardItem4         AS item, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardItem4         > 0 GROUP BY item
        ) n JOIN item_template it ON it.entry = n.item
        GROUP BY item');
    foreach ($quests as $iId => $q) {
        if ($_ = taughtSpell($q)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $q['qty'] > 1 ? 0 : TYPE_QUEST, $q['quest'], $q['side']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $iId, $q['qty'] > 1 ? 0 : TYPE_QUEST, $q['quest'], $q['side']);
    }
    $mailLoot = DB::World()->select('
        SELECT
            IF(mlt.Reference > 0, -mlt.Reference, mlt.Item) AS ARRAY_KEY,
            qt.ID AS entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            count(1) AS qty,
            BIT_OR(IF(qt.RequiredRaces & 0x2B2 AND !(qt.RequiredRaces & 0x44D), 2, IF(qt.RequiredRaces & 0x44D AND !(qt.RequiredRaces & 0x2B2), 1, 3))) AS side
        FROM
            mail_loot_template mlt
        JOIN
            quest_template qt ON qt.RewardMailTemplateId = mlt.entry
        LEFT JOIN
            item_template it ON it.entry = mlt.Item AND mlt.Reference <= 0
        WHERE
            qt.RewardMailTemplateId > 0
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($mailLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']);
                }
                $itemOT[] = $iId;
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']);
        }
        $itemOT[] = $roi;
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 4, 4, 4);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 4, 4, 4);
    }
    ##############
    #  5: Vendor # (w/o xCost Arena/Honor)
    ##############
    CLISetup::log('   * #5  Vendor');
    $spellBuff = [];
    $itemBuff = [];
    $xCostIds = DB::Aowow()->selectCol('SELECT Id FROM dbc_itemextendedcost WHERE reqHonorPoints <> 0 OR reqArenaPoints <> 0');
    $vendors = DB::World()->select('SELECT n.item AS ARRAY_KEY, n.npc, SUM(n.qty) AS qty, it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2 FROM (
            SELECT item, entry AS npc, COUNT(1) AS qty FROM npc_vendor WHERE ExtendedCost NOT IN (?a) GROUP BY item
            UNION
            SELECT item, c.id AS npc, COUNT(1) AS qty FROM game_event_npc_vendor genv JOIN creature c ON c.guid = genv.guid WHERE ExtendedCost NOT IN (?a) GROUP BY item
        ) n JOIN item_template it ON it.entry = n.item
        GROUP BY item', $xCostIds, $xCostIds);
    foreach ($vendors as $iId => $v) {
        if ($_ = taughtSpell($v)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $v['qty'] > 1 ? 0 : TYPE_NPC, $v['npc']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $iId, $v['qty'] > 1 ? 0 : TYPE_NPC, $v['npc']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 5, 5, 5);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 5, 5, 5);
    }
    ###############
    # 10: Starter #
    ###############
    CLISetup::log('   * #10 Starter');
    if ($pcii = DB::World()->select('SELECT ?d, itemid, 1 FROM playercreateinfo_item', TYPE_ITEM)) {
        DB::Aowow()->query(queryfy('[V]', $pcii, $insBasic), 10, 10, 10);
    }
    for ($i = 1; $i < 21; $i++) {
        DB::Aowow()->query($insSub, 10, DB::Aowow()->subquery('SELECT ?d, item?d, 1, NULL AS m, NULL AS mt FROM dbc_charstartoutfit WHERE item?d > 0', TYPE_ITEM, $i, $i), 10, 10);
    }
    ###################
    # 12: Achievement #
    ###################
    CLISetup::log('   * #12 Achievement');
    $spellBuff = [];
    $itemBuff = [];
    $xItems = DB::Aowow()->select('SELECT id AS entry, itemExtra AS ARRAY_KEY, COUNT(1) AS qty FROM ?_achievement WHERE itemExtra > 0 GROUP BY itemExtra');
    $rewItems = DB::World()->select('
        SELECT
            src.item AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            COUNT(1) AS qty
        FROM (
            SELECT IFNULL(IF(mlt.Reference > 0, -mlt.Reference, mlt.Item), ar.item) AS item, ar.entry
            FROM achievement_reward ar LEFT JOIN mail_loot_template mlt ON mlt.entry = ar.mailTemplate
            WHERE ar.mailTemplate > 0 OR ar.item > 0
        ) src
        LEFT JOIN
            item_template it ON src.item = it.entry
        GROUP BY
            ARRAY_KEY
    ');
    $extraItems = DB::World()->select('SELECT entry AS ARRAY_KEY, class, subclass, spellid_1, spelltrigger_1, spellid_2, spelltrigger_2 FROM item_template WHERE entry IN (?a)', array_keys($xItems));
    foreach ($extraItems as $iId => $l) {
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $xItems[$iId]['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $xItems[$iId]['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $iId, $xItems[$iId]['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $xItems[$iId]['entry']);
    }
    foreach ($rewItems as $iId => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $iId, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 12, 12, 12);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 12, 12, 12);
    }
    ####################
    # 15: Disenchanted #
    ####################
    CLISetup::log('   * #15 Disenchanted');
    $spellBuff = [];
    $itemBuff = [];
    $deLoot = DB::World()->select('
        SELECT
            IF(dlt.Reference > 0, -dlt.Reference, dlt.Item) AS ARRAY_KEY,
            itA.entry,
            itB.class, itB.subclass, itB.spellid_1, itB.spelltrigger_1, itB.spellid_2, itB.spelltrigger_2,
            count(1) AS qty
        FROM
            disenchant_loot_template dlt
        JOIN
            item_template itA ON dlt.entry = itA.DisenchantId
        LEFT JOIN
            item_template itB ON itB.entry = dlt.Item AND dlt.Reference <= 0
        WHERE
            itA.DisenchantId > 0
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($deLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 15, 15, 15);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 15, 15, 15);
    }
    ##############
    # 16: Fished #
    ##############
    CLISetup::log('   * #16 Fished');
    $spellBuff = [];
    $itemBuff = [];
    $fishLoot = DB::World()->select('
        SELECT
            src.itemOrRef AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            count(1) AS qty
        FROM (
            SELECT 0 AS entry, IF(flt.Reference > 0, -flt.Reference, flt.Item) itemOrRef FROM fishing_loot_template flt UNION
            SELECT   gt.entry, IF(glt.Reference > 0, -glt.Reference, glt.Item) itemOrRef FROM gameobject_template   gt  JOIN gameobject_loot_template glt ON glt.entry = gt.Data1 WHERE `type` = 25 AND gt.Data1 > 0
        ) src
        LEFT JOIN
            item_template it ON src.itemOrRef > 0 AND src.itemOrRef = it.entry
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($fishLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 16, 16, 16);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 16, 16, 16);
    }
    ################
    # 17: Gathered #
    ################
    CLISetup::log('   * #17 Gathered');
    $spellBuff = [];
    $itemBuff = [];
    $herbLocks = DB::Aowow()->selectCol('SELECT id FROM dbc_lock WHERE properties1 = 2');
    $herbLoot = DB::World()->select('
        SELECT
            src.itemOrRef AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            count(1) AS qty,
            src.srcType
        FROM (
            SELECT ct.entry, IF(slt.Reference > 0, -slt.Reference, slt.Item) itemOrRef, ?d AS srcType FROM creature_template   ct JOIN skinning_loot_template   slt ON slt.entry = ct.skinloot WHERE (type_flags & ?d) AND ct.skinloot > 0 UNION
            SELECT gt.entry, IF(glt.Reference > 0, -glt.Reference, glt.Item) itemOrRef, ?d AS srcType FROM gameobject_template gt JOIN gameobject_loot_template glt ON glt.entry = gt.Data1    WHERE gt.`type` = 3 AND gt.Data1 > 0 AND Data0 IN (?a)
        ) src
        LEFT JOIN
            item_template it ON src.itemOrRef > 0 AND src.itemOrRef = it.entry
        GROUP BY
            ARRAY_KEY', TYPE_NPC, NPC_TYPEFLAG_HERBLOOT, TYPE_OBJECT, $herbLocks);
    foreach ($herbLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 17, 17, 17);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 17, 17, 17);
    }
    ##############
    # 18: Milled #
    ##############
    CLISetup::log('   * #18 Milled');
    $spellBuff = [];
    $itemBuff = [];
    $millLoot = DB::World()->select('
        SELECT
            IF(mlt.Reference > 0, -mlt.Reference, mlt.Item) AS ARRAY_KEY,
            itA.entry,
            itB.class, itB.subclass, itB.spellid_1, itB.spelltrigger_1, itB.spellid_2, itB.spelltrigger_2,
            count(1) AS qty
        FROM
            milling_loot_template mlt
        JOIN
            item_template itA ON mlt.entry = itA.entry
        LEFT JOIN
            item_template itB ON itB.entry = mlt.Item AND mlt.Reference <= 0
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($millLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 18, 18, 18);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 18, 18, 18);
    }
    #############
    # 19: Mined #
    #############
    CLISetup::log('   * #19 Mined');
    $spellBuff = [];
    $itemBuff = [];
    $mineLocks = DB::Aowow()->selectCol('SELECT id FROM dbc_lock WHERE properties1 = 3');
    $mineLoot = DB::World()->select('
        SELECT
            src.itemOrRef AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            count(1) AS qty,
            src.srcType
        FROM (
            SELECT ct.entry, IF(slt.Reference > 0, -slt.Reference, slt.Item) itemOrRef, ?d AS srcType FROM creature_template   ct JOIN skinning_loot_template   slt ON slt.entry = ct.skinloot WHERE (type_flags & ?d) AND ct.skinloot > 0 UNION
            SELECT gt.entry, IF(glt.Reference > 0, -glt.Reference, glt.Item) itemOrRef, ?d AS srcType FROM gameobject_template gt JOIN gameobject_loot_template glt ON glt.entry = gt.Data1    WHERE gt.`type` = 3 AND gt.Data1 > 0 AND Data0 IN (?a)
        ) src
        LEFT JOIN
            item_template it ON src.itemOrRef > 0 AND src.itemOrRef = it.entry
        GROUP BY
            ARRAY_KEY', TYPE_NPC, NPC_TYPEFLAG_MININGLOOT, TYPE_OBJECT, $mineLocks);
    foreach ($mineLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 19, 19, 19);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 19, 19, 19);
    }
    ##################
    # 20: Prospected #
    ##################
    CLISetup::log('   * #20 Prospected');
    $spellBuff = [];
    $itemBuff = [];
    $prospectLoot = DB::World()->select('
        SELECT
            IF(plt.Reference > 0, -plt.Reference, plt.Item) AS ARRAY_KEY,
            itA.entry,
            itB.class, itB.subclass, itB.spellid_1, itB.spelltrigger_1, itB.spellid_2, itB.spelltrigger_2,
            count(1) AS qty
        FROM
            prospecting_loot_template plt
        JOIN
            item_template itA ON plt.entry = itA.entry
        LEFT JOIN
            item_template itB ON itB.entry = plt.Item AND plt.Reference <= 0
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($prospectLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 20, 20, 20);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 20, 20, 20);
    }
    ##################
    # 21: Pickpocket #
    ##################
    CLISetup::log('   * #21 Pickpocket');
    $spellBuff = [];
    $itemBuff = [];
    $theftLoot = DB::World()->select('
        SELECT
            src.itemOrRef AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            COUNT(1) AS qty
        FROM (
            SELECT ct.entry, IF(plt.Reference > 0, -plt.Reference, plt.Item) itemOrRef FROM creature_template ct JOIN pickpocketing_loot_template plt ON plt.entry = ct.pickpocketloot WHERE ct.pickpocketloot > 0
        ) src
        LEFT JOIN
            item_template it ON src.itemOrRef > 0 AND src.itemOrRef = it.entry
        GROUP BY
            ARRAY_KEY
    ');
    foreach ($theftLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 21, 21, 21);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 21, 21, 21);
    }
    ################
    # 22: Salvaged #
    ################
    CLISetup::log('   * #22 Salvaged');
    $spellBuff = [];
    $itemBuff = [];
    $salvageLoot = DB::World()->select('
        SELECT
            src.itemOrRef AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            COUNT(1) AS qty
        FROM (
            SELECT ct.entry, IF(slt.Reference > 0, -slt.Reference, slt.Item) itemOrRef FROM creature_template ct JOIN skinning_loot_template slt ON slt.entry = ct.skinloot WHERE (type_flags & ?d) AND ct.skinloot > 0
        ) src
        LEFT JOIN
            item_template it ON src.itemOrRef > 0 AND src.itemOrRef = it.entry
        GROUP BY
            ARRAY_KEY', NPC_TYPEFLAG_ENGINEERLOOT);
    foreach ($salvageLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 22, 22, 22);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 22, 22, 22);
    }
    ###############
    # 23: Skinned #
    ###############
    CLISetup::log('   * #23 Skinned');
    $spellBuff = [];
    $itemBuff = [];
    $skinLoot = DB::World()->select('
        SELECT
            src.itemOrRef AS ARRAY_KEY,
            src.entry,
            it.class, it.subclass, it.spellid_1, it.spelltrigger_1, it.spellid_2, it.spelltrigger_2,
            COUNT(1) AS qty
        FROM (
            SELECT ct.entry, IF(slt.Reference > 0, -slt.Reference, slt.Item) itemOrRef FROM creature_template ct JOIN skinning_loot_template slt ON slt.entry = ct.skinloot WHERE (type_flags & ?d) = 0 AND ct.skinloot > 0
        ) src
        LEFT JOIN
            item_template it ON src.itemOrRef > 0 AND src.itemOrRef = it.entry
        GROUP BY
            ARRAY_KEY', NPC_TYPEFLAG_HERBLOOT | NPC_TYPEFLAG_MININGLOOT | NPC_TYPEFLAG_ENGINEERLOOT);
    foreach ($skinLoot as $roi => $l) {
        if ($roi < 0 && !empty($refLoot[-$roi])) {
            foreach ($refLoot[-$roi] as $iId => $r) {
                if ($_ = taughtSpell($r)) {
                    pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
                }
                pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
            }
            continue;
        }
        if ($_ = taughtSpell($l)) {
            pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
        }
        pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']);
    }
    if ($itemBuff) {
        DB::Aowow()->query(queryfy('[V]', $itemBuff, $insMore), 23, 23, 23);
    }
    if ($spellBuff) {
        DB::Aowow()->query(queryfy('[V]', $spellBuff, $insMore), 23, 23, 23);
    }
    /*********/
    /* Spell */
    /*********/
    CLISetup::log(' - Spells [original]');
    #  4: Quest
    CLISetup::log('   * #4  Quest');
    $quests = DB::World()->select('
        SELECT spell AS ARRAY_KEY, id, SUM(qty) AS qty, BIT_OR(side) AS side FROM (
            SELECT IF(rewardSpellCast = 0, rewardSpell, rewardSpellCast) AS spell, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE IF(rewardSpellCast = 0, rewardSpell, rewardSpellCast) > 0 GROUP BY spell
            UNION
            SELECT SourceSpellId AS spell, ID, COUNT(1) AS qty, IF(RequiredRaces & 0x2B2 AND !(RequiredRaces & 0x44D), 2, IF(RequiredRaces & 0x44D AND !(RequiredRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE SourceSpellId > 0 GROUP BY spell
        ) t GROUP BY spell');
    if ($quests) {
        $qSpells = DB::Aowow()->select('SELECT id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE id IN (?a) AND (effect1Id = 36 OR effect2Id = 36 OR effect3Id = 36)', array_keys($quests));
        $buff = [];
        foreach ($qSpells as $sId => $spell) {
            for ($i = 1; $i <= 3; $i++) {
                if ($spell['effect' . $i . 'Id'] != 36) {
                    // effect: learnSpell
                    continue;
                }
                pushBuffer($buff, TYPE_SPELL, $spell['effect' . $i . 'TriggerSpell'], $quests[$sId]['qty'] > 1 ? 0 : TYPE_QUEST, $quests[$sId]['qty'] > 1 ? 0 : $quests[$sId]['id'], $quests[$sId]['side']);
            }
        }
        DB::Aowow()->query(queryfy('[V]', $buff, $insMore), 4, 4, 4);
    }
    #  6: Trainer
    CLISetup::log('   * #6  Trainer');
    if ($tNpcs = DB::World()->select('SELECT SpellID AS ARRAY_KEY, ID AS entry, COUNT(1) AS qty FROM npc_trainer WHERE SpellID > 0 GROUP BY ARRAY_KEY')) {
        $tSpells = DB::Aowow()->select('SELECT Id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE Id IN (?a)', array_keys($tNpcs));
        $buff = [];
        // todo (med): this skips some spells (e.g. riding)
        foreach ($tNpcs as $spellId => $npc) {
            if (!isset($tSpells[$spellId])) {
                continue;
            }
            $effects = $tSpells[$spellId];
            $trainerId = $npc['entry'] > 200000 || $npc['qty'] > 1 ? null : $npc['entry'];
            $triggered = false;
            for ($i = 1; $i <= 3; $i++) {
                if ($effects['effect' . $i . 'Id'] != 36) {
                    // effect: learnSpell
                    continue;
                }
                $triggered = true;
                pushBuffer($buff, TYPE_SPELL, $effects['effect' . $i . 'TriggerSpell'], $trainerId ? TYPE_NPC : 0, $trainerId);
            }
            if (!$triggered) {
                pushBuffer($buff, TYPE_SPELL, $spellId, $trainerId ? TYPE_NPC : 0, $trainerId);
            }
        }
        DB::Aowow()->query(queryfy('[V]', $buff, $insMore), 6, 6, 6);
    }
    #  7: Discovery
    CLISetup::log('   * #7  Discovery');
    // 61756: Northrend Inscription Research (FAST QA VERSION);
    if ($disco = DB::World()->select('SELECT ?d, spellId, 1 FROM skill_discovery_template WHERE reqSpell <> ?d', TYPE_SPELL, 61756)) {
        DB::Aowow()->query(queryfy('[V]', $disco, $insBasic), 7, 7, 7);
    }
    #  9: Talent
    CLISetup::log('   * #9  Talent');
    $tSpells = DB::Aowow()->select('
        SELECT s.Id AS ARRAY_KEY, s.effect1Id, s.effect2Id, s.effect3Id, s.effect1TriggerSpell, s.effect2TriggerSpell, s.effect3TriggerSpell
        FROM   dbc_talent t
        JOIN   dbc_spell s ON s.Id = t.rank1
        WHERE  t.rank2 < 1 AND (t.talentSpell = 1 OR (s.effect1Id = 36 OR s.effect2Id = 36 OR s.effect3Id = 36))
    ');
    $n = 0;
    $buff = [];
    while ($tSpells) {
        CLISetup::log('     - ' . ++$n . '. pass');
        $recurse = [];
        foreach ($tSpells as $tId => $spell) {
            for ($i = 1; $i <= 3; $i++) {
                if ($spell['effect' . $i . 'Id'] == 36) {
                    // effect: learnSpell
                    $recurse[$spell['effect' . $i . 'TriggerSpell']] = $tId;
                }
            }
            if (array_search($tId, $recurse)) {
                unset($tSpells[$tId]);
            }
        }
        foreach ($tSpells as $tId => $__) {
            $buff[$tId] = [TYPE_SPELL, $tId, 1];
        }
        if (!$recurse) {
            break;
        }
        $tSpells = DB::Aowow()->select('SELECT Id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE Id IN (?a)', array_keys($recurse));
    }
    DB::Aowow()->query(queryfy('[V]', $buff, $insBasic), 9, 9, 9);
    # 10: Starter
    CLISetup::log('   * #10 Starter');
    /* acquireMethod
           ABILITY_LEARNED_ON_GET_PROFESSION_SKILL     = 1,        learnedAt = 1 && source10 = 1
           ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL  = 2         not used for now
       */
    $subSkills = DB::Aowow()->subquery('SELECT ?d, spellId, 1, NULL AS m, NULL AS mt FROM dbc_skilllineability WHERE acquireMethod = 1 AND (reqSkillLevel = 1 OR skillLineId = 129) GROUP BY spellId', TYPE_SPELL);
    DB::Aowow()->query($insSub, 10, $subSkills, 10, 10);
    if ($pcis = DB::World()->select('SELECT ?d, Spell, 1 FROM playercreateinfo_spell', TYPE_SPELL)) {
        DB::Aowow()->query(queryfy('[V]', $pcis, $insBasic), 10, 10, 10);
    }
    /**********/
    /* Titles */
    /**********/
    CLISetup::log(' - Titles');
    #  4: Quest
    CLISetup::log('   * #4  Quest');
    if ($quests = DB::World()->select('SELECT ?d, RewardTitle, 1, ?d, ID FROM quest_template WHERE RewardTitle > 0', TYPE_TITLE, TYPE_QUEST)) {
        DB::Aowow()->query(queryfy('[V]', $quests, $insMore), 4, 4, 4);
    }
    # 12: Achievement
    CLISetup::log('   * #12 Achievement');
    $sets = DB::World()->select('
        SELECT ?d, IF (title_A <> 0, title_A, title_H) AS title, 1, ?d, entry FROM achievement_reward WHERE title_A <> 0 OR title_H <> 0 GROUP BY title
        UNION
        SELECT ?d, title_H AS title, 1, ?d, entry FROM achievement_reward WHERE title_A <> title_H AND title_A <> 0 AND title_H <> 0', TYPE_TITLE, TYPE_ACHIEVEMENT, TYPE_TITLE, TYPE_ACHIEVEMENT);
    if ($sets) {
        DB::Aowow()->query(queryfy('[V]', $sets, $insMore), 12, 12, 12);
    }
    # 13: Source-String
    CLISetup::log('   * #13 cuStrings');
    $src13 = [null, 42, 52, 71, 80, 157, 163, 167, 169, 177];
    foreach ($src13 as $src => $tId) {
        if ($tId) {
            DB::Aowow()->query(queryfy('[V]', [[TYPE_TITLE, $tId, $src]], $insBasic), 13, 13, 13);
        }
    }
    return true;
}
Пример #28
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;
}
Пример #29
0
function spawns()
{
    $alphaMapCache = [];
    $alphaMapCheck = function ($areaId, array &$set) use(&$alphaMapCache) {
        $file = 'setup/generated/alphaMaps/' . $areaId . '.png';
        if (!file_exists($file)) {
            // file does not exist (probably instanced area)
            return false;
        }
        // invalid and corner cases (literally)
        if (!is_array($set) || empty($set['posX']) || empty($set['posY']) || $set['posX'] >= 100 || $set['posY'] >= 100) {
            $set = null;
            return true;
        }
        if (empty($alphaMapCache[$areaId])) {
            $alphaMapCache[$areaId] = imagecreatefrompng($file);
        }
        // alphaMaps are 1000 x 1000, adapt points [black => valid point]
        if (!imagecolorat($alphaMapCache[$areaId], $set['posX'] * 10, $set['posY'] * 10)) {
            $set = null;
        }
        return true;
    };
    $checkCoords = function ($points) use($alphaMapCheck) {
        $result = [];
        $capitals = array(1497, 1637, 1638, 3487, 1519, 1537, 1657, 3557, 3703, 4395);
        foreach ($points as $res) {
            if ($alphaMapCheck($res['areaId'], $res)) {
                if (!$res) {
                    continue;
                }
                // some rough measure how central the spawn is on the map (the lower the number, the better)
                // 0: perfect center; 1: touches a border
                $q = abs(($res['posX'] - 50) / 50 * (($res['posY'] - 50) / 50));
                if (empty($result) || $result[0] > $q) {
                    $result = [$q, $res];
                }
            } else {
                if (in_array($res['areaId'], $capitals)) {
                    // capitals (auto-discovered) and no hand-made alphaMap available
                    return $res;
                } else {
                    if (empty($result)) {
                        // add with lowest quality if alpha map is missing
                        $result = [1.0, $res];
                    }
                }
            }
        }
        // spawn does not really match on a map, but we need at least one result
        if (!$result) {
            usort($points, function ($a, $b) {
                return $a['quality'] < $b['quality'] ? -1 : 1;
            });
            $result = [1.0, $points[0]];
        }
        return $result[1];
    };
    $query[1] = ['SELECT c.guid, 1 AS "type", c.id AS typeId, c.spawntimesecs AS respawn, c.phaseMask, c.zoneId AS areaId, c.map, IFNULL(ca.path_id, 0) AS pathId, c.position_y AS `posX`, c.position_x AS `posY` ' . 'FROM creature c LEFT JOIN creature_addon ca ON ca.guid = c.guid', ' - assembling ' . CLISetup::bold('creature') . ' spawns'];
    $query[2] = ['SELECT c.guid, 2 AS "type", c.id AS typeId, ABS(c.spawntimesecs) AS respawn, c.phaseMask, c.zoneId AS areaId, c.map, 0 as pathId, c.position_y AS `posX`, c.position_x AS `posY` ' . 'FROM gameobject c', ' - assembling ' . CLISetup::bold('gameobject') . ' spawns'];
    $query[3] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, w.waittime AS "wait", w.location_y AS `posX`, w.location_x AS `posY` ' . 'FROM creature c JOIN script_waypoint w ON c.id = w.entry', ' - assembling waypoints from ' . CLISetup::bold('script_waypoint')];
    $query[4] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, 0 AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' . 'FROM creature c JOIN waypoints w ON c.id = w.entry', ' - assembling waypoints from ' . CLISetup::bold('waypoints')];
    $query[5] = ['SELECT c.guid, -w.id AS "npcOrPath", w.point, c.zoneId AS areaId, c.map, w.delay AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' . 'FROM creature c JOIN creature_addon ca ON ca.guid = c.guid JOIN waypoint_data w ON w.id = ca.path_id', ' - assembling waypoints from ' . CLISetup::bold('waypoint_data')];
    $queryPost = 'SELECT dm.Id, wma.areaId, IFNULL(dm.floor, 0) AS floor, ' . '100 - ROUND(IF(dm.Id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right)  * 100 / (wma.left - wma.right)), 1) AS `posX`, ' . '100 - ROUND(IF(dm.Id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)), 1) AS `posY`, ' . '((abs(IF(dm.Id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right)  * 100 / (wma.left - wma.right)) - 50) / 50) * ' . ' (abs(IF(dm.Id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)) - 50) / 50)) AS quality ' . 'FROM dbc_worldmaparea wma ' . 'LEFT JOIN dbc_dungeonmap dm ON dm.mapId = IF(?d AND wma.mapId NOT IN (0, 1, 530), wma.mapId, -1) ' . 'WHERE wma.mapId = ?d AND IF(?d, wma.areaId = ?d, wma.areaId <> 0) ' . 'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) AND (dm.Id IS NULL OR ?d) ' . 'ORDER BY quality ASC';
    /*********************/
    /* truncate old data */
    /*********************/
    DB::Aowow()->query('TRUNCATE TABLE ?_spawns');
    DB::Aowow()->query('TRUNCATE TABLE ?_creature_waypoints');
    /**************************/
    /* offsets for transports */
    /**************************/
    $transports = DB::World()->selectCol('SELECT Data0 AS pathId, Data6 AS ARRAY_KEY FROM gameobject_template WHERE type = 15 AND Data6 <> 0');
    foreach ($transports as &$t) {
        $t = DB::Aowow()->selectRow('SELECT posX, posY, mapId FROM dbc_taxipathnode tpn WHERE tpn.pathId = ?d AND nodeIdx = 0', $t);
    }
    /**************/
    /* perform... */
    /**************/
    foreach ($query as $idx => $q) {
        CLISetup::log($q[1]);
        $n = 0;
        $sum = 0;
        foreach (DB::World()->select($q[0]) as $spawn) {
            if (!$n) {
                CLISetup::log(' * sets ' . ($sum + 1) . ' - ' . ($sum += SqlGen::$stepSize));
            }
            if ($n++ > SqlGen::$stepSize) {
                $n = 0;
            }
            // npc/object is on a transport -> apply offsets to path of transport
            // note, that the coordinates are mixed up .. again
            // also note, that transport DO spawn outside of displayable area maps .. another todo i guess..
            if (isset($transports[$spawn['map']])) {
                $spawn['posX'] += $transports[$spawn['map']]['posY'];
                $spawn['posY'] += $transports[$spawn['map']]['posX'];
                $spawn['map'] = $transports[$spawn['map']]['mapId'];
            }
            $points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 1, $spawn['map'], $spawn['areaId'], $spawn['areaId'], $spawn['areaId'] ? 1 : 0);
            if (!$points) {
                // retry: TC counts pre-instance subareas as instance-maps .. which have no map file
                $points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 0, $spawn['map'], 0, 0, 1);
            }
            if (!$points) {
                CLISetup::log('GUID ' . $spawn['guid'] . ($idx < 3 ? '' : ' on path/point ' . $spawn['npcOrPath'] . '/' . $spawn['point']) . ' could not be matched to displayable area [A:' . $spawn['areaId'] . '; X:' . $spawn['posY'] . '; Y:' . $spawn['posX'] . ']', CLISetup::LOG_WARN);
                continue;
            }
            // if areaId is set, area was determined by TC .. we're fine .. mostly
            $final = $spawn['areaId'] ? $points[0] : $checkCoords($points);
            if ($idx < 3) {
                $set = array('guid' => $spawn['guid'], 'type' => $spawn['type'], 'typeId' => $spawn['typeId'], 'respawn' => $spawn['respawn'], 'phaseMask' => $spawn['phaseMask'], 'pathId' => $spawn['pathId'], 'areaId' => $final['areaId'], 'floor' => $final['floor'], 'posX' => $final['posX'], 'posY' => $final['posY']);
                DB::Aowow()->query('REPLACE INTO ?_spawns (?#) VALUES (?a)', array_keys($set), array_values($set));
            } else {
                $set = array('creatureOrPath' => $spawn['npcOrPath'], 'point' => $spawn['point'], 'wait' => $spawn['wait'], 'areaId' => $final['areaId'], 'floor' => $final['floor'], 'posX' => $final['posX'], 'posY' => $final['posY']);
                DB::Aowow()->query('REPLACE INTO ?_creature_waypoints (?#) VALUES (?a)', array_keys($set), array_values($set));
            }
        }
    }
    /*****************************/
    /* spawn vehicle accessories */
    /*****************************/
    // get vehicle template accessories
    $accessories = DB::World()->select('
        SELECT vta.accessory_entry AS typeId,  c.guid,  vta.entry, count(1) AS nSeats FROM vehicle_template_accessory vta LEFT JOIN creature c ON c.id = vta.entry GROUP BY accessory_entry,  c.guid UNION
        SELECT  va.accessory_entry AS typeId, va.guid, 0 AS entry, count(1) AS nSeats FROM vehicle_accessory           va                                          GROUP BY accessory_entry, va.guid');
    // accessories may also be vehicles (e.g. "Kor'kron Infiltrator" is seated on "Kor'kron Suppression Turret" is seated on "Kor'kron Troop Transport")
    // so we will retry finding a spawned vehicle if none were found on the previous pass and a change occured
    $vGuid = 0;
    // not really used, but we need some kind of index
    $n = 0;
    $matches = -1;
    while ($matches) {
        $matches = 0;
        foreach ($accessories as $idx => $data) {
            $vehicles = [];
            if ($data['guid']) {
                // vehicle already spawned
                $vehicles = DB::Aowow()->select('SELECT s.areaId, s.posX, s.posY, s.floor FROM ?_spawns s WHERE s.guid   = ?d AND s.type = ?d', $data['guid'], TYPE_NPC);
            } else {
                if ($data['entry']) {
                    // vehicle on unspawned vehicle action
                    $vehicles = DB::Aowow()->select('SELECT s.areaId, s.posX, s.posY, s.floor FROM ?_spawns s WHERE s.typeId = ?d AND s.type = ?d', $data['entry'], TYPE_NPC);
                }
            }
            if ($vehicles) {
                $matches++;
                foreach ($vehicles as $v) {
                    // if there is more than one vehicle, its probably due to overlapping zones
                    for ($i = 0; $i < $data['nSeats']; $i++) {
                        DB::Aowow()->query('
                            REPLACE INTO ?_spawns (`guid`, `type`, `typeId`, `respawn`, `spawnMask`, `phaseMask`, `areaId`, `floor`, `posX`, `posY`, `pathId`) VALUES
                            (?d, ?d, ?d, 0, 0, 1, ?d, ?d, ?d, ?d, 0)', --$vGuid, TYPE_NPC, $data['typeId'], $v['areaId'], $v['floor'], $v['posX'], $v['posY']);
                    }
                }
                unset($accessories[$idx]);
            }
        }
        if ($matches) {
            CLISetup::log(' * assigned ' . $matches . ' accessories on ' . ++$n . '. pass on vehicle accessories');
        }
    }
    if ($accessories) {
        CLISetup::log(count($accessories) . ' accessories could not be fitted onto a spawned vehicle.', CLISetup::LOG_WARN);
    }
    /********************************/
    /* restrict difficulty displays */
    /********************************/
    DB::Aowow()->query('UPDATE ?_spawns s, dbc_worldmaparea wma, dbc_map m SET s.spawnMask = 0 WHERE s.areaId = wma.areaId AND wma.mapId = m.Id AND m.areaType IN (0, 3, 4)');
    return true;
}
Пример #30
0
function itemset()
{
    $locales = [LOCALE_EN, LOCALE_FR, LOCALE_DE, LOCALE_ES, LOCALE_RU];
    $setToHoliday = array(761 => 141, 762 => 372, 785 => 341, 812 => 181);
    // find events associated with holidayIds
    if ($pairs = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($setToHoliday))) {
        foreach ($setToHoliday as &$hId) {
            $hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0;
        }
    }
    // tags where refId == virtualId
    // in pve sets are not recycled beyond the contentGroup
    $tagsById = array(1 => [181, 182, 183, 184, 185, 186, 187, 188, 189], 2 => [511, 512, 513, 514, 515, 516, 517, 518, 519], 3 => [201, 202, 203, 204, 205, 206, 207, 208, 209], 4 => [210, 211, 212, 213, 214, 215, 216, 217, 218], 5 => [521, 523, 524, 525, 526, 527, 528, 529, 530], 6 => [522, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 697, 718], 7 => [281, 282, 301, 341, 342, 343, 344, 345, 346, 347, 348, 361, 362, 381, 382, 401], 8 => [383, 384, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 402, 717, 698], 9 => [494, 495, 498, 500, 502, 504, 506, 508, 510], 10 => [493, 496, 497, 499, 501, 503, 505, 507, 509], 11 => [477, 480, 474, 475, 476, 478, 479, 481, 482], 12 => [621, 624, 625, 626, 631, 632, 633, 638, 639, 640, 645, 648, 651, 654, 655, 663, 664], 13 => [622, 627, 628, 629, 634, 635, 636, 641, 642, 643, 646, 649, 652, 656, 657, 665, 666], 14 => [620, 623, 630, 637, 644, 647, 650, 653, 658, 659, 660, 661, 662], 15 => [467, 468, 469, 470, 471, 472, 473, 483, 484, 485, 486, 487, 488, 908], 16 => [587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 688, 689, 691, 692, 693, 694, 695, 696], 18 => [668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684], 21 => [738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752], 23 => [795, 805, 804, 803, 802, 801, 800, 799, 798, 797, 796, 794, 793, 792, 791, 790, 789, 788, 787], 25 => [838, 837, 836, 835, 834, 833, 832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820], 27 => [880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844, 843], 29 => [901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883]);
    // well .. f**k
    $tagsByNamePart = array(17 => ['gladiator'], 19 => ['merciless'], 20 => ['vengeful'], 22 => ['brutal'], 24 => ['deadly', 'hateful', 'savage'], 26 => ['furious'], 28 => ['relentless'], 30 => ['wrathful']);
    DB::Aowow()->query('TRUNCATE TABLE ?_itemset');
    $vIdx = 0;
    $virtualId = 0;
    $sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset');
    foreach ($sets as $setId => $setData) {
        $spells = $items = $mods = $descText = $name = $gains = [];
        $max = $reqLvl = $min = $quality = $heroic = $nPieces = [];
        $classMask = $type = 0;
        $hasRing = false;
        $holiday = isset($setToHoliday[$setId]) ? $setToHoliday[$setId] : 0;
        $canReuse = !$holiday;
        // can't reuse holiday-sets
        $slotList = [];
        $pieces = DB::World()->select('SELECT *, IF(InventoryType = 15, 26, IF(InventoryType = 5, 20, InventoryType)) AS slot, entry AS ARRAY_KEY FROM item_template WHERE itemset = ?d AND (class <> 4 OR subclass NOT IN (1, 2, 3, 4) OR armor > 0 OR Quality = 1) ORDER BY itemLevel, subclass, slot ASC', $setId);
        /****************************************/
        /* determine type and reuse from pieces */
        /****************************************/
        // make the first vId always same as setId
        $firstPiece = reset($pieces);
        $tmp = [$firstPiece['Quality'] . $firstPiece['ItemLevel'] => $setId];
        // walk through all items associated with the set
        foreach ($pieces as $itemId => $piece) {
            $classMask |= $piece['AllowableClass'] & CLASS_MASK_ALL;
            $key = $piece['Quality'] . str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT);
            if (!isset($tmp[$key])) {
                $tmp[$key] = --$vIdx;
            }
            $vId = $tmp[$key];
            // check only actual armor in rare quality or higher (or inherits holiday)
            if ($piece['class'] != ITEM_CLASS_ARMOR || $piece['subclass'] == 0) {
                $canReuse = false;
            }
            /* gather relevant stats for use */
            if (!isset($quality[$vId]) || $piece['Quality'] > $quality[$vId]) {
                $quality[$vId] = $piece['Quality'];
            }
            if ($piece['Flags'] & ITEM_FLAG_HEROIC) {
                $heroic[$vId] = true;
            }
            if (!isset($reqLvl[$vId]) || $piece['RequiredLevel'] > $reqLvl[$vId]) {
                $reqLvl[$vId] = $piece['RequiredLevel'];
            }
            if (!isset($min[$vId]) || $piece['ItemLevel'] < $min[$vId]) {
                $min[$vId] = $piece['ItemLevel'];
            }
            if (!isset($max[$vId]) || $piece['ItemLevel'] > $max[$vId]) {
                $max[$vId] = $piece['ItemLevel'];
            }
            if (!isset($items[$vId][$piece['slot']]) || !$canReuse) {
                if (!isset($nPieces[$vId])) {
                    $nPieces[$vId] = 1;
                } else {
                    $nPieces[$vId]++;
                }
            }
            if (isset($items[$vId][$piece['slot']])) {
                // not reusable -> insert anyway on unique keys
                if (!$canReuse) {
                    $items[$vId][$piece['slot'] . $itemId] = $itemId;
                } else {
                    CLISetup::log("set: " . $setId . " ilvl: " . $piece['ItemLevel'] . " - conflict between item: " . $items[$vId][$piece['slot']] . " and item: " . $itemId . " choosing lower itemId", CLISetup::LOG_WARN);
                    if ($items[$vId][$piece['slot']] > $itemId) {
                        $items[$vId][$piece['slot']] = $itemId;
                    }
                }
            } else {
                $items[$vId][$piece['slot']] = $itemId;
            }
            /* check for type */
            // skip cloaks, they mess with armor classes
            if ($piece['slot'] == 16) {
                continue;
            }
            // skip event-sets
            if ($piece['Quality'] == 1) {
                continue;
            }
            if ($piece['class'] == 2 && $piece['subclass'] == 0) {
                $type = 8;
            } else {
                if ($piece['class'] == 2 && $piece['subclass'] == 4) {
                    $type = 9;
                } else {
                    if ($piece['class'] == 2 && $piece['subclass'] == 7) {
                        $type = 10;
                    } else {
                        if ($piece['class'] == 2 && $piece['subclass'] == 13) {
                            $type = 7;
                        } else {
                            if ($piece['class'] == 2 && $piece['subclass'] == 15) {
                                $type = 5;
                            }
                        }
                    }
                }
            }
            // Dagger
            if (!$type) {
                if ($piece['class'] == 4 && $piece['slot'] == 12) {
                    $type = 11;
                } else {
                    if ($piece['class'] == 4 && $piece['slot'] == 2) {
                        $type = 12;
                    } else {
                        if ($piece['class'] == 4 && $piece['subclass'] != 0) {
                            $type = $piece['subclass'];
                        }
                    }
                }
                // 'armor' set
                if ($piece['class'] == 4 && $piece['slot'] == 11) {
                    $hasRing = true;
                }
                // contains ring
            }
        }
        if ($hasRing && !$type) {
            $type = 6;
        }
        // pure ring-set
        $isMultiSet = false;
        $oldSlotMask = 0x0;
        foreach ($items as $subset) {
            $curSlotMask = 0x0;
            foreach ($subset as $slot => $item) {
                $curSlotMask |= 1 << $slot;
            }
            if ($oldSlotMask && $oldSlotMask == $curSlotMask) {
                $isMultiSet = true;
                break;
            }
            $oldSlotMask = $curSlotMask;
        }
        if (!$isMultiSet || !$canReuse || $setId == 555) {
            $temp = [];
            foreach ($items as $subset) {
                foreach ($subset as $slot => $item) {
                    if (isset($temp[$slot]) && $temp[$slot] < $item) {
                        CLISetup::log("set: " . $setId . " - conflict between item: " . $item . " and item: " . $temp[$slot] . " choosing lower itemId", CLISetup::LOG_WARN);
                    } else {
                        if ($slot == 13 || ($slot = 11)) {
                            // special case
                            $temp[] = $item;
                        } else {
                            $temp[$slot] = $item;
                        }
                    }
                }
            }
            $items = [$temp];
            $heroic = [reset($heroic)];
            $nPieces = [count($temp)];
            $quality = [reset($quality)];
            $reqLvl = [reset($reqLvl)];
            $max = $max ? [max($max)] : [0];
            $min = $min ? [min($min)] : [0];
        }
        foreach ($items as &$subsets) {
            $subsets = array_pad($subsets, 10, 0);
        }
        /********************/
        /* calc statbonuses */
        /********************/
        for ($i = 1; $i < 9; $i++) {
            if ($setData['spellId' . $i] > 0 && $setData['itemCount' . $i] > 0) {
                $spells[] = [$setData['spellId' . $i], $setData['itemCount' . $i]];
            }
        }
        $bonusSpells = new SpellList(array(['s.id', array_column($spells, 0)]));
        $mods = $bonusSpells->getStatGain();
        $spells = array_pad($spells, 8, [0, 0]);
        for ($i = 1; $i < 9; $i++) {
            if ($setData['itemCount' . $i] > 0 && !empty($mods[$setData['spellId' . $i]])) {
                $gains[$setData['itemCount' . $i]] = $mods[$setData['spellId' . $i]];
            }
        }
        /**************************/
        /* get name & description */
        /**************************/
        foreach ($locales as $loc) {
            User::useLocale($loc);
            $name[$loc] = Util::localizedString($setData, 'name');
            foreach ($bonusSpells->iterate() as $__) {
                if (!isset($descText[$loc])) {
                    $descText[$loc] = '';
                }
                $descText[$loc] .= $bonusSpells->parseText()[0] . "\n";
            }
            // strip rating blocks - e.g. <!--rtg19-->14&nbsp;<small>(<!--rtg%19-->0.30%&nbsp;@&nbsp;L<!--lvl-->80)</small>
            $descText[$loc] = preg_replace('/<!--rtg\\d+-->(\\d+)&nbsp.*?<\\/small>/i', '\\1', $descText[$loc]);
        }
        /****************************/
        /* finalaize data and write */
        /****************************/
        foreach ($items as $vId => $vSet) {
            $note = 0;
            foreach ($tagsById as $tag => $sets) {
                if (!in_array($setId, $sets)) {
                    continue;
                }
                $note = $tag;
            }
            if (!$note && $min > 120 && $classMask && $classMask != CLASS_MASK_ALL) {
                foreach ($tagsByNamePart as $tag => $strings) {
                    foreach ($strings as $str) {
                        if (isset($pieces[reset($vSet)]) && stripos($pieces[reset($vSet)]['name'], $str) === 0) {
                            $note = $tag;
                            break 2;
                        }
                    }
                }
            }
            $row = [];
            $row[] = $vId < 0 ? --$virtualId : $setId;
            $row[] = $setId;
            // refSetId
            $row[] = 0;
            // cuFlags
            $row = array_merge($row, $name, $vSet);
            foreach (array_column($spells, 0) as $spellId) {
                $row[] = $spellId;
            }
            foreach (array_column($spells, 1) as $nItems) {
                $row[] = $nItems;
            }
            $row = array_merge($row, $descText);
            $row[] = serialize($gains);
            $row[] = $nPieces[$vId];
            $row[] = $min[$vId];
            $row[] = $max[$vId];
            $row[] = $reqLvl[$vId];
            $row[] = $classMask == CLASS_MASK_ALL ? 0 : $classMask;
            $row[] = !empty($heroic[$vId]) ? 1 : 0;
            $row[] = $quality[$vId];
            $row[] = $type;
            $row[] = $note;
            // contentGroup
            $row[] = $holiday;
            $row[] = $setData['reqSkillId'];
            $row[] = $setData['reqSkillLevel'];
            DB::Aowow()->query('REPLACE INTO ?_itemset VALUES (?a)', array_values($row));
        }
    }
    // hide empty sets
    DB::Aowow()->query('UPDATE ?_itemset SET cuFlags = cuFlags | ?d WHERE item1 = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW);
    return true;
}