Exemplo n.º 1
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;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
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);
}
Exemplo n.º 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);
    }
}
Exemplo n.º 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");
}
Exemplo 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);
}
Exemplo n.º 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;
}
Exemplo n.º 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);
}
Exemplo n.º 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");
}
Exemplo 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];
}
Exemplo n.º 11
0
function glyphs()
{
    $success = true;
    $glyphList = DB::Aowow()->Select('SELECT i.id AS itemId,
                   i.*,
                   IF (g.typeFlags & 0x1, 2, 1) AS type,
                   i.subclass AS classs,
                   i.requiredLevel AS level,
                   s1.Id AS glyphSpell,
                   ic.iconString AS icon,
                   s1.skillLine1 AS skillId,
                   s2.Id AS glyphEffect,
                   s2.Id AS ARRAY_KEY
            FROM   ?_items i
            JOIN   ?_spell s1 ON s1.Id = i.spellid1
            JOIN   ?_glyphproperties g ON g.Id = s1.effect1MiscValue
            JOIN   ?_spell s2 ON s2.Id = g.spellId
            JOIN   ?_icons ic ON ic.Id = s1.iconIdAlt
            WHERE  i.classBak = 16');
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE));
    foreach (CLISetup::$localeIds as $lId) {
        set_time_limit(30);
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $glyphsOut = [];
        foreach ($glyphSpells->iterate() as $__) {
            $pop = $glyphList[$glyphSpells->id];
            if (!$pop['glyphEffect']) {
                continue;
            }
            if ($glyphSpells->getField('effect1Id') != 6 && $glyphSpells->getField('effect2Id') != 6 && $glyphSpells->getField('effect3Id') != 6) {
                continue;
            }
            $glyphsOut[$pop['itemId']] = array('name' => Util::localizedString($pop, 'name'), 'description' => $glyphSpells->parseText()[0], 'icon' => $pop['icon'], 'type' => $pop['type'], 'classs' => $pop['classs'], 'skill' => $pop['skillId'], 'level' => $pop['level']);
        }
        $toFile = "var g_glyphs = " . Util::toJSON($glyphsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/glyphs';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
Exemplo n.º 12
0
function pets()
{
    $success = true;
    $locations = [];
    $petList = DB::Aowow()->Select('SELECT    cr. id,
                      cr.name_loc0, cr.name_loc2, cr.name_loc3, cr.name_loc6, cr.name_loc8,
                      cr.minLevel,
                      cr.maxLevel,
                      ft.A,
                      ft.H,
                      cr.rank AS classification,
                      cr.family,
                      cr.displayId1 AS displayId,
                      cr.textureString AS skin,
                      LOWER(SUBSTRING_INDEX(cf.iconString, "\\\\", -1)) AS icon,
                      cf.petTalentType AS type
            FROM      ?_creature cr
            JOIN      ?_factiontemplate  ft ON ft.Id = cr.faction
            JOIN      dbc_creaturefamily cf ON cf.id = cr.family
            WHERE     cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0
            ORDER BY  cr.id ASC');
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    foreach (CLISetup::$localeIds as $lId) {
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $petsOut = [];
        foreach ($petList as $pet) {
            // get locations
            // again: caching will save you time and nerves
            if (!isset($locations[$pet['id']])) {
                $locations[$pet['id']] = DB::Aowow()->SelectCol('SELECT DISTINCT areaId FROM ?_spawns WHERE type = ?d AND typeId = ?d', TYPE_NPC, $pet['id']);
            }
            $petsOut[$pet['id']] = array('id' => $pet['id'], 'name' => Util::localizedString($pet, 'name'), 'minlevel' => $pet['minLevel'], 'maxlevel' => $pet['maxLevel'], 'location' => $locations[$pet['id']], 'react' => [$pet['A'], $pet['H']], 'classification' => $pet['classification'], 'family' => $pet['family'], 'displayId' => $pet['displayId'], 'skin' => $pet['skin'], 'icon' => $pet['icon'], 'type' => $pet['type']);
        }
        $toFile = "var g_pets = " . Util::toJSON($petsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/pets';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
Exemplo n.º 13
0
function gems()
{
    // sketchy, but should work
    // Id < 36'000 || ilevel < 70 ? BC : WOTLK
    $gems = DB::Aowow()->Select('SELECT    i.id AS itemId,
                      i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc6, i.name_loc8,
                      IF (i.id < 36000 OR i.itemLevel < 70, 1 , 2) AS expansion,
                      i.quality,
                      ic.iconString AS icon,
                      i.gemEnchantmentId AS enchId,
                      i.gemColorMask AS colors
            FROM      ?_items i
            JOIN      ?_icons ic ON ic.id = -i.displayId
            WHERE     i.gemEnchantmentId <> 0
            ORDER BY  i.id DESC');
    $success = true;
    // check directory-structure
    foreach (Util::$localeStrings as $dir) {
        if (!CLISetup::writeDir('datasets/' . $dir)) {
            $success = false;
        }
    }
    $enchIds = [];
    foreach ($gems as $pop) {
        $enchIds[] = $pop['enchId'];
    }
    $enchMisc = [];
    $enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
    foreach (CLISetup::$localeIds as $lId) {
        set_time_limit(5);
        User::useLocale($lId);
        Lang::load(Util::$localeStrings[$lId]);
        $gemsOut = [];
        foreach ($gems as $pop) {
            $gemsOut[$pop['itemId']] = array('name' => Util::localizedString($pop, 'name'), 'quality' => $pop['quality'], 'icon' => strToLower($pop['icon']), 'enchantment' => Util::localizedString(@$enchMisc[$pop['enchId']]['text'] ?: [], 'text'), 'jsonequip' => @$enchJSON[$pop['enchId']] ?: [], 'colors' => $pop['colors'], 'expansion' => $pop['expansion']);
        }
        $toFile = "var g_gems = " . Util::toJSON($gemsOut) . ";";
        $file = 'datasets/' . User::$localeString . '/gems';
        if (!CLISetup::writeFile($file, $toFile)) {
            $success = false;
        }
    }
    return $success;
}
Exemplo n.º 14
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);
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
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);
    }
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
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;
}
Exemplo n.º 21
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);
}
Exemplo n.º 22
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;
}
Exemplo n.º 23
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);
         }
     }
 }
Exemplo n.º 24
0
 public static function log($txt = '', $lvl = -1)
 {
     if (self::$logFile && !self::$logHandle) {
         if (!file_exists(self::$logFile)) {
             self::$logHandle = fopen(self::$logFile, 'w');
         } else {
             $logFileParts = pathinfo(self::$logFile);
             $i = 1;
             while (file_exists($logFileParts['dirname'] . '/' . $logFileParts['filename'] . $i . (isset($logFileParts['extension']) ? '.' . $logFileParts['extension'] : ''))) {
                 $i++;
             }
             self::$logFile = $logFileParts['dirname'] . '/' . $logFileParts['filename'] . $i . (isset($logFileParts['extension']) ? '.' . $logFileParts['extension'] : '');
             self::$logHandle = fopen(self::$logFile, 'w');
         }
     }
     $msg = "\n";
     if ($txt) {
         $msg = str_pad(date('H:i:s'), 10);
         switch ($lvl) {
             case self::LOG_ERROR:
                 // red      critical error
                 $msg .= '[' . self::red('ERR') . ']   ';
                 break;
             case self::LOG_WARN:
                 // yellow   notice
                 $msg .= '[' . self::yellow('WARN') . ']  ';
                 break;
             case self::LOG_OK:
                 // green    success
                 $msg .= '[' . self::green('OK') . ']    ';
                 break;
             case self::LOG_INFO:
                 // blue     info
                 $msg .= '[' . self::blue('INFO') . ']  ';
                 break;
             default:
                 $msg .= '        ';
         }
         $msg .= $txt . "\n";
     }
     echo $msg;
     if (self::$logHandle) {
         // remove highlights for logging
         fwrite(self::$logHandle, preg_replace(["/\\[\\d+m/", "/\\[0m/"], '', $msg));
     }
     flush();
 }
Exemplo n.º 25
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;
            }
        }
    }
}
Exemplo n.º 26
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;
 }
Exemplo n.º 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;
}
Exemplo n.º 28
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;
}
Exemplo n.º 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;
}
Exemplo n.º 30
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;
        }
    }
}