diff --git a/setup/setup.php b/setup/setup.php index 21fc3182..5873145d 100644 --- a/setup/setup.php +++ b/setup/setup.php @@ -17,6 +17,7 @@ define('ERR_MISSING_INCL', 'required function %s() could not be found at %s'); require_once 'setup/tools/CLISetup.class.php'; +require_once 'setup/tools/setupScript.class.php'; require_once 'setup/tools/dbc.class.php'; require_once 'setup/tools/imagecreatefromblp.func.php'; diff --git a/setup/tools/setupScript.class.php b/setup/tools/setupScript.class.php new file mode 100644 index 00000000..11543208 --- /dev/null +++ b/setup/tools/setupScript.class.php @@ -0,0 +1,76 @@ +dbcSourceFiles) + { + CLI::write(' SetupScript '.$this->command.' is set up for DBCcopy but has no source set!', CLI::LOG_ERROR); + return false; + } + else if (count($this->dbcSourceFiles) != 1) + CLI::write(' SetupScript '.$this->command.' is set up for DBCcopy but has multiple sources set!', CLI::LOG_WARN); + + CLI::write('SqlGen::generate() - copying '.$this->dbcSourceFiles[0].'.dbc into aowow_'.$this->command); + + $dbc = new DBC($this->dbcSourceFiles[0], ['temporary' => false, 'tableName' => 'aowow_'.$this->command]); + if ($dbc->error) + return false; + + return !!$dbc->readFile(); + } +} + +trait TrCustomData +{ + // apply post generator custom data + public function applyCustomData() : void + { + if (!$this->customData) + return; + + foreach ($this->customData as $id => $data) + if ($data) + DB::Aowow()->query('UPDATE ?_'.$this->command.' SET ?a WHERE id = ?d', $data, $id); + } +} + +abstract class SetupScript +{ + protected $fileTemplatePath = ''; + protected $fileTemplateFile = ''; + + protected $tblDependancyAowow = []; + protected $tblDependancyTC = []; + + protected $dbcSourceFiles = []; + + // abstract protected $command; + + abstract public function generate() : bool; + + public function getRequiredDBCs() : array + { + return $this->dbcSourceFiles; + } + + public function getDependancies(bool $aowow) : array + { + return $aowow ? $this->tblDependancyAowow : $this->tblDependancyTC; + } + + public function getName() : string + { + return $this->command; + } +} + +?> \ No newline at end of file diff --git a/setup/tools/sqlGen.class.php b/setup/tools/sqlGen.class.php index ab7648f0..4b1dbef0 100644 --- a/setup/tools/sqlGen.class.php +++ b/setup/tools/sqlGen.class.php @@ -7,74 +7,14 @@ if (!CLI) die('not in cli mode'); -/* provide these with basic content - aowow_announcements - aowow_articles - aowow_config - aowow_home_featuredbox - aowow_home_featuredbox_overlay - aowow_home_oneliners - aowow_home_titles - aowow_sourcestrings -*/ - - class SqlGen { const MODE_NORMAL = 1; const MODE_FIRSTRUN = 2; const MODE_UPDATE = 3; - private static $tables = array( // [dbcName, saveDbc, AowowDeps, TCDeps] - 'achievementcategory' => ['achievement_category', false, null, null], - 'achievementcriteria' => ['achievement_criteria', false, null, null], - 'itemenchantmentcondition' => ['spellitemenchantmentcondition', false, null, null], - 'itemextendedcost' => ['itemextendedcost', false, null, null], - 'itemlimitcategory' => ['itemlimitcategory', false, null, null], - 'itemrandomproppoints' => ['randproppoints', false, null, null], - 'lock' => ['lock', true, null, null], - 'mailtemplate' => ['mailtemplate', false, null, null], - 'scalingstatdistribution' => ['scalingstatdistribution', true, null, null], - 'scalingstatvalues' => ['scalingstatvalues', true, null, null], - 'spellfocusobject' => ['spellfocusobject', false, null, null], - 'spelloverride' => ['overridespelldata', false, null, null], - 'spellrange' => ['spellrange', false, null, null], - 'spellvariables' => ['spelldescriptionvariables', false, null, null], - 'totemcategory' => ['totemcategory', false, null, null], - 'icons' => [null, null, null, null], - 'glyphproperties' => [null, true, ['icons'], null], - 'talents' => [null, null, null, null], - 'classes' => [null, null, null, null], - 'factions' => [null, null, null, null], - 'factiontemplate' => [null, null, null, null], - 'holidays' => [null, null, null, null], - 'itemrandomenchant' => [null, null, null, null], - 'races' => [null, null, null, null], - 'shapeshiftforms' => [null, null, null, null], - 'skillline' => [null, null, ['icons'], null], - 'emotes' => [null, null, null, null], - 'sounds' => [null, null, null, null], - 'areatrigger' => [null, null, null, ['areatrigger_involvedrelation', 'areatrigger_scripts', 'areatrigger_tavern', 'areatrigger_teleport', 'quest_template', 'quest_template_addon']], - 'itemenchantment' => [null, null, null, ['spell_enchant_proc_data']], - 'achievement' => [null, null, ['icons'], ['dbc_achievement', 'disables']], - 'creature' => [null, null, null, ['creature_template', 'creature_template_locale', 'creature_classlevelstats', 'instance_encounters']], - 'currencies' => [null, null, null, ['item_template', 'item_template_locale']], - 'events' => [null, null, null, ['game_event', 'game_event_prerequisite']], - 'objects' => [null, null, null, ['gameobject_template', 'gameobject_template_locale', 'gameobject_questitem']], - 'pet' => [null, null, ['icons'], ['creature_template', 'creature']], - 'quests' => [null, null, null, ['quest_template', 'quest_template_addon', 'quest_template_locale', 'game_event', 'game_event_seasonal_questrelation', 'disables']], - 'quests_startend' => [null, null, null, ['creature_queststarter', 'creature_questender', 'game_event_creature_quest', 'gameobject_queststarter', 'gameobject_questender', 'game_event_gameobject_quest', 'item_template']], - 'spell' => [null, null, ['icons'], ['skill_discovery_template', 'item_template', 'creature_template', 'creature_template_addon', 'smart_scripts', 'npc_trainer', 'disables', 'spell_ranks', 'spell_dbc']], - 'spelldifficulty' => [null, null, null, ['spelldifficulty_dbc']], - 'taxi' /* nodes + paths */ => [null, null, null, ['creature_template', 'creature']], - 'titles' => [null, null, null, ['quest_template', 'game_event_seasonal_questrelation', 'game_event', 'achievement_reward']], - 'items' => [null, null, ['icons'], ['item_template', 'item_template_locale', 'spell_group', 'game_event']], - 'spawns' /* + waypoints */ => [null, null, null, ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data']], - 'zones' => [null, null, null, ['access_requirement']], - 'itemset' => [null, null, ['spell'], ['item_template', 'game_event']], - 'item_stats' /* + ench */ => [null, null, ['items', 'spell'], null], - 'source' => [null, null, ['spell', 'achievement'], ['npc_vendor', 'game_event_npc_vendor', 'creature', 'quest_template', 'quest_template_addon', 'playercreateinfo_item', 'npc_trainer', 'skill_discovery_template', 'playercreateinfo_skills', 'achievement_reward', 'skill_perfect_item_template']] - ); + private static $tables = []; + private static $tmpStore = []; public static $cliOpts = []; private static $shortOpts = 'h'; @@ -84,13 +24,61 @@ class SqlGen public static $subScripts = []; public static $defaultExecTime = 30; - public static $stepSize = 1000; + public static $sqlBatchSize = 1000; - public static function init($mode = self::MODE_NORMAL, array $updScripts = []) + public static function init(int $mode = self::MODE_NORMAL, array $updScripts = []) : void { self::$defaultExecTime = ini_get('max_execution_time'); $doScripts = null; + + // register subscripts + foreach (glob('setup/tools/sqlgen/*.func.php') as $file) + include_once $file; + + while (self::$tmpStore) + { + $nDepsMissing = count(self::$tmpStore); + + foreach (self::$tmpStore as $idx => $ts) + { + $depsOK = true; + foreach ($ts->getDependancies(true) as $d) + { + if (isset(self::$tables[$d])) + continue; + + $depsOK = false; + break; + } + + if ($depsOK) + { + if (isset(self::$tables[$ssRef->getName()])) + { + CLI::write('a SetupScript named '.CLI::bold($ts->getName()).' was already registered. Skipping...', CLI::LOG_WARN); + unset(self::$tmpStore[$idx]); + continue; + } + + self::$tables[$ts->getName()] = $ts; + unset(self::$tmpStore[$idx]); + } + } + + if ($nDepsMissing == count(self::$tmpStore)) + { + CLI::write('the flollowing SetupScripts have unresolved dependancies and have not been registered:', CLI::LOG_ERROR); + foreach (self::$tmpStore as $ts) + CLI::write(' * '.CLI::bold($ts->getName()).' => '.implode(', ', $ts->getDependancies(true))); + + self::$tmpStore = []; + break; + } + } + + + // handle command prompts if (getopt(self::$shortOpts, self::$longOpts) || $mode == self::MODE_FIRSTRUN) self::handleCLIOpts($doScripts); else if ($mode != self::MODE_UPDATE) @@ -115,7 +103,50 @@ class SqlGen self::$mode = $mode; } - private static function handleCLIOpts(&$doTbls) + public static function register(SetupScript $ssRef) : bool + { + // if dependancies haven't been stored yet, put aside for later use + foreach ($ssRef->getDependancies(true) as $d) + { + if (isset(self::$tables[$d])) + continue; + + self::$tmpStore[] = $ssRef; + return false; + } + + if (isset(self::$tables[$ssRef->getName()])) + { + CLI::write('a SetupScript named '.CLI::bold($ssRef->getName()).' was already registered. Skipping...', CLI::LOG_WARN); + return false; + } + + self::$tables[$ssRef->getName()] = $ssRef; + + // recheck temp stored dependancies + foreach (self::$tmpStore as $idx => $ts) + { + $depsOK = true; + foreach ($ts->getDependancies(true) as $d) + { + if (isset(self::$tables[$d])) + continue; + + $depsOK = false; + break; + } + + if ($depsOK) + { + self::$tables[$ts->getName()] = $ts; + unset(self::$tmpStore[$idx]); + } + } + + return true; + } + + private static function handleCLIOpts(&$doTbls) : void { $doTbls = []; $_ = getopt(self::$shortOpts, self::$longOpts); @@ -130,13 +161,13 @@ class SqlGen if (!empty($_['sync'])) { $sync = explode(',', $_['sync']); - foreach (self::$tables as $name => $info) - if (!empty($info[3]) && array_intersect($sync, $info[3])) + foreach (self::$tables as $name => &$ssRef) + if (array_intersect($sync, $ssRef->getDependancies(false))) $doTbls[] = $name; // recursive dependencies - foreach (self::$tables as $name => $info) - if (!empty($info[2]) && array_intersect($doTbls, $info[2])) + foreach (self::$tables as $name => &$ssRef) + if (array_intersect($sync, $ssRef->getDependancies(true))) $doTbls[] = $name; $doTbls = $doTbls ? array_unique($doTbls) : null; @@ -145,17 +176,17 @@ class SqlGen $doTbls = explode(',', $_['sql']); } - public static function printCLIHelp() + public static function printCLIHelp() : void { echo "\nusage: php aowow --sql= [-h --help]\n\n"; echo "--sql : available tables:\n"; - foreach (self::$tables as $t => $info) - echo " * ".str_pad($t, 24).(isset($info[3]) ? ' - TC deps: '.implode(', ', $info[3]) : '').(isset($info[2]) ? ' - Aowow deps: '.implode(', ', $info[2]) : '')."\n"; + foreach (self::$tables as $t => &$ssRef) + echo " * ".str_pad($t, 24).($ssRef->getDependancies(false) ? ' - TC deps: '.implode(', ', $ssRef->getDependancies(false)) : '').($ssRef->getDependancies(true) ? ' - Aowow deps: '.implode(', ', $ssRef->getDependancies(true)) : '')."\n"; echo "-h --help : shows this info\n"; } - public static function generate($tableName, array $updateIds = []) + public static function generate(string $tableName, array $updateIds = []) : bool { if (!isset(self::$tables[$tableName])) { @@ -163,50 +194,28 @@ class SqlGen return false; } - if (!empty(self::$tables[$tableName][0])) // straight copy from dbc source + $ssRef = &self::$tables[$tableName]; + + CLI::write('SqlGen::generate() - filling aowow_'.$tableName.' with data'); + + // check for required auxiliary DBC files + if (!in_array('TrDBCcopy', class_uses($ssRef))) + foreach ($ssRef->getRequiredDBCs() as $req) + if (!CLISetup::loadDBC($req)) + return false; + + if ($ssRef->generate($updateIds)) { - $tbl = self::$tables[$tableName]; // shorthand - CLI::write('SqlGen::generate() - copying '.$tbl[0].'.dbc into aowow_'.$tableName); + if (method_exists($ssRef, 'applyCustomData')) + $ssRef->applyCustomData(); - $dbc = new DBC($tbl[0], ['temporary' => CLISetup::$tmpDBC, 'tableName' => 'aowow_'.$tableName]); - if ($dbc->error) - return false; - - return !!$dbc->readFile(); + return true; } - else if (file_exists('setup/tools/sqlgen/'.$tableName.'.func.php')) - { - $customData = $reqDBC = []; - - CLI::write('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 - CLI::write(' - subscript \''.$tableName.'\' not defined in included file', CLI::LOG_ERROR); - - return $success; - } - else - CLI::write(sprintf(ERR_MISSING_INCL, $tableName, 'setup/tools/sqlgen/'.$tableName.'.func.php'), CLI::LOG_ERROR); + return false; } - public static function getMode() + public static function getMode() : int { return self::$mode; } diff --git a/setup/tools/sqlgen/achievement.func.php b/setup/tools/sqlgen/achievement.func.php index 1ab10d85..fd1ad34a 100644 --- a/setup/tools/sqlgen/achievement.func.php +++ b/setup/tools/sqlgen/achievement.func.php @@ -7,22 +7,21 @@ if (!CLI) die('not in cli mode'); -/* deps: - * dbc_achievement - * disables -*/ - -// Higher Learning - item rewarded through gossip -$customData = array( - 1956 => ['itemExtra' => 44738] -); -$reqDBC = ['achievement_category', 'achievement', 'spellicon']; - -function achievement(array $ids = []) +SqlGen::register(new class extends SetupScript { - if ($ids) - DB::Aowow()->query('DELETE FROM ?_achievement WHERE id IN (?a)', $ids); - else + use TrCustomData; + + protected $command = 'achievement'; + + protected $tblDependancyAowow = ['icons']; + protected $tblDependancyTC = ['dbc_achievement', 'disables']; + protected $dbcSourceFiles = ['achievement_category', 'achievement', 'spellicon']; + + private $customData = array( + 1956 => ['itemExtra' => 44738] // Higher Learning - item rewarded through gossip + ); + + public function generate(array $ids = []) : bool { DB::Aowow()->query(' REPLACE INTO @@ -55,50 +54,51 @@ function achievement(array $ids = []) dbc_spellicon si ON si.id = a.iconId LEFT JOIN ?_icons i ON LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) = i.name - '); - } + { WHERE a.id IN (?a) } + ', $ids ?: DBSIMPLE_SKIP); - // serverside achievements - $serverAchievements = DB::World()->select('SELECT ID, IF(requiredFaction = -1, 3, IF(requiredFaction = 0, 2, 1)) AS "faction", mapID, points, flags, count, refAchievement FROM achievement_dbc{ WHERE id IN (?a)}', - $ids ?: DBSIMPLE_SKIP - ); - foreach ($serverAchievements as $sa) - DB::Aowow()->query('REPLACE INTO ?_achievement (id, faction, map, points, flags, reqCriteriaCount, refAchievement, cuFlags, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8) VALUES (?d, ?d, ?d, ?d, ?d, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?)', - $sa['ID'], $sa['faction'], $sa['mapID'], $sa['points'], $sa['flags'], $sa['count'], $sa['refAchievement'], CUSTOM_SERVERSIDE, - 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'] + // serverside achievements + $serverAchievements = DB::World()->select('SELECT ID, IF(requiredFaction = -1, 3, IF(requiredFaction = 0, 2, 1)) AS "faction", mapID, points, flags, count, refAchievement FROM achievement_dbc{ WHERE id IN (?a)}', + $ids ?: DBSIMPLE_SKIP ); - - if ($ids) - return true; - - // create chain of achievements - $chainIdx = 0; - $parents = DB::Aowow()->selectCol('SELECT a.id FROM dbc_achievement a JOIN dbc_achievement b ON b.previous = a.id WHERE a.previous = 0'); - foreach ($parents as $chainId => $next) - { - $tree = [null, $next]; - while ($next = DB::Aowow()->selectCell('SELECT id FROM dbc_achievement WHERE previous = ?d', $next)) - $tree[] = $next; - - foreach ($tree as $idx => $aId) - { - if (!$aId) - continue; - - DB::Aowow()->query('UPDATE ?_achievement SET cuFlags = cuFlags | ?d, chainId = ?d, chainPos = ?d WHERE id = ?d', - $idx == 1 ? ACHIEVEMENT_CU_FIRST_SERIES : (count($tree) == $idx + 1 ? ACHIEVEMENT_CU_LAST_SERIES : 0), - $chainId + 1, - $idx, - $aId + foreach ($serverAchievements as $sa) + DB::Aowow()->query('REPLACE INTO ?_achievement (id, faction, map, points, flags, reqCriteriaCount, refAchievement, cuFlags, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8) VALUES (?d, ?d, ?d, ?d, ?d, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?)', + $sa['ID'], $sa['faction'], $sa['mapID'], $sa['points'], $sa['flags'], $sa['count'], $sa['refAchievement'], CUSTOM_SERVERSIDE, + 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'], 'Serverside - #'.$sa['ID'] ); + + if ($ids) + return true; + + // create chain of achievements + $chainIdx = 0; + $parents = DB::Aowow()->selectCol('SELECT a.id FROM dbc_achievement a JOIN dbc_achievement b ON b.previous = a.id WHERE a.previous = 0'); + foreach ($parents as $chainId => $next) + { + $tree = [null, $next]; + while ($next = DB::Aowow()->selectCell('SELECT id FROM dbc_achievement WHERE previous = ?d', $next)) + $tree[] = $next; + + foreach ($tree as $idx => $aId) + { + if (!$aId) + continue; + + DB::Aowow()->query('UPDATE ?_achievement SET cuFlags = cuFlags | ?d, chainId = ?d, chainPos = ?d WHERE id = ?d', + $idx == 1 ? ACHIEVEMENT_CU_FIRST_SERIES : (count($tree) == $idx + 1 ? ACHIEVEMENT_CU_LAST_SERIES : 0), + $chainId + 1, + $idx, + $aId + ); + } } + + // apply disables + if ($criteria = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 4')) + DB::Aowow()->query('UPDATE aowow_achievement a JOIN aowow_achievementcriteria ac ON a.id = ac.refAchievementId SET a.cuFlags = ?d WHERE ac.id IN (?a)', CUSTOM_DISABLED, $criteria); + + return true; } - - // apply disables - if ($criteria = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 4')) - DB::Aowow()->query('UPDATE aowow_achievement a JOIN aowow_achievementcriteria ac ON a.id = ac.refAchievementId SET a.cuFlags = ?d WHERE ac.id IN (?a)', CUSTOM_DISABLED, $criteria); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/achievementcategory.func.php b/setup/tools/sqlgen/achievementcategory.func.php new file mode 100644 index 00000000..c79e6bcf --- /dev/null +++ b/setup/tools/sqlgen/achievementcategory.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/achievementcriteria.func.php b/setup/tools/sqlgen/achievementcriteria.func.php new file mode 100644 index 00000000..7ba793df --- /dev/null +++ b/setup/tools/sqlgen/achievementcriteria.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/areatrigger.func.php b/setup/tools/sqlgen/areatrigger.func.php index 1c03d8e9..130af58c 100644 --- a/setup/tools/sqlgen/areatrigger.func.php +++ b/setup/tools/sqlgen/areatrigger.func.php @@ -7,101 +7,96 @@ if (!CLI) die('not in cli mode'); -/* deps: - * areatrigger_tavern - * areatrigger_scripts - * areatrigger_involvedrelation - * quest_template - * quest_template_addon - * areatrigger_teleport -*/ - -$customData = array( -); -$reqDBC = ['areatrigger']; - -function areatrigger(/*array $ids = [] */) +SqlGen::register(new class extends SetupScript { - DB::Aowow()->query('TRUNCATE ?_areatrigger'); - DB::Aowow()->query('INSERT INTO ?_areatrigger SELECT id, 0, 0, NULL, orientation, NULL, NULL, NULL, NULL, NULL, NULL FROM dbc_areatrigger'); + protected $command = 'areatrigger'; - /* notes: - * while areatrigger DO have dimensions, displaying them on a map is almost always futile, - * as they are either too small to be noticable or larger than the map itself (looking at you, oculus dungeon exit) - */ + protected $tblDependancyTC = ['areatrigger_involvedrelation', 'areatrigger_scripts', 'areatrigger_tavern', 'areatrigger_teleport', 'quest_template', 'quest_template_addon']; + protected $dbcSourceFiles = ['areatrigger']; - // 1: Taverns - CLI::write(' - fetching taverns'); - - $addData = DB::World()->select('SELECT id AS ARRAY_KEY, name, ?d AS `type` FROM areatrigger_tavern', AT_TYPE_TAVERN); - foreach ($addData as $id => $ad) - DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE id = ?d', $ad, $id); - - // 2: Teleporter + teleporting 4: Smart Trigger - CLI::write(' - calculation teleporter coordinates'); - - $addData = DB::World()->select(' - SELECT ID AS ARRAY_KEY, Name AS `name`, target_map AS `map`, target_position_x AS `posY`, target_position_y AS `posX`, target_orientation AS `orientation` FROM areatrigger_teleport UNION - SELECT entryorguid AS ARRAY_KEY, "TBD" AS `name`, action_param1 AS `map`, target_x AS `posY`, target_y AS `posX`, target_o AS `orientation` FROM smart_scripts WHERE source_type = 2 AND action_type = 62 - '); - foreach ($addData as $id => $ad) + public function generate(array $ids = []) : bool { - // todo (low): unify with spawns function - $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, 571) OR wma.areaId = 4395), wma.mapId, -1) ' . - 'WHERE wma.mapId = ?d AND wma.areaId <> 0 ' . - 'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) ' . - 'ORDER BY quality ASC'; + DB::Aowow()->query('TRUNCATE ?_areatrigger'); + DB::Aowow()->query('INSERT INTO ?_areatrigger SELECT id, 0, 0, NULL, orientation, NULL, NULL, NULL, NULL, NULL, NULL FROM dbc_areatrigger'); - $points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 1, $ad['map']); - if (!$points) - $points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 0, $ad['map']); + /* notes: + * while areatrigger DO have dimensions, displaying them on a map is almost always futile, + * as they are either too small to be noticable or larger than the map itself (looking at you, oculus dungeon exit) + */ - if (!$points) + // 1: Taverns + CLI::write(' - fetching taverns'); + + $addData = DB::World()->select('SELECT id AS ARRAY_KEY, name, ?d AS `type` FROM areatrigger_tavern', AT_TYPE_TAVERN); + foreach ($addData as $id => $ad) + DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE id = ?d', $ad, $id); + + // 2: Teleporter + teleporting 4: Smart Trigger + CLI::write(' - calculation teleporter coordinates'); + + $addData = DB::World()->select(' + SELECT ID AS ARRAY_KEY, Name AS `name`, target_map AS `map`, target_position_x AS `posY`, target_position_y AS `posX`, target_orientation AS `orientation` FROM areatrigger_teleport UNION + SELECT entryorguid AS ARRAY_KEY, "TBD" AS `name`, action_param1 AS `map`, target_x AS `posY`, target_y AS `posX`, target_o AS `orientation` FROM smart_scripts WHERE source_type = 2 AND action_type = 62 + '); + foreach ($addData as $id => $ad) { - CLI::write(' * AT '.$id.' teleporter endpoint '.CLI::bold($ad['name']).' could not be matched to displayable area [M:'.$ad['map'].'; X:'.$ad['posY'].'; Y:'.$ad['posX'].']', CLI::LOG_WARN); - DB::Aowow()->query('UPDATE ?_areatrigger SET `name` = ?, `type` = ?d WHERE id = ?d', $ad['name'], AT_TYPE_TELEPORT, $id); - continue; + // todo (low): unify with spawns function + $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, 571) OR wma.areaId = 4395), wma.mapId, -1) ' . + 'WHERE wma.mapId = ?d AND wma.areaId <> 0 ' . + 'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) ' . + 'ORDER BY quality ASC'; + + $points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 1, $ad['map']); + if (!$points) + $points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 0, $ad['map']); + + if (!$points) + { + CLI::write(' * AT '.$id.' teleporter endpoint '.CLI::bold($ad['name']).' could not be matched to displayable area [M:'.$ad['map'].'; X:'.$ad['posY'].'; Y:'.$ad['posX'].']', CLI::LOG_WARN); + DB::Aowow()->query('UPDATE ?_areatrigger SET `name` = ?, `type` = ?d WHERE id = ?d', $ad['name'], AT_TYPE_TELEPORT, $id); + continue; + } + + $update = array( + 'name' => $ad['name'], + 'type' => AT_TYPE_TELEPORT, + 'teleportA' => $points[0]['areaId'], + 'teleportX' => $points[0]['posX'], + 'teleportY' => $points[0]['posY'], + 'teleportO' => $ad['orientation'], + 'teleportF' => $points[0]['floor'] + ); + + DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE id = ?d', $update, $id); } - $update = array( - 'name' => $ad['name'], - 'type' => AT_TYPE_TELEPORT, - 'teleportA' => $points[0]['areaId'], - 'teleportX' => $points[0]['posX'], - 'teleportY' => $points[0]['posY'], - 'teleportO' => $ad['orientation'], - 'teleportF' => $points[0]['floor'] - ); + // 3: Quest Objectives + CLI::write(' - satisfying quest objectives'); - DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE id = ?d', $update, $id); + $addData = DB::World()->select('SELECT atir.id AS ARRAY_KEY, qt.ID AS quest, NULLIF(qt.AreaDescription, "") AS `name`, qta.SpecialFlags FROM quest_template qt LEFT JOIN quest_template_addon qta ON qta.ID = qt.ID JOIN areatrigger_involvedrelation atir ON atir.quest = qt.ID'); + foreach ($addData as $id => $ad) + { + if (!($ad['SpecialFlags'] & QUEST_FLAG_SPECIAL_EXT_COMPLETE)) + CLI::write(' * Areatrigger '.CLI::bold($id).' is involved in Quest '.CLI::bold($ad['quest']).', but Quest is not flagged for external completion (SpecialFlags & '.Util::asHex(QUEST_FLAG_SPECIAL_EXT_COMPLETE).')', CLI::LOG_WARN); + + DB::Aowow()->query('UPDATE ?_areatrigger SET name = ?, type = ?d, quest = ?d WHERE id = ?d', $ad['name'], AT_TYPE_OBJECTIVE, $ad['quest'], $id); + } + + // 4/5 Scripted + CLI::write(' - assigning scripts'); + + $addData = DB::World()->select('SELECT entry AS ARRAY_KEY, IF(ScriptName = "SmartTrigger", NULL, ScriptName) AS `name`, IF(ScriptName = "SmartTrigger", 4, 5) AS `type` FROM areatrigger_scripts'); + foreach ($addData as $id => $ad) + DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE id = ?d', $ad, $id); + + return true; } - - // 3: Quest Objectives - CLI::write(' - satisfying quest objectives'); - - $addData = DB::World()->select('SELECT atir.id AS ARRAY_KEY, qt.ID AS quest, NULLIF(qt.AreaDescription, "") AS `name`, qta.SpecialFlags FROM quest_template qt LEFT JOIN quest_template_addon qta ON qta.ID = qt.ID JOIN areatrigger_involvedrelation atir ON atir.quest = qt.ID'); - foreach ($addData as $id => $ad) - { - if (!($ad['SpecialFlags'] & QUEST_FLAG_SPECIAL_EXT_COMPLETE)) - CLI::write(' * Areatrigger '.CLI::bold($id).' is involved in Quest '.CLI::bold($ad['quest']).', but Quest is not flagged for external completion (SpecialFlags & '.Util::asHex(QUEST_FLAG_SPECIAL_EXT_COMPLETE).')', CLI::LOG_WARN); - - DB::Aowow()->query('UPDATE ?_areatrigger SET name = ?, type = ?d, quest = ?d WHERE id = ?d', $ad['name'], AT_TYPE_OBJECTIVE, $ad['quest'], $id); - } - - // 4/5 Scripted - CLI::write(' - assigning scripts'); - - $addData = DB::World()->select('SELECT entry AS ARRAY_KEY, IF(ScriptName = "SmartTrigger", NULL, ScriptName) AS `name`, IF(ScriptName = "SmartTrigger", 4, 5) AS `type` FROM areatrigger_scripts'); - foreach ($addData as $id => $ad) - DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE id = ?d', $ad, $id); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/classes.func.php b/setup/tools/sqlgen/classes.func.php index 098b3b15..00709f20 100644 --- a/setup/tools/sqlgen/classes.func.php +++ b/setup/tools/sqlgen/classes.func.php @@ -7,44 +7,52 @@ if (!CLI) die('not in cli mode'); -// roles (1:heal; 2:mleDPS; 4:rngDPS; 8:tank) -$customData = array( - 1 => ['roles' => 0xA], - 2 => ['roles' => 0xB], - 3 => ['roles' => 0x4], - 4 => ['roles' => 0x2], - 5 => ['roles' => 0x5], - 6 => ['roles' => 0xA], - 7 => ['roles' => 0x7], - 8 => ['roles' => 0x4], - 9 => ['roles' => 0x4], - 11 => ['roles' => 0xF], -); -$reqDBC = ['spell', 'charbaseinfo', 'skillraceclassinfo', 'skilllineability', 'chrclasses']; - -function classes() +SqlGen::register(new class extends SetupScript { - $classes = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_chrclasses'); + use TrCustomData; - // add raceMask - $races = DB::Aowow()->select('SELECT classId AS ARRAY_KEY, BIT_OR(1 << (raceId - 1)) AS raceMask FROM dbc_charbaseinfo GROUP BY classId'); - Util::arraySumByKey($classes, $races); + protected $command = 'classes'; - // add skills - $skills = DB::Aowow()->select('SELECT LOG(2, classMask) + 1 AS ARRAY_KEY, GROUP_CONCAT(skillLine SEPARATOR \' \') AS skills FROM dbc_skillraceclassinfo WHERE flags = 1040 GROUP BY classMask HAVING ARRAY_KEY = CAST(LOG(2, classMask) + 1 AS SIGNED)'); - Util::arraySumByKey($classes, $skills); + protected $dbcSourceFiles = ['spell', 'charbaseinfo', 'skillraceclassinfo', 'skilllineability', 'chrclasses']; - // add weaponTypeMask & armorTypeMask - foreach ($classes as $id => &$data) + // roles (1:heal; 2:mleDPS; 4:rngDPS; 8:tank) + private $customData = array( + 1 => ['roles' => 0xA], + 2 => ['roles' => 0xB], + 3 => ['roles' => 0x4], + 4 => ['roles' => 0x2], + 5 => ['roles' => 0x5], + 6 => ['roles' => 0xA], + 7 => ['roles' => 0x7], + 8 => ['roles' => 0x4], + 9 => ['roles' => 0x4], + 11 => ['roles' => 0xF], + ); + + public function generate(array $ids = []) : bool { - $data['weaponTypeMask'] = DB::Aowow()->selectCell('SELECT BIT_OR(equippedItemSubClassMask) FROM dbc_spell s JOIN dbc_skilllineability sla ON sla.spellId = s.id JOIN dbc_skillraceclassinfo srci ON srci.skillLine = sla.skillLineId AND srci.classMask & ?d WHERE sla.skilllineid <> 183 AND (sla.reqClassMask & ?d OR sla.reqClassMask = 0) AND equippedItemClass = ?d AND (effect1Id = 60 OR effect2Id = 60)', 1 << ($id - 1), 1 << ($id - 1), ITEM_CLASS_WEAPON); - $data['armorTypeMask'] = DB::Aowow()->selectCell('SELECT BIT_OR(equippedItemSubClassMask) FROM dbc_spell s JOIN dbc_skilllineability sla ON sla.spellId = s.id JOIN dbc_skillraceclassinfo srci ON srci.skillLine = sla.skillLineId AND srci.classMask & ?d WHERE sla.reqClassMask & ?d AND equippedItemClass = ?d AND (effect1Id = 60 OR effect2Id = 60)', 1 << ($id - 1), 1 << ($id - 1), ITEM_CLASS_ARMOR); + $classes = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_chrclasses'); + + // add raceMask + $races = DB::Aowow()->select('SELECT classId AS ARRAY_KEY, BIT_OR(1 << (raceId - 1)) AS raceMask FROM dbc_charbaseinfo GROUP BY classId'); + Util::arraySumByKey($classes, $races); + + // add skills + $skills = DB::Aowow()->select('SELECT LOG(2, classMask) + 1 AS ARRAY_KEY, GROUP_CONCAT(skillLine SEPARATOR \' \') AS skills FROM dbc_skillraceclassinfo WHERE flags = 1040 GROUP BY classMask HAVING ARRAY_KEY = CAST(LOG(2, classMask) + 1 AS SIGNED)'); + Util::arraySumByKey($classes, $skills); + + // add weaponTypeMask & armorTypeMask + foreach ($classes as $id => &$data) + { + $data['weaponTypeMask'] = DB::Aowow()->selectCell('SELECT BIT_OR(equippedItemSubClassMask) FROM dbc_spell s JOIN dbc_skilllineability sla ON sla.spellId = s.id JOIN dbc_skillraceclassinfo srci ON srci.skillLine = sla.skillLineId AND srci.classMask & ?d WHERE sla.skilllineid <> 183 AND (sla.reqClassMask & ?d OR sla.reqClassMask = 0) AND equippedItemClass = ?d AND (effect1Id = 60 OR effect2Id = 60)', 1 << ($id - 1), 1 << ($id - 1), ITEM_CLASS_WEAPON); + $data['armorTypeMask'] = DB::Aowow()->selectCell('SELECT BIT_OR(equippedItemSubClassMask) FROM dbc_spell s JOIN dbc_skilllineability sla ON sla.spellId = s.id JOIN dbc_skillraceclassinfo srci ON srci.skillLine = sla.skillLineId AND srci.classMask & ?d WHERE sla.reqClassMask & ?d AND equippedItemClass = ?d AND (effect1Id = 60 OR effect2Id = 60)', 1 << ($id - 1), 1 << ($id - 1), ITEM_CLASS_ARMOR); + } + + foreach ($classes as $cl) + DB::Aowow()->query('REPLACE INTO ?_classes (?#) VALUES (?a)', array_keys($cl), array_values($cl)); + + return true; } - - foreach ($classes as $cl) - DB::Aowow()->query('REPLACE INTO ?_classes (?#) VALUES (?a)', array_keys($cl), array_values($cl)); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/creature.func.php b/setup/tools/sqlgen/creature.func.php index ecef6462..56abf74a 100644 --- a/setup/tools/sqlgen/creature.func.php +++ b/setup/tools/sqlgen/creature.func.php @@ -7,156 +7,152 @@ if (!CLI) die('not in cli mode'); -/* deps: - * creature_template - * creature_template_locale - * creature_classlevelstats - * instance_encounters -*/ - - -$customData = array( -); -$reqDBC = ['creaturedisplayinfo', 'creaturedisplayinfoextra']; - -function creature(array $ids = []) +SqlGen::register(new class extends SetupScript { - $baseQuery = ' - SELECT - ct.entry, - IF(ie.entry IS NULL, 0, ?d) AS cuFlags, -- cuFlags - difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, - KillCredit1, KillCredit2, - modelid1, modelid2, modelid3, modelid4, - "" AS textureString, -- textureString - 0 AS modelId, -- modelId - 0 AS humanoid, -- uses creaturedisplayinfoextra - "" AS iconString, -- iconString - ct.name, IFNULL(ctl2.`Name`, "") AS n2, IFNULL(ctl3.`Name`, "") AS n3, IFNULL(ctl4.`Name`, "") AS n4, IFNULL(ctl6.`Name`, "") AS n6, IFNULL(ctl8.`Name`, "") AS n8, - subname, IFNULL(ctl2.`Title`, "") AS t2, IFNULL(ctl3.`Title`, "") AS t3, IFNULL(ctl4.`Title`, "") AS t4, IFNULL(ctl6.`Title`, "") AS t6, IFNULL(ctl8.`Title`, "") AS t8, - minLevel, maxLevel, - exp, - faction, - npcflag, - IF(rank > 4, 0, rank), - dmgSchool, - DamageModifier, - BaseAttackTime, - RangeAttackTime, - BaseVariance, - RangeVariance, - unit_class, - unit_flags, unit_flags2, dynamicflags, - family, - trainer_type, - trainer_spell, - trainer_class, - trainer_race, - (CASE ct.exp WHEN 0 THEN min.damage_base WHEN 1 THEN min.damage_exp1 ELSE min.damage_exp2 END) AS dmgMin, - (CASE ct.exp WHEN 0 THEN max.damage_base WHEN 1 THEN max.damage_exp1 ELSE max.damage_exp2 END) AS dmgMax, - min.attackpower AS mleAtkPwrMin, - max.attackpower AS mleAtkPwrMax, - min.rangedattackpower AS rmgAtkPwrMin, - max.rangedattackpower AS rmgAtkPwrMax, - type, - type_flags, - lootid, pickpocketloot, skinloot, - spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, - PetSpellDataId, - VehicleId, - mingold, maxgold, - AIName, - (CASE ct.exp WHEN 0 THEN min.basehp0 WHEN 1 THEN min.basehp1 ELSE min.basehp2 END) * ct.HealthModifier AS healthMin, - (CASE ct.exp WHEN 0 THEN max.basehp0 WHEN 1 THEN max.basehp1 ELSE max.basehp2 END) * ct.HealthModifier AS healthMax, - min.basemana * ct.ManaModifier AS manaMin, - max.basemana * ct.ManaModifier AS manaMax, - min.basearmor * ct.ArmorModifier AS armorMin, - max.basearmor * ct.ArmorModifier AS armorMax, - RacialLeader, - mechanic_immune_mask, - flags_extra, - ScriptName - FROM - creature_template ct - JOIN - creature_classlevelstats min ON ct.unit_class = min.class AND ct.minlevel = min.level - JOIN - creature_classlevelstats max ON ct.unit_class = max.class AND ct.maxlevel = max.level - LEFT JOIN - creature_template_locale ctl2 ON ct.entry = ctl2.entry AND ctl2.`locale` = "frFR" - LEFT JOIN - creature_template_locale ctl3 ON ct.entry = ctl3.entry AND ctl3.`locale` = "deDE" - LEFT JOIN - creature_template_locale ctl4 ON ct.entry = ctl4.entry AND ctl4.`locale` = "zhCN" - LEFT JOIN - creature_template_locale ctl6 ON ct.entry = ctl6.entry AND ctl6.`locale` = "esES" - LEFT JOIN - creature_template_locale ctl8 ON ct.entry = ctl8.entry AND ctl8.`locale` = "ruRU" - LEFT JOIN - instance_encounters ie ON ie.creditEntry = ct.entry AND ie.creditType = 0 - WHERE - ct.entry > ?d - { - AND ct.entry IN (?a) - } - ORDER BY - ct.entry ASC - LIMIT - ?d'; + protected $command = 'creature'; - $dummyQuery = ' - UPDATE - ?_creature a - JOIN - ( - SELECT b.difficultyEntry1 AS dummy FROM ?_creature b UNION - SELECT c.difficultyEntry2 AS dummy FROM ?_creature c UNION - SELECT d.difficultyEntry3 AS dummy FROM ?_creature d - ) j - SET - a.cuFlags = a.cuFlags | ?d - WHERE - a.id = j.dummy'; + protected $tblDependancyTC = ['creature_template', 'creature_template_locale', 'creature_classlevelstats', 'instance_encounters']; + protected $dbcSourceFiles = ['creaturedisplayinfo', 'creaturedisplayinfoextra']; - $displayInfoQuery = ' - UPDATE - ?_creature c - JOIN - dbc_creaturedisplayinfo cdi ON c.displayId1 = cdi.id - LEFT JOIN - dbc_creaturedisplayinfoextra cdie ON cdi.extraInfoId = cdie.id - SET - c.textureString = IFNULL(cdie.textureString, cdi.skin1), - c.modelId = cdi.modelId, - c.iconString = cdi.iconString, - c.humanoid = IF(cdie.id IS NULL, 0, 1)'; - - $lastMax = 0; - while ($npcs = DB::World()->select($baseQuery, NPC_CU_INSTANCE_BOSS, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$stepSize)) + public function generate(array $ids = []) : bool { - $newMax = max(array_column($npcs, 'entry')); + $baseQuery = ' + SELECT + ct.entry, + IF(ie.entry IS NULL, 0, ?d) AS cuFlags, -- cuFlags + difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, + KillCredit1, KillCredit2, + modelid1, modelid2, modelid3, modelid4, + "" AS textureString, -- textureString + 0 AS modelId, -- modelId + 0 AS humanoid, -- uses creaturedisplayinfoextra + "" AS iconString, -- iconString + ct.name, IFNULL(ctl2.`Name`, "") AS n2, IFNULL(ctl3.`Name`, "") AS n3, IFNULL(ctl4.`Name`, "") AS n4, IFNULL(ctl6.`Name`, "") AS n6, IFNULL(ctl8.`Name`, "") AS n8, + subname, IFNULL(ctl2.`Title`, "") AS t2, IFNULL(ctl3.`Title`, "") AS t3, IFNULL(ctl4.`Title`, "") AS t4, IFNULL(ctl6.`Title`, "") AS t6, IFNULL(ctl8.`Title`, "") AS t8, + minLevel, maxLevel, + exp, + faction, + npcflag, + IF(rank > 4, 0, rank), + dmgSchool, + DamageModifier, + BaseAttackTime, + RangeAttackTime, + BaseVariance, + RangeVariance, + unit_class, + unit_flags, unit_flags2, dynamicflags, + family, + trainer_type, + trainer_spell, + trainer_class, + trainer_race, + (CASE ct.exp WHEN 0 THEN min.damage_base WHEN 1 THEN min.damage_exp1 ELSE min.damage_exp2 END) AS dmgMin, + (CASE ct.exp WHEN 0 THEN max.damage_base WHEN 1 THEN max.damage_exp1 ELSE max.damage_exp2 END) AS dmgMax, + min.attackpower AS mleAtkPwrMin, + max.attackpower AS mleAtkPwrMax, + min.rangedattackpower AS rmgAtkPwrMin, + max.rangedattackpower AS rmgAtkPwrMax, + type, + type_flags, + lootid, pickpocketloot, skinloot, + spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, + PetSpellDataId, + VehicleId, + mingold, maxgold, + AIName, + (CASE ct.exp WHEN 0 THEN min.basehp0 WHEN 1 THEN min.basehp1 ELSE min.basehp2 END) * ct.HealthModifier AS healthMin, + (CASE ct.exp WHEN 0 THEN max.basehp0 WHEN 1 THEN max.basehp1 ELSE max.basehp2 END) * ct.HealthModifier AS healthMax, + min.basemana * ct.ManaModifier AS manaMin, + max.basemana * ct.ManaModifier AS manaMax, + min.basearmor * ct.ArmorModifier AS armorMin, + max.basearmor * ct.ArmorModifier AS armorMax, + RacialLeader, + mechanic_immune_mask, + flags_extra, + ScriptName + FROM + creature_template ct + JOIN + creature_classlevelstats min ON ct.unit_class = min.class AND ct.minlevel = min.level + JOIN + creature_classlevelstats max ON ct.unit_class = max.class AND ct.maxlevel = max.level + LEFT JOIN + creature_template_locale ctl2 ON ct.entry = ctl2.entry AND ctl2.`locale` = "frFR" + LEFT JOIN + creature_template_locale ctl3 ON ct.entry = ctl3.entry AND ctl3.`locale` = "deDE" + LEFT JOIN + creature_template_locale ctl4 ON ct.entry = ctl4.entry AND ctl4.`locale` = "zhCN" + LEFT JOIN + creature_template_locale ctl6 ON ct.entry = ctl6.entry AND ctl6.`locale` = "esES" + LEFT JOIN + creature_template_locale ctl8 ON ct.entry = ctl8.entry AND ctl8.`locale` = "ruRU" + LEFT JOIN + instance_encounters ie ON ie.creditEntry = ct.entry AND ie.creditType = 0 + WHERE + ct.entry > ?d + { + AND ct.entry IN (?a) + } + ORDER BY + ct.entry ASC + LIMIT + ?d'; - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + $dummyQuery = ' + UPDATE + ?_creature a + JOIN + ( + SELECT b.difficultyEntry1 AS dummy FROM ?_creature b UNION + SELECT c.difficultyEntry2 AS dummy FROM ?_creature c UNION + SELECT d.difficultyEntry3 AS dummy FROM ?_creature d + ) j + SET + a.cuFlags = a.cuFlags | ?d + WHERE + a.id = j.dummy'; - $lastMax = $newMax; + $displayInfoQuery = ' + UPDATE + ?_creature c + JOIN + dbc_creaturedisplayinfo cdi ON c.displayId1 = cdi.id + LEFT JOIN + dbc_creaturedisplayinfoextra cdie ON cdi.extraInfoId = cdie.id + SET + c.textureString = IFNULL(cdie.textureString, cdi.skin1), + c.modelId = cdi.modelId, + c.iconString = cdi.iconString, + c.humanoid = IF(cdie.id IS NULL, 0, 1)'; - foreach ($npcs as $npc) - DB::Aowow()->query('REPLACE INTO ?_creature VALUES (?a)', array_values($npc)); + $lastMax = 0; + while ($npcs = DB::World()->select($baseQuery, NPC_CU_INSTANCE_BOSS, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + { + $newMax = max(array_column($npcs, 'entry')); + + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + + $lastMax = $newMax; + + foreach ($npcs as $npc) + DB::Aowow()->query('REPLACE INTO ?_creature VALUES (?a)', array_values($npc)); + } + + // apply "textureString", "modelId" and "iconSring" + DB::Aowow()->query($displayInfoQuery); + + // apply cuFlag: difficultyDummy + DB::Aowow()->query($dummyQuery, NPC_CU_DIFFICULTY_DUMMY | CUSTOM_EXCLUDE_FOR_LISTVIEW); + + // apply cuFlag: excludeFromListview [for trigger-creatures] + DB::Aowow()->query('UPDATE ?_creature SET cuFlags = cuFlags | ?d WHERE flagsExtra & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x80); + + // apply cuFlag: exCludeFromListview [for nameparts indicating internal usage] + DB::Aowow()->query('UPDATE ?_creature SET cuFlags = cuFlags | ?d WHERE name_loc0 LIKE "%[%" OR name_loc0 LIKE "%(%" OR name_loc0 LIKE "%visual%" OR name_loc0 LIKE "%trigger%" OR name_loc0 LIKE "%credit%" OR name_loc0 LIKE "%marker%"', CUSTOM_EXCLUDE_FOR_LISTVIEW); + + return true; } - - // apply "textureString", "modelId" and "iconSring" - DB::Aowow()->query($displayInfoQuery); - - // apply cuFlag: difficultyDummy - DB::Aowow()->query($dummyQuery, NPC_CU_DIFFICULTY_DUMMY | CUSTOM_EXCLUDE_FOR_LISTVIEW); - - // apply cuFlag: excludeFromListview [for trigger-creatures] - DB::Aowow()->query('UPDATE ?_creature SET cuFlags = cuFlags | ?d WHERE flagsExtra & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x80); - - // apply cuFlag: exCludeFromListview [for nameparts indicating internal usage] - DB::Aowow()->query('UPDATE ?_creature SET cuFlags = cuFlags | ?d WHERE name_loc0 LIKE "%[%" OR name_loc0 LIKE "%(%" OR name_loc0 LIKE "%visual%" OR name_loc0 LIKE "%trigger%" OR name_loc0 LIKE "%credit%" OR name_loc0 LIKE "%marker%"', CUSTOM_EXCLUDE_FOR_LISTVIEW); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/currencies.func.php b/setup/tools/sqlgen/currencies.func.php index db6d21e3..e1c1b68d 100644 --- a/setup/tools/sqlgen/currencies.func.php +++ b/setup/tools/sqlgen/currencies.func.php @@ -7,82 +7,87 @@ if (!CLI) die('not in cli mode'); -/* deps: - * item_template - * item_template_locale -*/ - -// hide test tokens and move them to unused -$customData = array( - 1 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], - 2 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], - 4 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], - 22 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], - 141 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], - 103 => ['cap' => 10000], // Arena Points - 104 => ['cap' => 75000] // Honor Points -); -$reqDBC = ['itemdisplayinfo', 'currencytypes']; - -function currencies(array $ids = []) +SqlGen::register(new class extends SetupScript { - if (!$ids) - DB::Aowow()->query('REPLACE INTO ?_currencies (id, category, itemId) SELECT id, category, itemId FROM dbc_currencytypes'); + use TrCustomData; - $moneyItems = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, itemId FROM dbc_currencytypes{ WHERE id IN (?a)}', $ids ?: DBSIMPLE_SKIP); + protected $command = 'currencies'; - // apply names & cap - $moneyNames = DB::World()->select(' - SELECT - it.entry AS ARRAY_KEY, - it.name AS name_loc0, IFNULL(itl2.Name, "") AS name_loc2, IFNULL(itl3.Name, "") AS name_loc3, IFNULL(itl4.Name, "") AS name_loc4, IFNULL(itl6.Name, "") AS name_loc6, IFNULL(itl8.Name, "") AS name_loc8, - it.maxCount AS cap - FROM - item_template it - LEFT JOIN - item_template_locale itl2 ON it.entry = itl2.ID AND itl2.locale = "frFR" - LEFT JOIN - item_template_locale itl3 ON it.entry = itl3.ID AND itl3.locale = "deDE" - LEFT JOIN - item_template_locale itl4 ON it.entry = itl4.ID AND itl4.locale = "zhCN" - LEFT JOIN - item_template_locale itl6 ON it.entry = itl6.ID AND itl6.locale = "esES" - LEFT JOIN - item_template_locale itl8 ON it.entry = itl8.ID AND itl8.locale = "ruRU" - WHERE - it.entry IN (?a)', - $moneyItems); + protected $tblDependancyAowow = ['icons']; + protected $tblDependancyTC = ['item_template', 'item_template_locale']; + protected $dbcSourceFiles = ['itemdisplayinfo', 'currencytypes']; - foreach ($moneyItems as $cId => $itemId) + // hide test tokens and move them to unused + private $customData = array( + 1 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], + 2 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], + 4 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], + 22 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], + 141 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3], + 103 => ['cap' => 10000], // Arena Points + 104 => ['cap' => 75000] // Honor Points + ); + + public function generate(array $ids = []) : bool { - if (!empty($moneyNames[$itemId])) - $strings = $moneyNames[$itemId]; - else + 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 & cap + $moneyNames = DB::World()->select(' + SELECT + it.entry AS ARRAY_KEY, + it.name AS name_loc0, IFNULL(itl2.Name, "") AS name_loc2, IFNULL(itl3.Name, "") AS name_loc3, IFNULL(itl4.Name, "") AS name_loc4, IFNULL(itl6.Name, "") AS name_loc6, IFNULL(itl8.Name, "") AS name_loc8, + it.maxCount AS cap + FROM + item_template it + LEFT JOIN + item_template_locale itl2 ON it.entry = itl2.ID AND itl2.locale = "frFR" + LEFT JOIN + item_template_locale itl3 ON it.entry = itl3.ID AND itl3.locale = "deDE" + LEFT JOIN + item_template_locale itl4 ON it.entry = itl4.ID AND itl4.locale = "zhCN" + LEFT JOIN + item_template_locale itl6 ON it.entry = itl6.ID AND itl6.locale = "esES" + LEFT JOIN + item_template_locale itl8 ON it.entry = itl8.ID AND itl8.locale = "ruRU" + WHERE + it.entry IN (?a)', + $moneyItems); + + foreach ($moneyItems as $cId => $itemId) { - CLI::write('item #'.$itemId.' required by currency #'.$cId.' not in item_template', CLI::LOG_WARN); - $strings = ['name_loc0' => 'Item #'.$itemId.' not in DB', 'iconId' => 0, 'cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3]; + if (!empty($moneyNames[$itemId])) + $strings = $moneyNames[$itemId]; + else + { + CLI::write('item #'.$itemId.' required by currency #'.$cId.' not in item_template', CLI::LOG_WARN); + $strings = ['name_loc0' => 'Item #'.$itemId.' not in DB', 'iconId' => 0, 'cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3]; + } + + DB::Aowow()->query('UPDATE ?_currencies SET ?a WHERE itemId = ?d', $strings, $itemId); } - 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 c, + ?_icons i, + dbc_itemdisplayinfo idi + SET + c.iconId = i.id + WHERE + i.name = LOWER(idi.inventoryIcon1) AND + idi.id = ?d AND + c.itemId = ?d + ', $iconId, $itemId); + + return true; } - - // 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 c, - ?_icons i, - dbc_itemdisplayinfo idi - SET - c.iconId = i.id - WHERE - i.name = LOWER(idi.inventoryIcon1) AND - idi.id = ?d AND - c.itemId = ?d - ', $iconId, $itemId); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/emotes.func.php b/setup/tools/sqlgen/emotes.func.php index 0c188d68..bd8eb042 100644 --- a/setup/tools/sqlgen/emotes.func.php +++ b/setup/tools/sqlgen/emotes.func.php @@ -7,93 +7,96 @@ if (!CLI) die('not in cli mode'); -$customData = array( -); -$reqDBC = ['emotes', 'emotestext', 'emotestextdata']; - -function emotes(/*array $ids = [] */) +SqlGen::register(new class extends SetupScript { - /**********/ - /* Basics */ - /**********/ + protected $command = 'emotes'; - $globStrPath = CLISetup::$srcDir.'%sInterface/FrameXML/GlobalStrings.lua'; - $allOK = true; - $locPath = []; + protected $dbcSourceFiles = ['emotes', 'emotestext', 'emotestextdata']; - DB::Aowow()->query('TRUNCATE ?_emotes_aliasses'); - - foreach (CLISetup::$localeIds as $lId) + public function generate(array $ids = []) : bool { - foreach (CLISetup::$expectedPaths as $xp => $locId) + /**********/ + /* Basics */ + /**********/ + + $globStrPath = CLISetup::$srcDir.'%sInterface/FrameXML/GlobalStrings.lua'; + $allOK = true; + $locPath = []; + + DB::Aowow()->query('TRUNCATE ?_emotes_aliasses'); + + foreach (CLISetup::$localeIds as $lId) { - if ($lId != $locId) - continue; - - if ($xp) // if in subDir add trailing slash - $xp .= '/'; - - $path = sprintf($globStrPath, $xp); - if (CLISetup::fileExists($path)) + foreach (CLISetup::$expectedPaths as $xp => $locId) { - $locPath[$lId] = $path; - continue 2; + if ($lId != $locId) + continue; + + if ($xp) // if in subDir add trailing slash + $xp .= '/'; + + $path = sprintf($globStrPath, $xp); + if (CLISetup::fileExists($path)) + { + $locPath[$lId] = $path; + continue 2; + } + } + + CLI::write('GlobalStrings.lua not found for selected locale '.CLI::bold(Util::$localeStrings[$lId]), CLI::LOG_WARN); + $allOK = false; + } + + $_= DB::Aowow()->query('REPLACE INTO ?_emotes SELECT + et.id, + LOWER(et.command), + IF(e.animationId, 1, 0), + 0, -- cuFlags + etdT.text_loc0, etdT.text_loc2, etdT.text_loc3, etdT.text_loc4, etdT.text_loc6, etdT.text_loc8, + etdNT.text_loc0, etdNT.text_loc2, etdNT.text_loc3, etdNT.text_loc4, etdNT.text_loc6, etdNT.text_loc8, + etdS.text_loc0, etdS.text_loc2, etdS.text_loc3, etdS.text_loc4, etdS.text_loc6, etdS.text_loc8 + FROM + dbc_emotestext et + LEFT JOIN + dbc_emotes e ON e.id = et.emoteId + LEFT JOIN + dbc_emotestextdata etdT ON etdT.id = et.targetId + LEFT JOIN + dbc_emotestextdata etdNT ON etdNT.id = et.noTargetId + LEFT JOIN + dbc_emotestextdata etdS ON etdS.id = et.selfId' + ); + + if (!$_) + $allOK = false; + + // i have no idea, how the indexing in this file works. + // sometimes the \d+ after EMOTE is the emoteTextId, but not nearly often enough + $aliasses = []; + foreach ($locPath as $lId => $path) + foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) + if (preg_match('/^EMOTE(\d+)_CMD\d+\s=\s\"\/([^"]+)\";$/', $line, $m)) + $aliasses[$m[1]][] = [$lId, $m[2]]; + + + $emotes = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, cmd FROM ?_emotes'); + + foreach($emotes as $eId => $cmd) + { + foreach ($aliasses as $gsId => $data) + { + if (in_array($cmd, array_column($data, 1))) + { + foreach ($data as $d) + DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_aliasses VALUES (?d, ?d, ?) ON DUPLICATE KEY UPDATE locales = locales | ?d', $eId, (1 << $d[0]), strtolower($d[1]), (1 << $d[0])); + + break; + } } } - CLI::write('GlobalStrings.lua not found for selected locale '.CLI::bold(Util::$localeStrings[$lId]), CLI::LOG_WARN); - $allOK = false; + return $allOK; } - - $_= DB::Aowow()->query('REPLACE INTO ?_emotes SELECT - et.id, - LOWER(et.command), - IF(e.animationId, 1, 0), - 0, -- cuFlags - etdT.text_loc0, etdT.text_loc2, etdT.text_loc3, etdT.text_loc4, etdT.text_loc6, etdT.text_loc8, - etdNT.text_loc0, etdNT.text_loc2, etdNT.text_loc3, etdNT.text_loc4, etdNT.text_loc6, etdNT.text_loc8, - etdS.text_loc0, etdS.text_loc2, etdS.text_loc3, etdS.text_loc4, etdS.text_loc6, etdS.text_loc8 - FROM - dbc_emotestext et - LEFT JOIN - dbc_emotes e ON e.id = et.emoteId - LEFT JOIN - dbc_emotestextdata etdT ON etdT.id = et.targetId - LEFT JOIN - dbc_emotestextdata etdNT ON etdNT.id = et.noTargetId - LEFT JOIN - dbc_emotestextdata etdS ON etdS.id = et.selfId' - ); - - if (!$_) - $allOK = false; - - // i have no idea, how the indexing in this file works. - // sometimes the \d+ after EMOTE is the emoteTextId, but not nearly often enough - $aliasses = []; - foreach ($locPath as $lId => $path) - foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) - if (preg_match('/^EMOTE(\d+)_CMD\d+\s=\s\"\/([^"]+)\";$/', $line, $m)) - $aliasses[$m[1]][] = [$lId, $m[2]]; - - - $emotes = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, cmd FROM ?_emotes'); - - foreach($emotes as $eId => $cmd) - { - foreach ($aliasses as $gsId => $data) - { - if (in_array($cmd, array_column($data, 1))) - { - foreach ($data as $d) - DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_aliasses VALUES (?d, ?d, ?) ON DUPLICATE KEY UPDATE locales = locales | ?d', $eId, (1 << $d[0]), strtolower($d[1]), (1 << $d[0])); - - break; - } - } - } - - return $allOK; -} +}); ?> diff --git a/setup/tools/sqlgen/events.func.php b/setup/tools/sqlgen/events.func.php index f22eceb3..ab0c8a3d 100644 --- a/setup/tools/sqlgen/events.func.php +++ b/setup/tools/sqlgen/events.func.php @@ -7,46 +7,43 @@ if (!CLI) die('not in cli mode'); -/* deps: - * game_event - * game_event_prerequisite -*/ - -$customData = array( -); -$reqDBC = array( -); - -function events(array $ids = []) +SqlGen::register(new class extends SetupScript { - $eventQuery = ' - SELECT - ge.eventEntry, - holiday, - 0, -- cuFlags - IFNULL(UNIX_TIMESTAMP(start_time), 0), - IFNULL(UNIX_TIMESTAMP(end_time), 0), - occurence * 60, - length * 60, - IF (gep.eventEntry IS NOT NULL, GROUP_CONCAT(prerequisite_event SEPARATOR " "), NULL), - description - FROM - game_event ge - LEFT JOIN - game_event_prerequisite gep ON gep.eventEntry = ge.eventEntry - { - WHERE - ge.eventEntry IN (?a) - } - GROUP BY - ge.eventEntry'; + protected $command = 'events'; - $events = DB::World()->select($eventQuery, $ids ?: DBSIMPLE_SKIP); + protected $tblDependancyTC = ['game_event', 'game_event_prerequisite']; - foreach ($events as $e) - DB::Aowow()->query('REPLACE INTO ?_events VALUES (?a)', array_values($e)); + public function generate(array $ids = []) : bool + { + $eventQuery = ' + SELECT + ge.eventEntry, + holiday, + 0, -- cuFlags + IFNULL(UNIX_TIMESTAMP(start_time), 0), + IFNULL(UNIX_TIMESTAMP(end_time), 0), + occurence * 60, + length * 60, + IF (gep.eventEntry IS NOT NULL, GROUP_CONCAT(prerequisite_event SEPARATOR " "), NULL), + description + FROM + game_event ge + LEFT JOIN + game_event_prerequisite gep ON gep.eventEntry = ge.eventEntry + { + WHERE + ge.eventEntry IN (?a) + } + GROUP BY + ge.eventEntry'; - return true; -} + $events = DB::World()->select($eventQuery, $ids ?: DBSIMPLE_SKIP); + + foreach ($events as $e) + DB::Aowow()->query('REPLACE INTO ?_events VALUES (?a)', array_values($e)); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/factions.func.php b/setup/tools/sqlgen/factions.func.php index 52648017..d819abde 100644 --- a/setup/tools/sqlgen/factions.func.php +++ b/setup/tools/sqlgen/factions.func.php @@ -7,126 +7,134 @@ if (!CLI) die('not in cli mode'); -$customData = array( - 47 => ['qmNpcIds' => '33310'], - 68 => ['qmNpcIds' => '33555'], - 69 => ['qmNpcIds' => '33653'], - 72 => ['qmNpcIds' => '33307'], - 76 => ['qmNpcIds' => '33553'], - 81 => ['qmNpcIds' => '33556'], - 922 => ['qmNpcIds' => '16528'], - 930 => ['qmNpcIds' => '33657'], - 932 => ['qmNpcIds' => '19321'], - 933 => ['qmNpcIds' => '20242 23007'], - 935 => ['qmNpcIds' => '21432'], - 941 => ['qmNpcIds' => '20241'], - 942 => ['qmNpcIds' => '17904'], - 946 => ['qmNpcIds' => '17657'], - 947 => ['qmNpcIds' => '17585'], - 970 => ['qmNpcIds' => '18382'], - 978 => ['qmNpcIds' => '20240'], - 989 => ['qmNpcIds' => '21643'], - 1011 => ['qmNpcIds' => '21655'], - 1012 => ['qmNpcIds' => '23159'], - 1037 => ['qmNpcIds' => '32773 32564'], - 1038 => ['qmNpcIds' => '23428'], - 1052 => ['qmNpcIds' => '32774 32565'], - 1073 => ['qmNpcIds' => '31916 32763'], - 1090 => ['qmNpcIds' => '32287'], - 1091 => ['qmNpcIds' => '32533'], - 1094 => ['qmNpcIds' => '34881'], - 1105 => ['qmNpcIds' => '31910'], - 1106 => ['qmNpcIds' => '30431'], - 1119 => ['qmNpcIds' => '32540'], - 1124 => ['qmNpcIds' => '34772'], - 1156 => ['qmNpcIds' => '37687'], - 1082 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW], - 952 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW], -); -$reqDBC = ['faction', 'factiontemplate']; - -function factions() +SqlGen::register(new class extends SetupScript { - $factionQuery = ' - REPLACE INTO - ?_factions - SELECT - f.id, - f.repIdx, - baseRepRaceMask1, baseRepRaceMask2, baseRepRaceMask3, baseRepRaceMask4, - baseRepClassMask1, baseRepClassMask2, baseRepClassMask3, baseRepClassMask4, - baseRepValue1, baseRepValue2, baseRepValue3, baseRepValue4, - IF(SUM(ft.ourMask & 0x6) / COUNT(1) = 0x4, 2, IF(SUM(ft.ourMask & 0x6) / COUNT(1) = 0x2, 1, 0)) as side, - 0, -- expansion - "", -- quartermasterNpcIds - "", -- factionTemplateIds - 0, -- cuFlags - parentFaction, - spilloverRateIn, spilloverRateOut, spilloverMaxRank, - name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 - FROM - dbc_faction f - LEFT JOIN - dbc_factiontemplate ft ON ft.factionid = f.id - GROUP BY - f.id'; + use TrCustomData; - $templateQuery = ' - UPDATE - ?_factions f - JOIN - (SELECT ft.factionId, GROUP_CONCAT(ft.id SEPARATOR " ") AS tplIds FROM dbc_factiontemplate ft GROUP BY ft.factionId) temp ON f.id = temp.factionId - SET - f.templateIds = temp.tplIds'; + protected $command = 'factions'; - $recursiveUpdateQuery = ' - UPDATE - ?_factions top - JOIN - (SELECT id, parentFactionId FROM ?_factions) mid ON mid.parentFactionId IN (?a) - LEFT JOIN - (SELECT id, parentFactionId FROM ?_factions) low ON low.parentFactionId = mid.id - SET - ?a - WHERE - repIdx > 0 AND ( - top.id IN (?a) OR - top.id = mid.id OR - top.id = low.id - )'; + protected $dbcSourceFiles = ['faction', 'factiontemplate']; - $excludeQuery = ' - UPDATE - ?_factions x - JOIN - dbc_faction f ON f.id = x.id - LEFT JOIN - dbc_factiontemplate ft ON f.id = ft.factionId - SET - cuFlags = cuFlags | ?d - WHERE - f.repIdx < 0 OR - ( - f.repIdx > 0 AND - (f.repFlags1 & 0x8 OR ft.id IS NULL) AND - (f.repFlags1 & 0x80) = 0 - )'; - - $pairs = array( - [[980], ['expansion' => 1]], - [[1097], ['expansion' => 2]], - [[469, 891, 1037], ['side' => 1]], - [[ 67, 892, 1052], ['side' => 2]], + private $customData = array( + 47 => ['qmNpcIds' => '33310'], + 68 => ['qmNpcIds' => '33555'], + 69 => ['qmNpcIds' => '33653'], + 72 => ['qmNpcIds' => '33307'], + 76 => ['qmNpcIds' => '33553'], + 81 => ['qmNpcIds' => '33556'], + 922 => ['qmNpcIds' => '16528'], + 930 => ['qmNpcIds' => '33657'], + 932 => ['qmNpcIds' => '19321'], + 933 => ['qmNpcIds' => '20242 23007'], + 935 => ['qmNpcIds' => '21432'], + 941 => ['qmNpcIds' => '20241'], + 942 => ['qmNpcIds' => '17904'], + 946 => ['qmNpcIds' => '17657'], + 947 => ['qmNpcIds' => '17585'], + 970 => ['qmNpcIds' => '18382'], + 978 => ['qmNpcIds' => '20240'], + 989 => ['qmNpcIds' => '21643'], + 1011 => ['qmNpcIds' => '21655'], + 1012 => ['qmNpcIds' => '23159'], + 1037 => ['qmNpcIds' => '32773 32564'], + 1038 => ['qmNpcIds' => '23428'], + 1052 => ['qmNpcIds' => '32774 32565'], + 1073 => ['qmNpcIds' => '31916 32763'], + 1090 => ['qmNpcIds' => '32287'], + 1091 => ['qmNpcIds' => '32533'], + 1094 => ['qmNpcIds' => '34881'], + 1105 => ['qmNpcIds' => '31910'], + 1106 => ['qmNpcIds' => '30431'], + 1119 => ['qmNpcIds' => '32540'], + 1124 => ['qmNpcIds' => '34772'], + 1156 => ['qmNpcIds' => '37687'], + 1082 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW], + 952 => ['cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW], ); - DB::Aowow()->query($factionQuery); - DB::Aowow()->query($templateQuery); - DB::Aowow()->query($excludeQuery, CUSTOM_EXCLUDE_FOR_LISTVIEW); + public function generate(array $ids = []) : bool + { + $factionQuery = ' + REPLACE INTO + ?_factions + SELECT + f.id, + f.repIdx, + baseRepRaceMask1, baseRepRaceMask2, baseRepRaceMask3, baseRepRaceMask4, + baseRepClassMask1, baseRepClassMask2, baseRepClassMask3, baseRepClassMask4, + baseRepValue1, baseRepValue2, baseRepValue3, baseRepValue4, + IF(SUM(ft.ourMask & 0x6) / COUNT(1) = 0x4, 2, IF(SUM(ft.ourMask & 0x6) / COUNT(1) = 0x2, 1, 0)) as side, + 0, -- expansion + "", -- quartermasterNpcIds + "", -- factionTemplateIds + 0, -- cuFlags + parentFaction, + spilloverRateIn, spilloverRateOut, spilloverMaxRank, + name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 + FROM + dbc_faction f + LEFT JOIN + dbc_factiontemplate ft ON ft.factionid = f.id + GROUP BY + f.id'; - foreach ($pairs as $p) - DB::Aowow()->query($recursiveUpdateQuery, $p[0], $p[1], $p[0]); + $templateQuery = ' + UPDATE + ?_factions f + JOIN + (SELECT ft.factionId, GROUP_CONCAT(ft.id SEPARATOR " ") AS tplIds FROM dbc_factiontemplate ft GROUP BY ft.factionId) temp ON f.id = temp.factionId + SET + f.templateIds = temp.tplIds'; - return true; -} + $recursiveUpdateQuery = ' + UPDATE + ?_factions top + JOIN + (SELECT id, parentFactionId FROM ?_factions) mid ON mid.parentFactionId IN (?a) + LEFT JOIN + (SELECT id, parentFactionId FROM ?_factions) low ON low.parentFactionId = mid.id + SET + ?a + WHERE + repIdx > 0 AND ( + top.id IN (?a) OR + top.id = mid.id OR + top.id = low.id + )'; + + $excludeQuery = ' + UPDATE + ?_factions x + JOIN + dbc_faction f ON f.id = x.id + LEFT JOIN + dbc_factiontemplate ft ON f.id = ft.factionId + SET + cuFlags = cuFlags | ?d + WHERE + f.repIdx < 0 OR + ( + f.repIdx > 0 AND + (f.repFlags1 & 0x8 OR ft.id IS NULL) AND + (f.repFlags1 & 0x80) = 0 + )'; + + $pairs = array( + [[980], ['expansion' => 1]], + [[1097], ['expansion' => 2]], + [[469, 891, 1037], ['side' => 1]], + [[ 67, 892, 1052], ['side' => 2]], + ); + + DB::Aowow()->query($factionQuery); + DB::Aowow()->query($templateQuery); + DB::Aowow()->query($excludeQuery, CUSTOM_EXCLUDE_FOR_LISTVIEW); + + foreach ($pairs as $p) + DB::Aowow()->query($recursiveUpdateQuery, $p[0], $p[1], $p[0]); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/factiontemplate.func.php b/setup/tools/sqlgen/factiontemplate.func.php index 35f65986..04d251f9 100644 --- a/setup/tools/sqlgen/factiontemplate.func.php +++ b/setup/tools/sqlgen/factiontemplate.func.php @@ -7,32 +7,35 @@ if (!CLI) die('not in cli mode'); -$customData = array( -); -$reqDBC = ['factiontemplate']; - -function factiontemplate() +SqlGen::register(new class extends SetupScript { - $query = ' - REPLACE INTO - ?_factiontemplate - SELECT - id, - factionId, - IF(friendFactionId1 = 1 OR friendFactionId2 = 1 OR friendFactionId3 = 1 OR friendFactionId4 = 1 OR friendlyMask & 0x3, - 1, - IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 0) - ), - IF(friendFactionId1 = 2 OR friendFactionId2 = 2 OR friendFactionId3 = 2 OR friendFactionId4 = 2 OR friendlyMask & 0x5, - 1, - IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 0) - ) - FROM - dbc_factiontemplate'; + protected $command = 'factiontemplate'; - DB::Aowow()->query($query); + protected $dbcSourceFiles = ['factiontemplate']; - return true; -} + public function generate(array $ids = []) : bool + { + $query = ' + REPLACE INTO + ?_factiontemplate + SELECT + id, + factionId, + IF(friendFactionId1 = 1 OR friendFactionId2 = 1 OR friendFactionId3 = 1 OR friendFactionId4 = 1 OR friendlyMask & 0x3, + 1, + IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 0) + ), + IF(friendFactionId1 = 2 OR friendFactionId2 = 2 OR friendFactionId3 = 2 OR friendFactionId4 = 2 OR friendlyMask & 0x5, + 1, + IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 0) + ) + FROM + dbc_factiontemplate'; + + DB::Aowow()->query($query); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/glyphproperties.func.php b/setup/tools/sqlgen/glyphproperties.func.php index 748a3e39..69a4103f 100644 --- a/setup/tools/sqlgen/glyphproperties.func.php +++ b/setup/tools/sqlgen/glyphproperties.func.php @@ -6,15 +6,22 @@ if (!defined('AOWOW_REVISION')) if (!CLI) die('not in cli mode'); -$reqDBC = ['glyphproperties', 'spellicon']; -function glyphproperties() +SqlGen::register(new class extends SetupScript { - DB::Aowow()->query('REPLACE INTO ?_glyphproperties SELECT id, spellId, typeFlags, 0, iconId FROM dbc_glyphproperties'); + protected $command = 'glyphproperties'; - DB::Aowow()->query('UPDATE ?_glyphproperties gp, ?_icons ic, dbc_spellicon si SET gp.iconId = ic.id WHERE gp.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1))'); + protected $tblDependancyAowow = ['icons']; + protected $dbcSourceFiles = ['glyphproperties', 'spellicon']; - return true; -} + public function generate(array $ids = []) : bool + { + DB::Aowow()->query('REPLACE INTO ?_glyphproperties SELECT id, spellId, typeFlags, 0, iconId FROM dbc_glyphproperties'); + + DB::Aowow()->query('UPDATE ?_glyphproperties gp, ?_icons ic, dbc_spellicon si SET gp.iconId = ic.id WHERE gp.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1))'); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/holidays.func.php b/setup/tools/sqlgen/holidays.func.php index 0790ae76..6e5d6080 100644 --- a/setup/tools/sqlgen/holidays.func.php +++ b/setup/tools/sqlgen/holidays.func.php @@ -7,53 +7,62 @@ if (!CLI) die('not in cli mode'); -$customData = array( - 62 => ['iconString' => 'inv_misc_missilelarge_red' ], - 141 => ['iconString' => 'calendar_winterveilstart', 'achievementCatOrId' => 156 ], - 181 => ['iconString' => 'calendar_noblegardenstart', 'achievementCatOrId' => 159 ], - 201 => ['iconString' => 'calendar_childrensweekstart', 'achievementCatOrId' => 163 ], - 283 => ['iconString' => 'inv_jewelry_necklace_21' ], - 284 => ['iconString' => 'inv_misc_rune_07' ], - 285 => ['iconString' => 'inv_jewelry_amulet_07' ], - 301 => ['iconString' => 'calendar_fishingextravaganzastart' ], - 321 => ['iconString' => 'calendar_harvestfestivalstart' ], - 324 => ['iconString' => 'calendar_hallowsendstart', 'bossCreature' => 23682, 'achievementCatOrId' => 158 ], - 327 => ['iconString' => 'calendar_lunarfestivalstart', 'bossCreature' => 15467, 'achievementCatOrId' => 160 ], - 335 => ['iconString' => 'calendar_loveintheairstart' ], - 341 => ['iconString' => 'calendar_midsummerstart', 'bossCreature' => 25740, 'achievementCatOrId' => 161 ], - 353 => ['iconString' => 'spell_nature_eyeofthestorm' ], - 372 => ['iconString' => 'calendar_brewfeststart', 'bossCreature' => 23872, 'achievementCatOrId' => 162 ], - 374 => ['iconString' => 'calendar_darkmoonfaireelwynnstart' ], - 375 => ['iconString' => 'calendar_darkmoonfairemulgorestart' ], - 376 => ['iconString' => 'calendar_darkmoonfaireterokkarstart' ], - 398 => ['iconString' => 'calendar_piratesdaystart', 'achievementCatOrId' => -3457], - 400 => ['iconString' => 'achievement_bg_winsoa' ], - 404 => ['iconString' => 'calendar_harvestfestivalstart', 'achievementCatOrId' => 14981], - 406 => ['iconString' => 'achievement_boss_lichking' ], - 409 => ['iconString' => 'calendar_dayofthedeadstart', 'achievementCatOrId' => -3456], - 420 => ['iconString' => 'achievement_bg_winwsg' ], - 423 => ['iconString' => 'calendar_loveintheairstart', 'bossCreature' => 36296, 'achievementCatOrId' => 187 ], - 424 => ['iconString' => 'calendar_fishingextravaganzastart' ], -); -$reqDBC = ['holidays', 'holidaydescriptions', 'holidaynames']; -function holidays() +SqlGen::register(new class extends SetupScript { - $query = ' - REPLACE INTO - ?_holidays (id, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, description_loc0, description_loc2, description_loc3, description_loc4, description_loc6, description_loc8, looping, scheduleType, textureString) - SELECT - h.id, n.name_loc0, n.name_loc2, n.name_loc3, n.name_loc4, n.name_loc6, n.name_loc8, d.description_loc0, d.description_loc2, d.description_loc3, d.description_loc4, d.description_loc6, d.description_loc8, h.looping, h.scheduleType, h.textureString - FROM - dbc_holidays h - LEFT JOIN - dbc_holidaynames n ON n.id = h.nameId - LEFT JOIN - dbc_holidaydescriptions d ON d.id = h.descriptionId'; + use TrCustomData; - DB::Aowow()->query($query); + protected $command = 'holidays'; - return true; -} + protected $dbcSourceFiles = ['holidays', 'holidaydescriptions', 'holidaynames']; + + private $customData = array( + 62 => ['iconString' => 'inv_misc_missilelarge_red' ], + 141 => ['iconString' => 'calendar_winterveilstart', 'achievementCatOrId' => 156 ], + 181 => ['iconString' => 'calendar_noblegardenstart', 'achievementCatOrId' => 159 ], + 201 => ['iconString' => 'calendar_childrensweekstart', 'achievementCatOrId' => 163 ], + 283 => ['iconString' => 'inv_jewelry_necklace_21' ], + 284 => ['iconString' => 'inv_misc_rune_07' ], + 285 => ['iconString' => 'inv_jewelry_amulet_07' ], + 301 => ['iconString' => 'calendar_fishingextravaganzastart' ], + 321 => ['iconString' => 'calendar_harvestfestivalstart' ], + 324 => ['iconString' => 'calendar_hallowsendstart', 'bossCreature' => 23682, 'achievementCatOrId' => 158 ], + 327 => ['iconString' => 'calendar_lunarfestivalstart', 'bossCreature' => 15467, 'achievementCatOrId' => 160 ], + 335 => ['iconString' => 'calendar_loveintheairstart' ], + 341 => ['iconString' => 'calendar_midsummerstart', 'bossCreature' => 25740, 'achievementCatOrId' => 161 ], + 353 => ['iconString' => 'spell_nature_eyeofthestorm' ], + 372 => ['iconString' => 'calendar_brewfeststart', 'bossCreature' => 23872, 'achievementCatOrId' => 162 ], + 374 => ['iconString' => 'calendar_darkmoonfaireelwynnstart' ], + 375 => ['iconString' => 'calendar_darkmoonfairemulgorestart' ], + 376 => ['iconString' => 'calendar_darkmoonfaireterokkarstart' ], + 398 => ['iconString' => 'calendar_piratesdaystart', 'achievementCatOrId' => -3457], + 400 => ['iconString' => 'achievement_bg_winsoa' ], + 404 => ['iconString' => 'calendar_harvestfestivalstart', 'achievementCatOrId' => 14981], + 406 => ['iconString' => 'achievement_boss_lichking' ], + 409 => ['iconString' => 'calendar_dayofthedeadstart', 'achievementCatOrId' => -3456], + 420 => ['iconString' => 'achievement_bg_winwsg' ], + 423 => ['iconString' => 'calendar_loveintheairstart', 'bossCreature' => 36296, 'achievementCatOrId' => 187 ], + 424 => ['iconString' => 'calendar_fishingextravaganzastart' ], + ); + + public function generate(array $ids = []) : bool + { + $query = ' + REPLACE INTO + ?_holidays (id, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, description_loc0, description_loc2, description_loc3, description_loc4, description_loc6, description_loc8, looping, scheduleType, textureString) + SELECT + h.id, n.name_loc0, n.name_loc2, n.name_loc3, n.name_loc4, n.name_loc6, n.name_loc8, d.description_loc0, d.description_loc2, d.description_loc3, d.description_loc4, d.description_loc6, d.description_loc8, h.looping, h.scheduleType, h.textureString + FROM + dbc_holidays h + LEFT JOIN + dbc_holidaynames n ON n.id = h.nameId + LEFT JOIN + dbc_holidaydescriptions d ON d.id = h.descriptionId'; + + DB::Aowow()->query($query); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/icons.func.php b/setup/tools/sqlgen/icons.func.php index 400583f8..91468e88 100644 --- a/setup/tools/sqlgen/icons.func.php +++ b/setup/tools/sqlgen/icons.func.php @@ -7,32 +7,35 @@ if (!CLI) die('not in cli mode'); -$customData = array( -); -$reqDBC = ['spellicon', 'itemdisplayinfo', 'creaturefamily']; - -function icons() +SqlGen::register(new class extends SetupScript { - DB::Aowow()->query('TRUNCATE ?_icons'); - DB::Aowow()->query('ALTER TABLE ?_icons AUTO_INCREMENT = 1'); + protected $command = 'icons'; - $baseQuery = ' - INSERT INTO ?_icons (`name`) SELECT x FROM - ( - (SELECT LOWER(SUBSTRING_INDEX(iconPath, "\\\\", -1)) AS x FROM dbc_spellicon WHERE iconPath LIKE "%icons%") - UNION - (SELECT LOWER(inventoryIcon1) AS x FROM dbc_itemdisplayinfo WHERE inventoryIcon1 <> "") - UNION - (SELECT LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS x FROM dbc_creaturefamily WHERE iconString LIKE "%icons%") - ) y - GROUP BY - x - ORDER BY - x ASC'; + protected $dbcSourceFiles = ['spellicon', 'itemdisplayinfo', 'creaturefamily']; - DB::Aowow()->query($baseQuery); + public function generate(array $ids = []) : bool + { + DB::Aowow()->query('TRUNCATE ?_icons'); + DB::Aowow()->query('ALTER TABLE ?_icons AUTO_INCREMENT = 1'); - return true; -} + $baseQuery = ' + INSERT INTO ?_icons (`name`) SELECT x FROM + ( + (SELECT LOWER(SUBSTRING_INDEX(iconPath, "\\\\", -1)) AS x FROM dbc_spellicon WHERE iconPath LIKE "%icons%") + UNION + (SELECT LOWER(inventoryIcon1) AS x FROM dbc_itemdisplayinfo WHERE inventoryIcon1 <> "") + UNION + (SELECT LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS x FROM dbc_creaturefamily WHERE iconString LIKE "%icons%") + ) y + GROUP BY + x + ORDER BY + x ASC'; + + DB::Aowow()->query($baseQuery); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/item_stats.func.php b/setup/tools/sqlgen/item_stats.func.php index c1f86f8d..3ba46a60 100644 --- a/setup/tools/sqlgen/item_stats.func.php +++ b/setup/tools/sqlgen/item_stats.func.php @@ -7,16 +7,6 @@ if (!CLI) die('not in cli mode'); -/* deps: - * ?_items finalized - * ?_spell finalized - * dbc_spellitemenchantment -*/ - -$customData = array( -); -$reqDBC = ['spellitemenchantment']; - class ItemStatSetup extends ItemList { private $statCols = []; @@ -138,140 +128,148 @@ class ItemStatSetup extends ItemList } } -function item_stats(array $ids = []) +SqlGen::register(new class extends SetupScript { - $offset = 0; + protected $command = 'item_stats'; // and enchantment stats - CLI::write(' - applying stats for enchantments'); - $enchStats = enchantment_stats(); - CLI::write(' '.count($enchStats).' enchantments parsed'); - CLI::write(' - applying stats for items'); + protected $tblDependancyAowow = ['items', 'spell']; + protected $dbcSourceFiles = ['spellitemenchantment']; - while (true) + private function enchantment_stats() : array { - $items = new ItemStatSetup($offset, SqlGen::$stepSize, $ids, $enchStats); - if ($items->error) - break; + $statCols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_NAME` LIKE "%item_stats"'); + $enchants = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_spellitemenchantment'); + $spells = []; + $spellStats = []; - $max = max($items->getFoundIDs()); - $num = count($items->getFoundIDs()); - - CLI::write(' * sets '.($offset + 1).' - '.($max)); - - $offset = $max; - - $items->writeStatsTable(); - } - - return true; -} - -function enchantment_stats() -{ - $statCols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_NAME` LIKE "%item_stats"'); - $enchants = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_spellitemenchantment'); - $spells = []; - $spellStats = []; - - foreach ($enchants as $eId => $e) - { - for ($i = 1; $i <=3; $i++) + foreach ($enchants as $eId => $e) { - // trigger: onEquip + valid SpellId - if ($e['object'.$i] > 0 && $e['type'.$i] == 3) - $spells[] = $e['object'.$i]; - } - } - - if ($spells) - $spellStats = (new SpellList(array(['id', $spells], CFG_SQL_LIMIT_NONE)))->getStatGain(); - - $result = []; - foreach ($enchants as $eId => $e) - { - // parse stats - $result[$eId] = []; - for ($h = 1; $h <= 3; $h++) - { - $obj = (int)$e['object'.$h]; - $val = (int)$e['amount'.$h]; - - switch ($e['type'.$h]) + for ($i = 1; $i <=3; $i++) { - case 6: // TYPE_TOTEM +AmountX as DPS (Rockbiter) - $result[$eId]['dps'] = $val; // we do not use dps as itemMod, so apply it directly - $obj = null; - break; - case 2: // TYPE_DAMAGE +AmountX damage - $obj = ITEM_MOD_WEAPON_DMG; - break; - // case 1: // TYPE_COMBAT_SPELL proc spell from ObjectX (amountX == procChance) - // case 7: // TYPE_USE_SPELL Engineering gadgets - case 3: // TYPE_EQUIP_SPELL Spells from ObjectX (use of amountX?) - if (!empty($spellStats[$obj])) - foreach ($spellStats[$obj] as $mod => $val) - if ($str = Game::$itemMods[$mod]) - Util::arraySumByKey($result[$eId], [$str => $val]); + // trigger: onEquip + valid SpellId + if ($e['object'.$i] > 0 && $e['type'.$i] == 3) + $spells[] = $e['object'.$i]; + } + } - $obj = null; - break; - case 4: // TYPE_RESISTANCE +AmountX resistance for ObjectX School - switch ($obj) - { - case 0: // Physical - $obj = ITEM_MOD_ARMOR; - break; - case 1: // Holy - $obj = ITEM_MOD_HOLY_RESISTANCE; - break; - case 2: // Fire - $obj = ITEM_MOD_FIRE_RESISTANCE; - break; - case 3: // Nature - $obj = ITEM_MOD_NATURE_RESISTANCE; - break; - case 4: // Frost - $obj = ITEM_MOD_FROST_RESISTANCE; - break; - case 5: // Shadow - $obj = ITEM_MOD_SHADOW_RESISTANCE; - break; - case 6: // Arcane - $obj = ITEM_MOD_ARCANE_RESISTANCE; - break; - default: - $obj = null; - } - break; - case 5: // TYPE_STAT +AmountX for Statistic by type of ObjectX - if ($obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] .. - $obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere + if ($spells) + $spellStats = (new SpellList(array(['id', $spells], CFG_SQL_LIMIT_NONE)))->getStatGain(); - break; // stats are directly assigned below - case 8: // TYPE_PRISMATIC_SOCKET Extra Sockets AmountX as socketCount (ignore) - $result[$eId]['nsockets'] = $val; // there is no itemmod for sockets, so apply it directly - default: // TYPE_NONE dnd stuff; skip assignment below - $obj = null; + $result = []; + foreach ($enchants as $eId => $e) + { + // parse stats + $result[$eId] = []; + for ($h = 1; $h <= 3; $h++) + { + $obj = (int)$e['object'.$h]; + $val = (int)$e['amount'.$h]; + + switch ($e['type'.$h]) + { + case 6: // TYPE_TOTEM +AmountX as DPS (Rockbiter) + $result[$eId]['dps'] = $val; // we do not use dps as itemMod, so apply it directly + $obj = null; + break; + case 2: // TYPE_DAMAGE +AmountX damage + $obj = ITEM_MOD_WEAPON_DMG; + break; + // case 1: // TYPE_COMBAT_SPELL proc spell from ObjectX (amountX == procChance) + // case 7: // TYPE_USE_SPELL Engineering gadgets + case 3: // TYPE_EQUIP_SPELL Spells from ObjectX (use of amountX?) + if (!empty($spellStats[$obj])) + foreach ($spellStats[$obj] as $mod => $val) + if ($str = Game::$itemMods[$mod]) + Util::arraySumByKey($result[$eId], [$str => $val]); + + $obj = null; + break; + case 4: // TYPE_RESISTANCE +AmountX resistance for ObjectX School + switch ($obj) + { + case 0: // Physical + $obj = ITEM_MOD_ARMOR; + break; + case 1: // Holy + $obj = ITEM_MOD_HOLY_RESISTANCE; + break; + case 2: // Fire + $obj = ITEM_MOD_FIRE_RESISTANCE; + break; + case 3: // Nature + $obj = ITEM_MOD_NATURE_RESISTANCE; + break; + case 4: // Frost + $obj = ITEM_MOD_FROST_RESISTANCE; + break; + case 5: // Shadow + $obj = ITEM_MOD_SHADOW_RESISTANCE; + break; + case 6: // Arcane + $obj = ITEM_MOD_ARCANE_RESISTANCE; + break; + default: + $obj = null; + } + break; + case 5: // TYPE_STAT +AmountX for Statistic by type of ObjectX + if ($obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] .. + $obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere + + break; // stats are directly assigned below + case 8: // TYPE_PRISMATIC_SOCKET Extra Sockets AmountX as socketCount (ignore) + $result[$eId]['nsockets'] = $val; // there is no itemmod for sockets, so apply it directly + default: // TYPE_NONE dnd stuff; skip assignment below + $obj = null; + } + + if ($obj !== null) + if ($str = Game::$itemMods[$obj]) // check if we use these mods + Util::arraySumByKey($result[$eId], [$str => $val]); } - if ($obj !== null) - if ($str = Game::$itemMods[$obj]) // check if we use these mods - Util::arraySumByKey($result[$eId], [$str => $val]); + $updateCols = ['type' => TYPE_ENCHANTMENT, 'typeId' => $eId]; + foreach ($result[$eId] as $k => $v) + { + if (!in_array($k, $statCols) || !$v || $k == 'id') + continue; + + $updateCols[$k] = number_format($v, 2, '.', ''); + } + + DB::Aowow()->query('REPLACE INTO ?_item_stats (?#) VALUES (?a)', array_keys($updateCols), array_values($updateCols)); } - $updateCols = ['type' => TYPE_ENCHANTMENT, 'typeId' => $eId]; - foreach ($result[$eId] as $k => $v) - { - if (!in_array($k, $statCols) || !$v || $k == 'id') - continue; - - $updateCols[$k] = number_format($v, 2, '.', ''); - } - - DB::Aowow()->query('REPLACE INTO ?_item_stats (?#) VALUES (?a)', array_keys($updateCols), array_values($updateCols)); + return $result; } - return $result; -} + public function generate(array $ids = []) : bool + { + $offset = 0; + + CLI::write(' - applying stats for enchantments'); + $enchStats = enchantment_stats(); + CLI::write(' '.count($enchStats).' enchantments parsed'); + CLI::write(' - applying stats for items'); + + while (true) + { + $items = new ItemStatSetup($offset, SqlGen::$sqlBatchSize, $ids, $enchStats); + if ($items->error) + break; + + $max = max($items->getFoundIDs()); + $num = count($items->getFoundIDs()); + + CLI::write(' * sets '.($offset + 1).' - '.($max)); + + $offset = $max; + + $items->writeStatsTable(); + } + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/itemenchantment.func.php b/setup/tools/sqlgen/itemenchantment.func.php index fd5e1e0f..a36d9ebf 100644 --- a/setup/tools/sqlgen/itemenchantment.func.php +++ b/setup/tools/sqlgen/itemenchantment.func.php @@ -7,31 +7,35 @@ if (!CLI) die('not in cli mode'); -$customData = array( -); -$reqDBC = ['spellitemenchantment']; - -function itemenchantment() +SqlGen::register(new class extends SetupScript { - $baseQuery = ' - REPLACE INTO - ?_itemenchantment - SELECT - Id, charges, 0, 0, 0, type1, type2, type3, amount1, amount2, amount3, object1, object2, object3, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, conditionId, skillLine, skillLevel, requiredLevel - FROM - dbc_spellitemenchantment'; + protected $command = 'itemenchantment'; - DB::Aowow()->query($baseQuery); + protected $tblDependancyTC = ['spell_enchant_proc_data']; + protected $dbcSourceFiles = ['spellitemenchantment']; - $cuProcs = DB::World()->select('SELECT EnchantID AS ARRAY_KEY, Chance AS procChance, ProcsPerMinute AS ppmRate FROM spell_enchant_proc_data'); - foreach ($cuProcs as $id => $vals) - DB::Aowow()->query('UPDATE ?_itemenchantment SET ?a WHERE id = ?d', $vals, $id); + public function generate(array $ids = []) : bool + { + $baseQuery = ' + REPLACE INTO + ?_itemenchantment + SELECT + Id, charges, 0, 0, 0, type1, type2, type3, amount1, amount2, amount3, object1, object2, object3, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, conditionId, skillLine, skillLevel, requiredLevel + FROM + dbc_spellitemenchantment'; - // hide strange stuff - DB::Aowow()->query('UPDATE ?_itemenchantment SET cuFlags = ?d WHERE type1 = 0 AND type2 = 0 AND type3 = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW); - DB::Aowow()->query('UPDATE ?_itemenchantment SET cuFlags = ?d WHERE name_loc0 LIKE "%test%"', CUSTOM_EXCLUDE_FOR_LISTVIEW); + DB::Aowow()->query($baseQuery); - return true; -} + $cuProcs = DB::World()->select('SELECT EnchantID AS ARRAY_KEY, Chance AS procChance, ProcsPerMinute AS ppmRate FROM spell_enchant_proc_data'); + foreach ($cuProcs as $id => $vals) + DB::Aowow()->query('UPDATE ?_itemenchantment SET ?a WHERE id = ?d', $vals, $id); + + // hide strange stuff + DB::Aowow()->query('UPDATE ?_itemenchantment SET cuFlags = ?d WHERE type1 = 0 AND type2 = 0 AND type3 = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW); + DB::Aowow()->query('UPDATE ?_itemenchantment SET cuFlags = ?d WHERE name_loc0 LIKE "%test%"', CUSTOM_EXCLUDE_FOR_LISTVIEW); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/itemenchantmentcondition.func.php b/setup/tools/sqlgen/itemenchantmentcondition.func.php new file mode 100644 index 00000000..5a8773ac --- /dev/null +++ b/setup/tools/sqlgen/itemenchantmentcondition.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/itemextendedcost.func.php b/setup/tools/sqlgen/itemextendedcost.func.php new file mode 100644 index 00000000..97e1548c --- /dev/null +++ b/setup/tools/sqlgen/itemextendedcost.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/itemlimitcategory.func.php b/setup/tools/sqlgen/itemlimitcategory.func.php new file mode 100644 index 00000000..78f27d9d --- /dev/null +++ b/setup/tools/sqlgen/itemlimitcategory.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/itemrandomenchant.func.php b/setup/tools/sqlgen/itemrandomenchant.func.php index 63c1c3b1..c310bb7b 100644 --- a/setup/tools/sqlgen/itemrandomenchant.func.php +++ b/setup/tools/sqlgen/itemrandomenchant.func.php @@ -7,21 +7,24 @@ if (!CLI) die('not in cli mode'); -$customData = array( -); -$reqDBC = ['itemrandomsuffix', 'itemrandomproperties']; - -function itemrandomenchant() +SqlGen::register(new class extends SetupScript { - $query = ' - REPLACE INTO ?_itemrandomenchant - SELECT -id, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, nameINT, enchantId1, enchantId2, enchantId3, enchantId4, enchantId5, allocationPct1, allocationPct2, allocationPct3, allocationPct4, allocationPct5 FROM dbc_itemrandomsuffix - UNION - SELECT id, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, nameINT, enchantId1, enchantId2, enchantId3, enchantId4, enchantId5, 0, 0, 0, 0, 0 FROM dbc_itemrandomproperties'; + protected $command = 'itemrandomenchant'; - DB::Aowow()->query($query); + protected $dbcSourceFiles = ['itemrandomsuffix', 'itemrandomproperties']; - return true; -} + public function generate(array $ids = []) : bool + { + $query = ' + REPLACE INTO ?_itemrandomenchant + SELECT -id, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, nameINT, enchantId1, enchantId2, enchantId3, enchantId4, enchantId5, allocationPct1, allocationPct2, allocationPct3, allocationPct4, allocationPct5 FROM dbc_itemrandomsuffix + UNION + SELECT id, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, nameINT, enchantId1, enchantId2, enchantId3, enchantId4, enchantId5, 0, 0, 0, 0, 0 FROM dbc_itemrandomproperties'; + + DB::Aowow()->query($query); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/itemrandomproppoints.func.php b/setup/tools/sqlgen/itemrandomproppoints.func.php new file mode 100644 index 00000000..29ff91bb --- /dev/null +++ b/setup/tools/sqlgen/itemrandomproppoints.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/items.func.php b/setup/tools/sqlgen/items.func.php index 5ef7d702..aff091e6 100644 --- a/setup/tools/sqlgen/items.func.php +++ b/setup/tools/sqlgen/items.func.php @@ -7,252 +7,254 @@ if (!CLI) die('not in cli mode'); -/* deps: - * item_template - * item_template_locale - * spell_group - * game_event -*/ - -$customData = array( - 33147 => ['class' => 9, 'subClass' => 8], // one stray enchanting recipe .. with a strange icon - 7948 => ['itemset' => 221], // v unsure if this should be fixed v - 7949 => ['itemset' => 221], - 7950 => ['itemset' => 221], - 7951 => ['itemset' => 221], - 7952 => ['itemset' => 221], - 7953 => ['itemset' => 221] -); - -$reqDBC = ['gemproperties', 'itemdisplayinfo', 'spell', 'glyphproperties', 'durabilityquality', 'durabilitycosts']; - -function items(array $ids = []) +SqlGen::register(new class extends SetupScript { - $baseQuery = ' - SELECT - it.entry, - class, class as classBak, - subclass, subclass AS subClassBak, - SoundOverrideSubclass, - IFNULL(sg.id, 0) AS subSubClass, - it.name, IFNULL(itl2.Name, ""), IFNULL(itl3.Name, ""), IFNULL(itl4.Name, ""), IFNULL(itl6.Name, ""), IFNULL(itl8.Name, ""), - 0 AS iconId, - displayid, - 0 AS spellVisualId, - Quality, - Flags, FlagsExtra, - BuyCount, BuyPrice, SellPrice, - 0 AS repairPrice, - InventoryType AS slot, InventoryType AS slotBak, - AllowableClass, AllowableRace, - ItemLevel, - RequiredLevel, - RequiredSkill, RequiredSkillRank, - requiredspell, - requiredhonorrank, - RequiredCityRank, - RequiredReputationFaction, - RequiredReputationRank, - maxcount, - 0 AS cuFlags, - 0 AS model, - stackable, - ContainerSlots, - stat_type1, stat_value1, - stat_type2, stat_value2, - stat_type3, stat_value3, - stat_type4, stat_value4, - stat_type5, stat_value5, - stat_type6, stat_value6, - stat_type7, stat_value7, - stat_type8, stat_value8, - stat_type9, stat_value9, - stat_type10, stat_value10, - ScalingStatDistribution, - ScalingStatValue, - dmg_min1, dmg_max1, dmg_type1, - dmg_min2, dmg_max2, dmg_type2, - delay, - armor, ArmorDamageModifier, - block, - holy_res, fire_res, nature_res, frost_res, shadow_res, arcane_res, - ammo_type, - RangedModRange, - spellid_1, spelltrigger_1, spellcharges_1, spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, - spellid_2, spelltrigger_2, spellcharges_2, spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, - spellid_3, spelltrigger_3, spellcharges_3, spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, - spellid_4, spelltrigger_4, spellcharges_4, spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, - spellid_5, spelltrigger_5, spellcharges_5, spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, - bonding, - it.description, IFNULL(itl2.Description, ""), IFNULL(itl3.Description, ""), IFNULL(itl4.Description, ""), IFNULL(itl6.Description, ""), IFNULL(itl8.Description, ""), - PageText, - LanguageID, - startquest, - lockid, - Material, - IF(RandomProperty > 0, RandomProperty, -RandomSuffix) AS randomEnchant, - itemset, - MaxDurability, - area, - Map, - BagFamily, - TotemCategory, - socketColor_1, socketContent_1, - socketColor_2, socketContent_2, - socketColor_3, socketContent_3, - socketBonus, - GemProperties, - RequiredDisenchantSkill, - DisenchantID, - duration, - ItemLimitCategory, - IFNULL(ge.eventEntry, 0), - ScriptName, - FoodType, - 0 AS gemEnchantmentId, - minMoneyLoot, maxMoneyLoot, - 0 AS pickUpSoundId, - 0 AS dropDownSoundId, - 0 AS sheatheSoundId, - 0 AS unsheatheSoundId, - flagsCustom - FROM - item_template it - LEFT JOIN - item_template_locale itl2 ON it.entry = itl2.ID AND itl2.locale = "frFR" - LEFT JOIN - item_template_locale itl3 ON it.entry = itl3.ID AND itl3.locale = "deDE" - LEFT JOIN - item_template_locale itl4 ON it.entry = itl4.ID AND itl4.locale = "zhCN" - LEFT JOIN - item_template_locale itl6 ON it.entry = itl6.ID AND itl6.locale = "esES" - LEFT JOIN - item_template_locale itl8 ON it.entry = itl8.ID AND itl8.locale = "ruRU" - LEFT JOIN - spell_group sg ON sg.spell_id = it.spellid_1 AND it.class = 0 AND it.subclass = 2 AND sg.id IN (1, 2) - LEFT JOIN - game_event ge ON ge.holiday = it.HolidayId AND it.HolidayId > 0 - WHERE - it.entry > ?d - { - AND it.entry IN (?a) - } - ORDER BY - it.entry ASC - LIMIT - ?d'; + use TrCustomData; - $lastMax = 0; - while ($items = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$stepSize)) - { - $newMax = max(array_column($items, 'entry')); + protected $command = 'items'; - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + protected $tblDependancyAowow = ['icons']; + protected $tblDependancyTC = ['item_template', 'item_template_locale', 'spell_group', 'game_event']; + protected $dbcSourceFiles = ['gemproperties', 'itemdisplayinfo', 'spell', 'glyphproperties', 'durabilityquality', 'durabilitycosts']; - $lastMax = $newMax; + private $customData = array( + 33147 => ['class' => 9, 'subClass' => 8], // one stray enchanting recipe .. with a strange icon + 7948 => ['itemset' => 221], // v unsure if this should be fixed v + 7949 => ['itemset' => 221], + 7950 => ['itemset' => 221], + 7951 => ['itemset' => 221], + 7952 => ['itemset' => 221], + 7953 => ['itemset' => 221] + ); - foreach ($items as $item) - DB::Aowow()->query('REPLACE INTO ?_items VALUES (?a)', array_values($item)); - } - - - // merge with gemProperties - DB::Aowow()->query('UPDATE ?_items i, dbc_gemproperties gp SET i.gemEnchantmentId = gp.enchantmentId, i.gemColorMask = gp.colorMask WHERE i.gemColorMask = gp.id'); - - // get modelString - DB::Aowow()->query('UPDATE ?_items i, dbc_itemdisplayinfo idi SET i.model = IF(idi.leftModelName = "", idi.rightModelName, idi.leftModelName) WHERE i.displayId = idi.id'); - - // get iconId - DB::Aowow()->query('UPDATE ?_items i, dbc_itemdisplayinfo idi, ?_icons ic SET i.iconId = ic.id WHERE i.displayId = idi.id AND LOWER(idi.inventoryIcon1) = ic.name'); - - // unify slots: Robes => Chest; Ranged (right) => Ranged - DB::Aowow()->query('UPDATE ?_items SET slot = 15 WHERE slotbak = 26'); - DB::Aowow()->query('UPDATE ?_items SET slot = 5 WHERE slotbak = 20'); - - // custom sub-classes - DB::Aowow()->query(' - UPDATE ?_items SET subclass = IF( - slotbak = 4, -8, IF( -- shirt - slotbak = 19, -7, IF( -- tabard - slotbak = 16, -6, IF( -- cloak - slotbak = 23, -5, IF( -- held in offhand - slotbak = 12, -4, IF( -- trinket - slotbak = 2, -3, IF( -- amulet - slotbak = 11, -2, subClassBak -- ring - ))))))) WHERE class = 4'); - - // move alchemist stones to trinkets (Armor) - DB::Aowow()->query('UPDATE ?_items SET class = 4, subClass = -4 WHERE classBak = 7 AND subClassBak = 11 AND slotBak = 12'); - - // mark keys as key (if not quest items) - DB::Aowow()->query('UPDATE ?_items SET class = 13, subClass = 0 WHERE classBak IN (0, 15) AND bagFamily & 0x100'); - - // set subSubClass for Glyphs (major/minor) - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s, dbc_glyphproperties gp SET i.subSubClass = IF(gp.typeFlags & 0x1, 2, 1) WHERE i.spellId1 = s.id AND s.effect1MiscValue = gp.id AND i.classBak = 16'); - - // filter misc(class:15) junk(subclass:0) to appropriate categories - - // assign pets and mounts to category - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET subClass = IF(effect1AuraId <> 78, 2, IF(effect2AuraId = 207 OR effect3AuraId = 207 OR (s.id <> 65917 AND effect2AuraId = 4 AND effect3Id = 77), -7, 5)) WHERE s.id = spellId2 AND class = 15 AND spellId1 IN (483, 55884)'); - - // more corner cases (mounts that are not actualy learned) - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = -7 WHERE (effect1Id = 64 OR (effect1AuraId = 78 AND effect2AuraId = 4 AND effect3Id = 77) OR effect1AuraId = 207 OR effect2AuraId = 207 OR effect3AuraId = 207) AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 5'); - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = 5 WHERE s.effect1AuraId = 78 AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 0'); - - // move some permanent enchantments to own category - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.class = 0, i.subClass = 6 WHERE s.effect1Id = 53 AND s.id = i.spellId1 AND i.class = 15'); - - // move temporary enchantments to own category - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = -3 WHERE s.effect1Id = 54 AND s.id = i.spellId1 AND i.class = 0 AND i.subClassBak = 8'); - - // move armor tokens to own category - DB::Aowow()->query('UPDATE ?_items SET subClass = -2 WHERE quality = 4 AND class = 15 AND subClassBak = 0 AND requiredClass AND (requiredClass & 0x5FF) <> 0x5FF'); - - // move some junk to holiday if it requires one - DB::Aowow()->query('UPDATE ?_items SET subClass = 3 WHERE classBak = 15 AND subClassBak = 0 AND eventId <> 0'); - - // move misc items that start quests to class: quest (except Sayges scrolls for consistency) - DB::Aowow()->query('UPDATE ?_items SET class = 12 WHERE classBak = 15 AND startQuest <> 0 AND name_loc0 NOT LIKE "sayge\'s fortune%"'); - - // move perm. enchantments into appropriate cat/subcat - DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.class = 0, i.subClass = 6 WHERE s.id = i.spellId1 AND s.effect1Id = 53 AND i.classBak = 12'); - - // move some generic recipes into appropriate sub-categories - $skillz = array( + private $skill2cat = array( 773 => 11, // inscription 356 => 9, // fishing 186 => 12, // mining 185 => 5, // cooking 171 => 6 // alchemy - ); - foreach ($skillz as $skill => $cat) - DB::Aowow()->query('UPDATE ?_items SET subClass = ?d WHERE classBak = 9 AND subClassBak = 0 AND requiredSkill = ?d', $cat, $skill); - // calculate durabilityCosts - DB::Aowow()->query(' - UPDATE - ?_items i - JOIN - dbc_durabilityquality dq ON dq.id = ((i.quality + 1) * 2) - JOIN - dbc_durabilitycosts dc ON dc.id = i.itemLevel - SET - i.repairPrice = (durability* dq.mod * IF(i.classBak = 2, - CASE i.subClassBak - WHEN 0 THEN w0 WHEN 1 THEN w1 WHEN 2 THEN w2 WHEN 3 THEN w3 WHEN 4 THEN w4 - WHEN 5 THEN w5 WHEN 6 THEN w6 WHEN 7 THEN w7 WHEN 8 THEN w8 WHEN 10 THEN w10 - WHEN 11 THEN w11 WHEN 12 THEN w12 WHEN 13 THEN w13 WHEN 14 THEN w14 WHEN 15 THEN w15 - WHEN 16 THEN w16 WHEN 17 THEN w17 WHEN 18 THEN w18 WHEN 19 THEN w19 WHEN 20 THEN w20 - END, - CASE i.subClassBak - WHEN 1 THEN a1 WHEN 2 THEN a2 WHEN 3 THEN a3 WHEN 4 THEN a4 WHEN 6 THEN a6 - END - )) - WHERE - durability > 0 AND ((classBak = 4 AND subClassBak IN (1, 2, 3, 4, 6)) OR (classBak = 2 AND subClassBak <> 9))'); + public function generate(array $ids = []) : bool + { + $baseQuery = ' + SELECT + it.entry, + class, class as classBak, + subclass, subclass AS subClassBak, + SoundOverrideSubclass, + IFNULL(sg.id, 0) AS subSubClass, + it.name, IFNULL(itl2.Name, ""), IFNULL(itl3.Name, ""), IFNULL(itl4.Name, ""), IFNULL(itl6.Name, ""), IFNULL(itl8.Name, ""), + 0 AS iconId, + displayid, + 0 AS spellVisualId, + Quality, + Flags, FlagsExtra, + BuyCount, BuyPrice, SellPrice, + 0 AS repairPrice, + InventoryType AS slot, InventoryType AS slotBak, + AllowableClass, AllowableRace, + ItemLevel, + RequiredLevel, + RequiredSkill, RequiredSkillRank, + requiredspell, + requiredhonorrank, + RequiredCityRank, + RequiredReputationFaction, + RequiredReputationRank, + maxcount, + 0 AS cuFlags, + 0 AS model, + stackable, + ContainerSlots, + stat_type1, stat_value1, + stat_type2, stat_value2, + stat_type3, stat_value3, + stat_type4, stat_value4, + stat_type5, stat_value5, + stat_type6, stat_value6, + stat_type7, stat_value7, + stat_type8, stat_value8, + stat_type9, stat_value9, + stat_type10, stat_value10, + ScalingStatDistribution, + ScalingStatValue, + dmg_min1, dmg_max1, dmg_type1, + dmg_min2, dmg_max2, dmg_type2, + delay, + armor, ArmorDamageModifier, + block, + holy_res, fire_res, nature_res, frost_res, shadow_res, arcane_res, + ammo_type, + RangedModRange, + spellid_1, spelltrigger_1, spellcharges_1, spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, + spellid_2, spelltrigger_2, spellcharges_2, spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, + spellid_3, spelltrigger_3, spellcharges_3, spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, + spellid_4, spelltrigger_4, spellcharges_4, spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, + spellid_5, spelltrigger_5, spellcharges_5, spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, + bonding, + it.description, IFNULL(itl2.Description, ""), IFNULL(itl3.Description, ""), IFNULL(itl4.Description, ""), IFNULL(itl6.Description, ""), IFNULL(itl8.Description, ""), + PageText, + LanguageID, + startquest, + lockid, + Material, + IF(RandomProperty > 0, RandomProperty, -RandomSuffix) AS randomEnchant, + itemset, + MaxDurability, + area, + Map, + BagFamily, + TotemCategory, + socketColor_1, socketContent_1, + socketColor_2, socketContent_2, + socketColor_3, socketContent_3, + socketBonus, + GemProperties, + RequiredDisenchantSkill, + DisenchantID, + duration, + ItemLimitCategory, + IFNULL(ge.eventEntry, 0), + ScriptName, + FoodType, + 0 AS gemEnchantmentId, + minMoneyLoot, maxMoneyLoot, + 0 AS pickUpSoundId, + 0 AS dropDownSoundId, + 0 AS sheatheSoundId, + 0 AS unsheatheSoundId, + flagsCustom + FROM + item_template it + LEFT JOIN + item_template_locale itl2 ON it.entry = itl2.ID AND itl2.locale = "frFR" + LEFT JOIN + item_template_locale itl3 ON it.entry = itl3.ID AND itl3.locale = "deDE" + LEFT JOIN + item_template_locale itl4 ON it.entry = itl4.ID AND itl4.locale = "zhCN" + LEFT JOIN + item_template_locale itl6 ON it.entry = itl6.ID AND itl6.locale = "esES" + LEFT JOIN + item_template_locale itl8 ON it.entry = itl8.ID AND itl8.locale = "ruRU" + LEFT JOIN + spell_group sg ON sg.spell_id = it.spellid_1 AND it.class = 0 AND it.subclass = 2 AND sg.id IN (1, 2) + LEFT JOIN + game_event ge ON ge.holiday = it.HolidayId AND it.HolidayId > 0 + WHERE + it.entry > ?d + { + AND it.entry IN (?a) + } + ORDER BY + it.entry ASC + LIMIT + ?d'; - return true; -} + $lastMax = 0; + while ($items = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + { + $newMax = max(array_column($items, 'entry')); + + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + + $lastMax = $newMax; + + foreach ($items as $item) + DB::Aowow()->query('REPLACE INTO ?_items VALUES (?a)', array_values($item)); + } + + + // merge with gemProperties + DB::Aowow()->query('UPDATE ?_items i, dbc_gemproperties gp SET i.gemEnchantmentId = gp.enchantmentId, i.gemColorMask = gp.colorMask WHERE i.gemColorMask = gp.id'); + + // get modelString + DB::Aowow()->query('UPDATE ?_items i, dbc_itemdisplayinfo idi SET i.model = IF(idi.leftModelName = "", idi.rightModelName, idi.leftModelName) WHERE i.displayId = idi.id'); + + // get iconId + DB::Aowow()->query('UPDATE ?_items i, dbc_itemdisplayinfo idi, ?_icons ic SET i.iconId = ic.id WHERE i.displayId = idi.id AND LOWER(idi.inventoryIcon1) = ic.name'); + + // unify slots: Robes => Chest; Ranged (right) => Ranged + DB::Aowow()->query('UPDATE ?_items SET slot = 15 WHERE slotbak = 26'); + DB::Aowow()->query('UPDATE ?_items SET slot = 5 WHERE slotbak = 20'); + + // custom sub-classes + DB::Aowow()->query(' + UPDATE ?_items SET subclass = IF( + slotbak = 4, -8, IF( -- shirt + slotbak = 19, -7, IF( -- tabard + slotbak = 16, -6, IF( -- cloak + slotbak = 23, -5, IF( -- held in offhand + slotbak = 12, -4, IF( -- trinket + slotbak = 2, -3, IF( -- amulet + slotbak = 11, -2, subClassBak -- ring + ))))))) WHERE class = 4'); + + // move alchemist stones to trinkets (Armor) + DB::Aowow()->query('UPDATE ?_items SET class = 4, subClass = -4 WHERE classBak = 7 AND subClassBak = 11 AND slotBak = 12'); + + // mark keys as key (if not quest items) + DB::Aowow()->query('UPDATE ?_items SET class = 13, subClass = 0 WHERE classBak IN (0, 15) AND bagFamily & 0x100'); + + // set subSubClass for Glyphs (major/minor) + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s, dbc_glyphproperties gp SET i.subSubClass = IF(gp.typeFlags & 0x1, 2, 1) WHERE i.spellId1 = s.id AND s.effect1MiscValue = gp.id AND i.classBak = 16'); + + // filter misc(class:15) junk(subclass:0) to appropriate categories + + // assign pets and mounts to category + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET subClass = IF(effect1AuraId <> 78, 2, IF(effect2AuraId = 207 OR effect3AuraId = 207 OR (s.id <> 65917 AND effect2AuraId = 4 AND effect3Id = 77), -7, 5)) WHERE s.id = spellId2 AND class = 15 AND spellId1 IN (483, 55884)'); + + // more corner cases (mounts that are not actualy learned) + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = -7 WHERE (effect1Id = 64 OR (effect1AuraId = 78 AND effect2AuraId = 4 AND effect3Id = 77) OR effect1AuraId = 207 OR effect2AuraId = 207 OR effect3AuraId = 207) AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 5'); + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = 5 WHERE s.effect1AuraId = 78 AND s.id = i.spellId1 AND i.class = 15 AND i.subClass = 0'); + + // move some permanent enchantments to own category + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.class = 0, i.subClass = 6 WHERE s.effect1Id = 53 AND s.id = i.spellId1 AND i.class = 15'); + + // move temporary enchantments to own category + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.subClass = -3 WHERE s.effect1Id = 54 AND s.id = i.spellId1 AND i.class = 0 AND i.subClassBak = 8'); + + // move armor tokens to own category + DB::Aowow()->query('UPDATE ?_items SET subClass = -2 WHERE quality = 4 AND class = 15 AND subClassBak = 0 AND requiredClass AND (requiredClass & 0x5FF) <> 0x5FF'); + + // move some junk to holiday if it requires one + DB::Aowow()->query('UPDATE ?_items SET subClass = 3 WHERE classBak = 15 AND subClassBak = 0 AND eventId <> 0'); + + // move misc items that start quests to class: quest (except Sayges scrolls for consistency) + DB::Aowow()->query('UPDATE ?_items SET class = 12 WHERE classBak = 15 AND startQuest <> 0 AND name_loc0 NOT LIKE "sayge\'s fortune%"'); + + // move perm. enchantments into appropriate cat/subcat + DB::Aowow()->query('UPDATE ?_items i, dbc_spell s SET i.class = 0, i.subClass = 6 WHERE s.id = i.spellId1 AND s.effect1Id = 53 AND i.classBak = 12'); + + // move some generic recipes into appropriate sub-categories + foreach ($this->skill2cat as $skill => $cat) + DB::Aowow()->query('UPDATE ?_items SET subClass = ?d WHERE classBak = 9 AND subClassBak = 0 AND requiredSkill = ?d', $cat, $skill); + + // calculate durabilityCosts + DB::Aowow()->query(' + UPDATE + ?_items i + JOIN + dbc_durabilityquality dq ON dq.id = ((i.quality + 1) * 2) + JOIN + dbc_durabilitycosts dc ON dc.id = i.itemLevel + SET + i.repairPrice = (durability* dq.mod * IF(i.classBak = 2, + CASE i.subClassBak + WHEN 0 THEN w0 WHEN 1 THEN w1 WHEN 2 THEN w2 WHEN 3 THEN w3 WHEN 4 THEN w4 + WHEN 5 THEN w5 WHEN 6 THEN w6 WHEN 7 THEN w7 WHEN 8 THEN w8 WHEN 10 THEN w10 + WHEN 11 THEN w11 WHEN 12 THEN w12 WHEN 13 THEN w13 WHEN 14 THEN w14 WHEN 15 THEN w15 + WHEN 16 THEN w16 WHEN 17 THEN w17 WHEN 18 THEN w18 WHEN 19 THEN w19 WHEN 20 THEN w20 + END, + CASE i.subClassBak + WHEN 1 THEN a1 WHEN 2 THEN a2 WHEN 3 THEN a3 WHEN 4 THEN a4 WHEN 6 THEN a6 + END + )) + WHERE + durability > 0 AND ((classBak = 4 AND subClassBak IN (1, 2, 3, 4, 6)) OR (classBak = 2 AND subClassBak <> 9))'); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/itemset.func.php b/setup/tools/sqlgen/itemset.func.php index f7a2d41a..07dfc1fb 100644 --- a/setup/tools/sqlgen/itemset.func.php +++ b/setup/tools/sqlgen/itemset.func.php @@ -8,39 +8,35 @@ if (!CLI) /* note: the virtual set-ids wont match the ones of wowhead - since there are some unused itemsets and and items flying around in a default database this script will create about 20 sets more than you'd expect. + since there are some unused itemsets and items flying around in a default database this script will create about 20 sets more than you'd expect. and i have no idea how to merge the prefixes/suffixes for wotlk-raidsets and arena-sets in gereral onto the name.. at least not for all locales and i'll be damned if i have to skip one */ -/* deps: - * item_template - * game_event -*/ - - -$customData = array( - 221 => ['item1' => 7948, 'item2' => 7949, 'item3' => 7950, 'item4' => 7951, 'item5' => 7952, 'item6' => 7953] -); -$reqDBC = ['itemset']; - -function itemset() +SqlGen::register(new class extends SetupScript { - $setToHoliday = array ( - 761 => 141, // Winterveil - 762 => 372, // Brewfest - 785 => 341, // Midsummer - 812 => 181, // Noblegarden + use TrCustomData; + + protected $command = 'itemset'; + + protected $tblDependancyAowow = ['spell']; + protected $tblDependancyTC = ['item_template', 'game_event']; + protected $dbcSourceFiles = ['itemset']; + + private $customData = array( + 221 => ['item1' => 7948, 'item2' => 7949, 'item3' => 7950, 'item4' => 7951, 'item5' => 7952, 'item6' => 7953] ); - // 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; + private $setToHoliday = array ( + 761 => 141, // Winterveil + 762 => 372, // Brewfest + 785 => 341, // Midsummer + 812 => 181, // Noblegarden + ); // tags where refId == virtualId // in pve sets are not recycled beyond the contentGroup - $tagsById = array( + private $tagsById = array( // "Dungeon Set 1" 1 => [181, 182, 183, 184, 185, 186, 187, 188, 189], // "Dungeon Set 2" @@ -88,7 +84,7 @@ function itemset() ); // well .. fuck - $tagsByNamePart = array( + private $tagsByNamePart = array( 17 => ['gladiator'], // "Arena Season 1 Set", 19 => ['merciless'], // "Arena Season 2 Set", 20 => ['vengeful'], // "Arena Season 3 Set", @@ -99,272 +95,279 @@ function itemset() 30 => ['wrathful'] // "Arena Season 8 Set", ); - 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) + public function generate(array $ids = []) : bool { - $spells = $items = $mods = $descText = $name = $gains = []; - $max = $reqLvl = $min = $quality = $heroic = $nPieces = []; - $classMask = $type = 0; - $hasRing = false; + // 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($this->setToHoliday))) + foreach ($this->setToHoliday as &$hId) + $hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0; - $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); + DB::Aowow()->query('TRUNCATE TABLE ?_itemset'); - /****************************************/ - /* 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) + $vIdx = 0; + $virtualId = 0; + $sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset'); + foreach ($sets as $setId => $setData) { - $classMask |= ($piece['AllowableClass'] & CLASS_MASK_ALL); - $key = $piece['Quality'].str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT); + $spells = $items = $mods = $descText = $name = $gains = []; + $max = $reqLvl = $min = $quality = $heroic = $nPieces = []; + $classMask = $type = 0; + $hasRing = false; - if (!isset($tmp[$key])) - $tmp[$key] = --$vIdx; + $holiday = $this->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); - $vId = $tmp[$key]; + /****************************************/ + /* determine type and reuse from pieces */ + /****************************************/ - // check only actual armor in rare quality or higher (or inherits holiday) - if ($piece['class'] != ITEM_CLASS_ARMOR || $piece['subclass'] == 0) - $canReuse = false; + // make the first vId always same as setId + $firstPiece = reset($pieces); + $tmp = [$firstPiece['Quality'].$firstPiece['ItemLevel'] => $setId]; - /* 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) + // walk through all items associated with the set + foreach ($pieces as $itemId => $piece) { - if (!isset($nPieces[$vId])) - $nPieces[$vId] = 1; - else - $nPieces[$vId]++; - } + $classMask |= ($piece['AllowableClass'] & CLASS_MASK_ALL); + $key = $piece['Quality'].str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT); - if (isset($items[$vId][$piece['slot']])) - { - // not reusable -> insert anyway on unique keys - if (!$canReuse) - $items[$vId][$piece['slot'].$itemId] = $itemId; - else + 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) { - CLI::write("set: ".$setId." ilvl: ".$piece['ItemLevel']." - conflict between item: ".$items[$vId][$piece['slot']]." and item: ".$itemId." choosing lower itemId", CLI::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; // 1H-Axe - else if ($piece['class'] == 2 && $piece['subclass'] == 4) - $type = 9; // 1H-Mace - else if ($piece['class'] == 2 && $piece['subclass'] == 7) - $type = 10; // 1H-Sword - else if ($piece['class'] == 2 && $piece['subclass'] == 13) - $type = 7; // Fist Weapon - else if ($piece['class'] == 2 && $piece['subclass'] == 15) - $type = 5; // Dagger - - if (!$type) - { - if ($piece['class'] == 4 && $piece['slot'] == 12) - $type = 11; // trinket - else if ($piece['class'] == 4 && $piece['slot'] == 2) - $type = 12; // amulet - 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) - CLI::write("set: ".$setId." - conflict between item: ".$item." and item: ".$temp[$slot]." choosing lower itemId", CLI::LOG_WARN); - else if ($slot == 13 || $slot = 11) // special case - $temp[] = $item; + if (!isset($nPieces[$vId])) + $nPieces[$vId] = 1; else - $temp[$slot] = $item; + $nPieces[$vId]++; } - } - $items = [$temp]; - $heroic = [reset($heroic)]; - $nPieces = [count($temp)]; - $quality = [reset($quality)]; - $reqLvl = [reset($reqLvl)]; - $max = $max ? [max($max)] : [0]; - $min = $min ? [min($min)] : [0]; - } + if (isset($items[$vId][$piece['slot']])) + { + // not reusable -> insert anyway on unique keys + if (!$canReuse) + $items[$vId][$piece['slot'].$itemId] = $itemId; + else + { + CLI::write("set: ".$setId." ilvl: ".$piece['ItemLevel']." - conflict between item: ".$items[$vId][$piece['slot']]." and item: ".$itemId." choosing lower itemId", CLI::LOG_WARN); - foreach ($items as &$subsets) - $subsets = array_pad($subsets, 10, 0); + if ($items[$vId][$piece['slot']] > $itemId) + $items[$vId][$piece['slot']] = $itemId; + } + } + else + $items[$vId][$piece['slot']] = $itemId; - /********************/ - /* calc statbonuses */ - /********************/ + /* check for type */ - 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 (array_keys(array_filter(Util::$localeStrings)) 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. 14 (0.30% @ L80) - $descText[$loc] = preg_replace('/(\d+) .*?<\/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)) + // skip cloaks, they mess with armor classes + if ($piece['slot'] == 16) continue; - $note = $tag; + // skip event-sets + if ($piece['Quality'] == 1) + continue; + + if ($piece['class'] == 2 && $piece['subclass'] == 0) + $type = 8; // 1H-Axe + else if ($piece['class'] == 2 && $piece['subclass'] == 4) + $type = 9; // 1H-Mace + else if ($piece['class'] == 2 && $piece['subclass'] == 7) + $type = 10; // 1H-Sword + else if ($piece['class'] == 2 && $piece['subclass'] == 13) + $type = 7; // Fist Weapon + else if ($piece['class'] == 2 && $piece['subclass'] == 15) + $type = 5; // Dagger + + if (!$type) + { + if ($piece['class'] == 4 && $piece['slot'] == 12) + $type = 11; // trinket + else if ($piece['class'] == 4 && $piece['slot'] == 2) + $type = 12; // amulet + 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 (!$note && $min > 120 && $classMask && $classMask != CLASS_MASK_ALL) + if ($hasRing && !$type) + $type = 6; // pure ring-set + + $isMultiSet = false; + $oldSlotMask = 0x0; + foreach ($items as $subset) { - foreach ($tagsByNamePart as $tag => $strings) + $curSlotMask = 0x0; + foreach ($subset as $slot => $item) + $curSlotMask |= (1 << $slot); + + if ($oldSlotMask && $oldSlotMask == $curSlotMask) { - foreach ($strings as $str) + $isMultiSet = true; + break; + } + + $oldSlotMask = $curSlotMask; + } + + if (!$isMultiSet || !$canReuse || $setId == 555) + { + $temp = []; + foreach ($items as $subset) + { + foreach ($subset as $slot => $item) { - if (isset($pieces[reset($vSet)]) && stripos($pieces[reset($vSet)]['name'], $str) === 0) + if (isset($temp[$slot]) && $temp[$slot] < $item) + CLI::write("set: ".$setId." - conflict between item: ".$item." and item: ".$temp[$slot]." choosing lower itemId", CLI::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 (array_keys(array_filter(Util::$localeStrings)) 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. 14 (0.30% @ L80) + $descText[$loc] = preg_replace('/(\d+) .*?<\/small>/i', '\1', $descText[$loc]); + } + + /****************************/ + /* finalaize data and write */ + /****************************/ + + foreach ($items as $vId => $vSet) + { + $note = 0; + foreach ($this->tagsById as $tag => $sets) + { + if (!in_array($setId, $sets)) + continue; + + $note = $tag; + } + + if (!$note && $min > 120 && $classMask && $classMask != CLASS_MASK_ALL) + { + foreach ($this->tagsByNamePart as $tag => $strings) + { + foreach ($strings as $str) { - $note = $tag; - break 2; + 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)); } - - $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; } - - // hide empty sets - DB::Aowow()->query('UPDATE ?_itemset SET cuFlags = cuFlags | ?d WHERE item1 = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW); - - return true; -} - +}); ?> diff --git a/setup/tools/sqlgen/lock.func.php b/setup/tools/sqlgen/lock.func.php new file mode 100644 index 00000000..8a0b9186 --- /dev/null +++ b/setup/tools/sqlgen/lock.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/mailtemplate.func.php b/setup/tools/sqlgen/mailtemplate.func.php new file mode 100644 index 00000000..833a19f8 --- /dev/null +++ b/setup/tools/sqlgen/mailtemplate.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/objects.func.php b/setup/tools/sqlgen/objects.func.php index d5f5b557..6d6b4746 100644 --- a/setup/tools/sqlgen/objects.func.php +++ b/setup/tools/sqlgen/objects.func.php @@ -7,124 +7,121 @@ if (!CLI) die('not in cli mode'); -/* deps: - * gameobject_template - * gameobject_template_locale - * gameobject_questitem -*/ - - -$customData = array( -); -$reqDBC = ['lock']; - -function objects(array $ids = []) +SqlGen::register(new class extends SetupScript { - $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, - IFNULL(gtl2.`name`, "") AS name_loc2, - IFNULL(gtl3.`name`, "") AS name_loc3, - IFNULL(gtl4.`name`, "") AS name_loc4, - IFNULL(gtl6.`name`, "") AS name_loc6, - IFNULL(gtl8.`name`, "") AS name_loc8, - IFNULL(goa.faction, 0), - IFNULL(goa.flags, 0), - 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_addon goa ON go.entry = goa.entry - 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 gtl4 ON go.entry = gtl4.entry AND gtl4.`locale` = "zhCN" - 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 > ?d - { - AND go.entry IN (?a) - } - GROUP BY - go.entry - ORDER BY - go.entry ASC - LIMIT - ?d'; + protected $command = 'objects'; - $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) - }'; + protected $tblDependancyTC = ['gameobject_template', 'gameobject_template_locale', 'gameobject_questitem']; + protected $dbcSourceFiles = ['lock']; - $lastMax = 0; - while ($objects = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$stepSize)) + public function generate(array $ids = []) : bool { - $newMax = max(array_column($objects, 'entry')); + $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, + IFNULL(gtl2.`name`, "") AS name_loc2, + IFNULL(gtl3.`name`, "") AS name_loc3, + IFNULL(gtl4.`name`, "") AS name_loc4, + IFNULL(gtl6.`name`, "") AS name_loc6, + IFNULL(gtl8.`name`, "") AS name_loc8, + IFNULL(goa.faction, 0), + IFNULL(goa.flags, 0), + 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_addon goa ON go.entry = goa.entry + 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 gtl4 ON go.entry = gtl4.entry AND gtl4.`locale` = "zhCN" + 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 > ?d + { + AND go.entry IN (?a) + } + GROUP BY + go.entry + ORDER BY + go.entry ASC + LIMIT + ?d'; - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + $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) + }'; - $lastMax = $newMax; + $lastMax = 0; + while ($objects = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + { + $newMax = max(array_column($objects, 'entry')); - foreach ($objects as $o) - DB::Aowow()->query('REPLACE INTO ?_objects VALUES (?a)', array_values($o)); + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + + $lastMax = $newMax; + + 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; } - - // apply typeCat and reqSkill depending on locks - DB::Aowow()->query($updateQuery, $ids ?: DBSIMPLE_SKIP); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/pet.func.php b/setup/tools/sqlgen/pet.func.php index 18f4f433..199b3437 100644 --- a/setup/tools/sqlgen/pet.func.php +++ b/setup/tools/sqlgen/pet.func.php @@ -7,121 +7,120 @@ if (!CLI) die('not in cli mode'); -/* deps: - * creature_template - * creature -*/ - - -$customData = array( -); -$reqDBC = ['talent', 'spell', 'skilllineability', 'creaturefamily']; - -function pet(array $ids = []) +SqlGen::register(new class extends SetupScript { - $baseQuery = ' - REPLACE INTO - ?_pet - SELECT - f.id, - categoryEnumId, - 0, -- cuFlags - 0, -- minLevel - 0, -- maxLevel - petFoodMask, - petTalentType, - 0, -- exotic - 0, -- expansion - name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, - ic.id, - skillLine1, - 0, 0, 0, 0, -- spell[1-4] - 0, 0, 0 -- armor, damage, health - FROM - dbc_creaturefamily f - LEFT JOIN - ?_icons ic ON ic.name = LOWER(SUBSTRING_INDEX(f.iconString, "\\\\", -1)) - WHERE - petTalentType <> -1'; + protected $command = 'pet'; - $spawnQuery = ' - SELECT - ct.family AS ARRAY_KEY, - MIN(ct.minlevel) AS minLevel, - MAX(ct.maxlevel) AS maxLevel, - IF(ct.type_flags & 0x10000, 1, 0) AS exotic - FROM - creature_template ct - JOIN - creature c ON ct.entry = c.id - WHERE - ct.type_flags & 0x1 - GROUP BY - ct.family'; + protected $tblDependancyAowow = ['icons']; + protected $tblDependancyTC = ['creature_template', 'creature']; + protected $dbcSourceFiles = ['talent', 'spell', 'skilllineability', 'creaturefamily']; - $bonusQuery = ' - UPDATE - ?_pet p, - dbc_skilllineability sla, - dbc_spell s - SET - armor = s.effect2BasePoints + s.effect2DieSides, - damage = s.effect1BasePoints + s.effect1DieSides, - health = s.effect3BasePoints + s.effect3DieSides - WHERE - p.skillLineId = sla.skillLineId AND - sla.spellId = s.id AND - s.name_loc0 = "Tamed Pet Passive (DND)"'; - - $spellQuery = ' - SELECT - p.id, - MAX(s.id) AS spell - FROM - dbc_skilllineability sla - JOIN - ?_pet p ON p.skillLineId = sla.skillLineId - JOIN - dbc_spell s ON sla.spellId = s.id - LEFT OUTER JOIN - dbc_talent t ON s.id = t.rank1 - WHERE - (s.attributes0 & 0x40) = 0 AND - t.id IS NULL - GROUP BY - s.name_loc0, p.id'; - - // basic copy from creaturefamily.dbc - DB::Aowow()->query($baseQuery); - - // stats from craeture_template - $spawnInfo = DB::World()->query($spawnQuery); - foreach ($spawnInfo as $id => $info) - DB::Aowow()->query('UPDATE ?_pet SET ?a WHERE id = ?d', $info, $id); - - // add petFamilyModifier to health, mana, dmg - DB::Aowow()->query($bonusQuery); - - // add expansion manually - DB::Aowow()->query('UPDATE ?_pet SET expansion = 1 WHERE id IN (30, 31, 32, 33, 34)'); - DB::Aowow()->query('UPDATE ?_pet SET expansion = 2 WHERE id IN (37, 38, 39, 41, 42, 43, 44, 45, 46)'); - - // assign pet spells - $pets = DB::Aowow()->select($spellQuery); - $res = []; - - foreach ($pets as $set) // convert to usable structure + public function generate(array $ids = []) : bool { - if (!isset($res[$set['id']])) - $res[$set['id']] = []; + $baseQuery = ' + REPLACE INTO + ?_pet + SELECT + f.id, + categoryEnumId, + 0, -- cuFlags + 0, -- minLevel + 0, -- maxLevel + petFoodMask, + petTalentType, + 0, -- exotic + 0, -- expansion + name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, + ic.id, + skillLine1, + 0, 0, 0, 0, -- spell[1-4] + 0, 0, 0 -- armor, damage, health + FROM + dbc_creaturefamily f + LEFT JOIN + ?_icons ic ON ic.name = LOWER(SUBSTRING_INDEX(f.iconString, "\\\\", -1)) + WHERE + petTalentType <> -1'; - $res[$set['id']]['spellId'.(count($res[$set['id']]) + 1)] = $set['spell']; + $spawnQuery = ' + SELECT + ct.family AS ARRAY_KEY, + MIN(ct.minlevel) AS minLevel, + MAX(ct.maxlevel) AS maxLevel, + IF(ct.type_flags & 0x10000, 1, 0) AS exotic + FROM + creature_template ct + JOIN + creature c ON ct.entry = c.id + WHERE + ct.type_flags & 0x1 + GROUP BY + ct.family'; + + $bonusQuery = ' + UPDATE + ?_pet p, + dbc_skilllineability sla, + dbc_spell s + SET + armor = s.effect2BasePoints + s.effect2DieSides, + damage = s.effect1BasePoints + s.effect1DieSides, + health = s.effect3BasePoints + s.effect3DieSides + WHERE + p.skillLineId = sla.skillLineId AND + sla.spellId = s.id AND + s.name_loc0 = "Tamed Pet Passive (DND)"'; + + $spellQuery = ' + SELECT + p.id, + MAX(s.id) AS spell + FROM + dbc_skilllineability sla + JOIN + ?_pet p ON p.skillLineId = sla.skillLineId + JOIN + dbc_spell s ON sla.spellId = s.id + LEFT OUTER JOIN + dbc_talent t ON s.id = t.rank1 + WHERE + (s.attributes0 & 0x40) = 0 AND + t.id IS NULL + GROUP BY + s.name_loc0, p.id'; + + // basic copy from creaturefamily.dbc + DB::Aowow()->query($baseQuery); + + // stats from craeture_template + $spawnInfo = DB::World()->query($spawnQuery); + foreach ($spawnInfo as $id => $info) + DB::Aowow()->query('UPDATE ?_pet SET ?a WHERE id = ?d', $info, $id); + + // add petFamilyModifier to health, mana, dmg + DB::Aowow()->query($bonusQuery); + + // add expansion manually + DB::Aowow()->query('UPDATE ?_pet SET expansion = 1 WHERE id IN (30, 31, 32, 33, 34)'); + DB::Aowow()->query('UPDATE ?_pet SET expansion = 2 WHERE id IN (37, 38, 39, 41, 42, 43, 44, 45, 46)'); + + // assign pet spells + $pets = DB::Aowow()->select($spellQuery); + $res = []; + + foreach ($pets as $set) // convert to usable structure + { + if (!isset($res[$set['id']])) + $res[$set['id']] = []; + + $res[$set['id']]['spellId'.(count($res[$set['id']]) + 1)] = $set['spell']; + } + + foreach ($res as $pId => $row) + DB::Aowow()->query('UPDATE ?_pet SET ?a WHERE id = ?d', $row, $pId); + + return true; } - - foreach ($res as $pId => $row) - DB::Aowow()->query('UPDATE ?_pet SET ?a WHERE id = ?d', $row, $pId); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/quests.func.php b/setup/tools/sqlgen/quests.func.php index 01cf6824..a6eb64c2 100644 --- a/setup/tools/sqlgen/quests.func.php +++ b/setup/tools/sqlgen/quests.func.php @@ -7,266 +7,260 @@ if (!CLI) die('not in cli mode'); -/* deps: - * quest_template - * quest_template_addon - * quest_template_locale - * game_event - * game_event_seasonal_questrelation - * disables -*/ - - -$customData = array( -); -$reqDBC = ['questxp', 'questfactionreward']; - -function quests(array $ids = []) +SqlGen::register(new class extends SetupScript { - $baseQuery = ' - SELECT - q.ID, - QuestType, -- Method - QuestLevel, - MinLevel, - IFNULL(qa.MaxLevel, 0), - QuestSortID, - QuestSortID AS zoneOrSortBak, -- ZoneOrSortBak - QuestInfoID, -- QuestType - SuggestedGroupNum, - TimeAllowed, - IFNULL(gesqr.eventEntry, 0) AS eventId, - IFNULL(qa.PrevQuestId, 0), - IFNULL(qa.NextQuestId, 0), - IFNULL(qa.ExclusiveGroup, 0), - RewardNextQuest, - q.Flags, - IFNULL(qa.SpecialFlags, 0), - ( - IF(d.entry IS NULL, 0, 134217728) + -- disabled - IF(q.Flags & 16384, 536870912, 0) -- unavailable - ) AS cuFlags, -- cuFlags - IFNULL(qa.AllowableClasses, 0), - AllowableRaces, - IFNULL(qa.RequiredSkillId, 0), IFNULL(qa.RequiredSkillPoints, 0), - RequiredFactionId1, RequiredFactionId2, - RequiredFactionValue1, RequiredFactionValue2, - IFNULL(qa.RequiredMinRepFaction, 0),IFNULL(qa.RequiredMaxRepFaction, 0), - IFNULL(qa.RequiredMinRepValue, 0), IFNULL(qa.RequiredMaxRepValue, 0), - RequiredPlayerKills, - StartItem, - IFNULL(qa.ProvidedItemCount, 0), - IFNULL(qa.SourceSpellId, 0), - RewardXPDifficulty, -- QuestXP.dbc x level - RewardMoney, - RewardBonusMoney, - RewardDisplaySpell, RewardSpell, - RewardHonor * 124 * RewardKillHonor, -- alt calculation in QuestDef.cpp -> Quest::CalculateHonorGain(playerLevel) - IFNULL(qa.RewardMailTemplateId, 0), IFNULL(qa.RewardMailDelay, 0), - RewardTitle, - RewardTalents, - RewardArenaPoints, - RewardItem1, RewardItem2, RewardItem3, RewardItem4, - RewardAmount1, RewardAmount2, RewardAmount3, RewardAmount4, - RewardChoiceItemID1, RewardChoiceItemID2, RewardChoiceItemID3, RewardChoiceItemID4, RewardChoiceItemID5, RewardChoiceItemID6, - RewardChoiceItemQuantity1, RewardChoiceItemQuantity2, RewardChoiceItemQuantity3, RewardChoiceItemQuantity4, RewardChoiceItemQuantity5, RewardChoiceItemQuantity6, - RewardFactionID1, RewardFactionID2, RewardFactionID3, RewardFactionID4, RewardFactionID5, - IF (RewardFactionOverride1 <> 0, RewardFactionOverride1 / 100, RewardFactionValue1), - IF (RewardFactionOverride2 <> 0, RewardFactionOverride2 / 100, RewardFactionValue2), - IF (RewardFactionOverride3 <> 0, RewardFactionOverride3 / 100, RewardFactionValue3), - IF (RewardFactionOverride4 <> 0, RewardFactionOverride4 / 100, RewardFactionValue4), - IF (RewardFactionOverride5 <> 0, RewardFactionOverride5 / 100, RewardFactionValue5), - q.LogTitle, IFNULL(qtl2.Title, ""), IFNULL(qtl3.Title, ""), IFNULL(qtl4.Title, ""), IFNULL(qtl6.Title, ""), IFNULL(qtl8.Title, ""), - q.LogDescription, IFNULL(qtl2.Objectives, ""), IFNULL(qtl3.Objectives, ""), IFNULL(qtl4.Objectives, ""), IFNULL(qtl6.Objectives, ""), IFNULL(qtl8.Objectives, ""), - q.QuestDescription, IFNULL(qtl2.Details, ""), IFNULL(qtl3.Details, ""), IFNULL(qtl4.Details, ""), IFNULL(qtl6.Details, ""), IFNULL(qtl8.Details, ""), - q.AreaDescription, IFNULL(qtl2.EndText, ""), IFNULL(qtl3.EndText, ""), IFNULL(qtl4.EndText, ""), IFNULL(qtl6.EndText, ""), IFNULL(qtl8.EndText, ""), - IFNULL(qor.RewardText, ""), IFNULL(qorl2.RewardText, ""), IFNULL(qorl3.RewardText, ""), IFNULL(qorl4.RewardText, ""), IFNULL(qorl6.RewardText, ""), IFNULL(qorl8.RewardText, ""), - IFNULL(qri.CompletionText, ""), IFNULL(qril2.CompletionText, ""), IFNULL(qril3.CompletionText, ""), IFNULL(qril4.CompletionText, ""), IFNULL(qril6.CompletionText, ""), IFNULL(qril8.CompletionText, ""), - q.QuestCompletionLog, IFNULL(qtl2.CompletedText, ""), IFNULL(qtl3.CompletedText, ""), IFNULL(qtl4.CompletedText, ""), IFNULL(qtl6.CompletedText, ""), IFNULL(qtl8.CompletedText, ""), - RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, - RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, - ItemDrop1, ItemDrop2, ItemDrop3, ItemDrop4, - ItemDropQuantity1, ItemDropQuantity2, ItemDropQuantity3, ItemDropQuantity4, - RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, - RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, - q.ObjectiveText1, IFNULL(qtl2.ObjectiveText1, ""), IFNULL(qtl3.ObjectiveText1, ""), IFNULL(qtl4.ObjectiveText1, ""), IFNULL(qtl6.ObjectiveText1, ""), IFNULL(qtl8.ObjectiveText1, ""), - q.ObjectiveText2, IFNULL(qtl2.ObjectiveText2, ""), IFNULL(qtl3.ObjectiveText2, ""), IFNULL(qtl4.ObjectiveText2, ""), IFNULL(qtl6.ObjectiveText2, ""), IFNULL(qtl8.ObjectiveText2, ""), - q.ObjectiveText3, IFNULL(qtl2.ObjectiveText3, ""), IFNULL(qtl3.ObjectiveText3, ""), IFNULL(qtl4.ObjectiveText3, ""), IFNULL(qtl6.ObjectiveText3, ""), IFNULL(qtl8.ObjectiveText3, ""), - q.ObjectiveText4, IFNULL(qtl2.ObjectiveText4, ""), IFNULL(qtl3.ObjectiveText4, ""), IFNULL(qtl4.ObjectiveText4, ""), IFNULL(qtl6.ObjectiveText4, ""), IFNULL(qtl8.ObjectiveText4, "") - FROM - quest_template q - LEFT JOIN - quest_template_locale qtl2 ON q.ID = qtl2.ID AND qtl2.locale = "frFR" - LEFT JOIN - quest_template_locale qtl3 ON q.ID = qtl3.ID AND qtl3.locale = "deDE" - LEFT JOIN - quest_template_locale qtl4 ON q.ID = qtl4.ID AND qtl4.locale = "zhCN" - LEFT JOIN - quest_template_locale qtl6 ON q.ID = qtl6.ID AND qtl6.locale = "esES" - LEFT JOIN - quest_template_locale qtl8 ON q.ID = qtl8.ID AND qtl8.locale = "ruRU" - LEFT JOIN - quest_offer_reward qor ON q.ID = qor.ID - LEFT JOIN - quest_offer_reward_locale qorl2 ON q.ID = qorl2.ID AND qorl2.locale = "frFR" - LEFT JOIN - quest_offer_reward_locale qorl3 ON q.ID = qorl3.ID AND qorl3.locale = "deDE" - LEFT JOIN - quest_offer_reward_locale qorl4 ON q.ID = qorl4.ID AND qorl4.locale = "zhCN" - LEFT JOIN - quest_offer_reward_locale qorl6 ON q.ID = qorl6.ID AND qorl6.locale = "esES" - LEFT JOIN - quest_offer_reward_locale qorl8 ON q.ID = qorl8.ID AND qorl8.locale = "ruRU" - LEFT JOIN - quest_request_items qri ON q.ID = qri.ID - LEFT JOIN - quest_request_items_locale qril2 ON q.ID = qril2.ID AND qril2.locale = "frFR" - LEFT JOIN - quest_request_items_locale qril3 ON q.ID = qril3.ID AND qril3.locale = "deDE" - LEFT JOIN - quest_request_items_locale qril4 ON q.ID = qril4.ID AND qril4.locale = "zhCN" - LEFT JOIN - quest_request_items_locale qril6 ON q.ID = qril6.ID AND qril6.locale = "esES" - LEFT JOIN - quest_request_items_locale qril8 ON q.ID = qril8.ID AND qril8.locale = "ruRU" - LEFT JOIN - quest_template_addon qa ON q.ID = qa.ID - LEFT JOIN - game_event_seasonal_questrelation gesqr ON gesqr.questId = q.ID - LEFT JOIN - disables d ON d.entry = q.ID AND d.sourceType = 1 - WHERE - q.id > ?d - { - AND q.id IN (?a) - } - ORDER BY - q.ID ASC - LIMIT - ?d'; + protected $command = 'quests'; - $xpQuery = ' - UPDATE - ?_quests q, - dbc_questxp xp - SET - rewardXP = (CASE rewardXP - WHEN 0 THEN xp.Field1 WHEN 1 THEN xp.Field2 WHEN 2 THEN xp.Field3 WHEN 3 THEN xp.Field4 WHEN 4 THEN xp.Field5 - WHEN 5 THEN xp.Field6 WHEN 6 THEN xp.Field7 WHEN 7 THEN xp.Field8 WHEN 8 THEN xp.Field9 WHEN 9 THEN xp.Field10 - ELSE 0 - END) - WHERE - xp.id = q.level { AND - q.id IN(?a) - }'; + protected $tblDependancyTC = ['quest_template', 'quest_template_addon', 'quest_template_locale', 'game_event', 'game_event_seasonal_questrelation', 'disables']; + protected $dbcSourceFiles = ['questxp', 'questfactionreward']; - $repQuery = ' - UPDATE - ?_quests q - LEFT JOIN - dbc_questfactionreward rep ON rep.id = IF(rewardFactionValue?d > 0, 1, 2) - SET - rewardFactionValue?d = (CASE ABS(rewardFactionValue?d) - WHEN 0 THEN rep.Field1 WHEN 1 THEN rep.Field2 WHEN 2 THEN rep.Field3 WHEN 3 THEN rep.Field4 WHEN 4 THEN rep.Field5 - WHEN 5 THEN rep.Field6 WHEN 6 THEN rep.Field7 WHEN 7 THEN rep.Field8 WHEN 8 THEN rep.Field9 WHEN 9 THEN rep.Field10 - ELSE 0 - END) - WHERE - ABS(rewardFactionValue?d) BETWEEN 1 AND 10 { AND - q.id IN(?a) - }'; - - - $lastMax = 0; - while ($quests = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$stepSize)) + public function generate(array $ids = []) : bool { - $newMax = max(array_column($quests, 'ID')); + $baseQuery = ' + SELECT + q.ID, + QuestType, -- Method + QuestLevel, + MinLevel, + IFNULL(qa.MaxLevel, 0), + QuestSortID, + QuestSortID AS zoneOrSortBak, -- ZoneOrSortBak + QuestInfoID, -- QuestType + SuggestedGroupNum, + TimeAllowed, + IFNULL(gesqr.eventEntry, 0) AS eventId, + IFNULL(qa.PrevQuestId, 0), + IFNULL(qa.NextQuestId, 0), + IFNULL(qa.ExclusiveGroup, 0), + RewardNextQuest, + q.Flags, + IFNULL(qa.SpecialFlags, 0), + ( + IF(d.entry IS NULL, 0, 134217728) + -- disabled + IF(q.Flags & 16384, 536870912, 0) -- unavailable + ) AS cuFlags, -- cuFlags + IFNULL(qa.AllowableClasses, 0), + AllowableRaces, + IFNULL(qa.RequiredSkillId, 0), IFNULL(qa.RequiredSkillPoints, 0), + RequiredFactionId1, RequiredFactionId2, + RequiredFactionValue1, RequiredFactionValue2, + IFNULL(qa.RequiredMinRepFaction, 0),IFNULL(qa.RequiredMaxRepFaction, 0), + IFNULL(qa.RequiredMinRepValue, 0), IFNULL(qa.RequiredMaxRepValue, 0), + RequiredPlayerKills, + StartItem, + IFNULL(qa.ProvidedItemCount, 0), + IFNULL(qa.SourceSpellId, 0), + RewardXPDifficulty, -- QuestXP.dbc x level + RewardMoney, + RewardBonusMoney, + RewardDisplaySpell, RewardSpell, + RewardHonor * 124 * RewardKillHonor, -- alt calculation in QuestDef.cpp -> Quest::CalculateHonorGain(playerLevel) + IFNULL(qa.RewardMailTemplateId, 0), IFNULL(qa.RewardMailDelay, 0), + RewardTitle, + RewardTalents, + RewardArenaPoints, + RewardItem1, RewardItem2, RewardItem3, RewardItem4, + RewardAmount1, RewardAmount2, RewardAmount3, RewardAmount4, + RewardChoiceItemID1, RewardChoiceItemID2, RewardChoiceItemID3, RewardChoiceItemID4, RewardChoiceItemID5, RewardChoiceItemID6, + RewardChoiceItemQuantity1, RewardChoiceItemQuantity2, RewardChoiceItemQuantity3, RewardChoiceItemQuantity4, RewardChoiceItemQuantity5, RewardChoiceItemQuantity6, + RewardFactionID1, RewardFactionID2, RewardFactionID3, RewardFactionID4, RewardFactionID5, + IF (RewardFactionOverride1 <> 0, RewardFactionOverride1 / 100, RewardFactionValue1), + IF (RewardFactionOverride2 <> 0, RewardFactionOverride2 / 100, RewardFactionValue2), + IF (RewardFactionOverride3 <> 0, RewardFactionOverride3 / 100, RewardFactionValue3), + IF (RewardFactionOverride4 <> 0, RewardFactionOverride4 / 100, RewardFactionValue4), + IF (RewardFactionOverride5 <> 0, RewardFactionOverride5 / 100, RewardFactionValue5), + q.LogTitle, IFNULL(qtl2.Title, ""), IFNULL(qtl3.Title, ""), IFNULL(qtl4.Title, ""), IFNULL(qtl6.Title, ""), IFNULL(qtl8.Title, ""), + q.LogDescription, IFNULL(qtl2.Objectives, ""), IFNULL(qtl3.Objectives, ""), IFNULL(qtl4.Objectives, ""), IFNULL(qtl6.Objectives, ""), IFNULL(qtl8.Objectives, ""), + q.QuestDescription, IFNULL(qtl2.Details, ""), IFNULL(qtl3.Details, ""), IFNULL(qtl4.Details, ""), IFNULL(qtl6.Details, ""), IFNULL(qtl8.Details, ""), + q.AreaDescription, IFNULL(qtl2.EndText, ""), IFNULL(qtl3.EndText, ""), IFNULL(qtl4.EndText, ""), IFNULL(qtl6.EndText, ""), IFNULL(qtl8.EndText, ""), + IFNULL(qor.RewardText, ""), IFNULL(qorl2.RewardText, ""), IFNULL(qorl3.RewardText, ""), IFNULL(qorl4.RewardText, ""), IFNULL(qorl6.RewardText, ""), IFNULL(qorl8.RewardText, ""), + IFNULL(qri.CompletionText, ""), IFNULL(qril2.CompletionText, ""), IFNULL(qril3.CompletionText, ""), IFNULL(qril4.CompletionText, ""), IFNULL(qril6.CompletionText, ""), IFNULL(qril8.CompletionText, ""), + q.QuestCompletionLog, IFNULL(qtl2.CompletedText, ""), IFNULL(qtl3.CompletedText, ""), IFNULL(qtl4.CompletedText, ""), IFNULL(qtl6.CompletedText, ""), IFNULL(qtl8.CompletedText, ""), + RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, + RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, + ItemDrop1, ItemDrop2, ItemDrop3, ItemDrop4, + ItemDropQuantity1, ItemDropQuantity2, ItemDropQuantity3, ItemDropQuantity4, + RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, + RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, + q.ObjectiveText1, IFNULL(qtl2.ObjectiveText1, ""), IFNULL(qtl3.ObjectiveText1, ""), IFNULL(qtl4.ObjectiveText1, ""), IFNULL(qtl6.ObjectiveText1, ""), IFNULL(qtl8.ObjectiveText1, ""), + q.ObjectiveText2, IFNULL(qtl2.ObjectiveText2, ""), IFNULL(qtl3.ObjectiveText2, ""), IFNULL(qtl4.ObjectiveText2, ""), IFNULL(qtl6.ObjectiveText2, ""), IFNULL(qtl8.ObjectiveText2, ""), + q.ObjectiveText3, IFNULL(qtl2.ObjectiveText3, ""), IFNULL(qtl3.ObjectiveText3, ""), IFNULL(qtl4.ObjectiveText3, ""), IFNULL(qtl6.ObjectiveText3, ""), IFNULL(qtl8.ObjectiveText3, ""), + q.ObjectiveText4, IFNULL(qtl2.ObjectiveText4, ""), IFNULL(qtl3.ObjectiveText4, ""), IFNULL(qtl4.ObjectiveText4, ""), IFNULL(qtl6.ObjectiveText4, ""), IFNULL(qtl8.ObjectiveText4, "") + FROM + quest_template q + LEFT JOIN + quest_template_locale qtl2 ON q.ID = qtl2.ID AND qtl2.locale = "frFR" + LEFT JOIN + quest_template_locale qtl3 ON q.ID = qtl3.ID AND qtl3.locale = "deDE" + LEFT JOIN + quest_template_locale qtl4 ON q.ID = qtl4.ID AND qtl4.locale = "zhCN" + LEFT JOIN + quest_template_locale qtl6 ON q.ID = qtl6.ID AND qtl6.locale = "esES" + LEFT JOIN + quest_template_locale qtl8 ON q.ID = qtl8.ID AND qtl8.locale = "ruRU" + LEFT JOIN + quest_offer_reward qor ON q.ID = qor.ID + LEFT JOIN + quest_offer_reward_locale qorl2 ON q.ID = qorl2.ID AND qorl2.locale = "frFR" + LEFT JOIN + quest_offer_reward_locale qorl3 ON q.ID = qorl3.ID AND qorl3.locale = "deDE" + LEFT JOIN + quest_offer_reward_locale qorl4 ON q.ID = qorl4.ID AND qorl4.locale = "zhCN" + LEFT JOIN + quest_offer_reward_locale qorl6 ON q.ID = qorl6.ID AND qorl6.locale = "esES" + LEFT JOIN + quest_offer_reward_locale qorl8 ON q.ID = qorl8.ID AND qorl8.locale = "ruRU" + LEFT JOIN + quest_request_items qri ON q.ID = qri.ID + LEFT JOIN + quest_request_items_locale qril2 ON q.ID = qril2.ID AND qril2.locale = "frFR" + LEFT JOIN + quest_request_items_locale qril3 ON q.ID = qril3.ID AND qril3.locale = "deDE" + LEFT JOIN + quest_request_items_locale qril4 ON q.ID = qril4.ID AND qril4.locale = "zhCN" + LEFT JOIN + quest_request_items_locale qril6 ON q.ID = qril6.ID AND qril6.locale = "esES" + LEFT JOIN + quest_request_items_locale qril8 ON q.ID = qril8.ID AND qril8.locale = "ruRU" + LEFT JOIN + quest_template_addon qa ON q.ID = qa.ID + LEFT JOIN + game_event_seasonal_questrelation gesqr ON gesqr.questId = q.ID + LEFT JOIN + disables d ON d.entry = q.ID AND d.sourceType = 1 + WHERE + q.id > ?d + { + AND q.id IN (?a) + } + ORDER BY + q.ID ASC + LIMIT + ?d'; - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + $xpQuery = ' + UPDATE + ?_quests q, + dbc_questxp xp + SET + rewardXP = (CASE rewardXP + WHEN 0 THEN xp.Field1 WHEN 1 THEN xp.Field2 WHEN 2 THEN xp.Field3 WHEN 3 THEN xp.Field4 WHEN 4 THEN xp.Field5 + WHEN 5 THEN xp.Field6 WHEN 6 THEN xp.Field7 WHEN 7 THEN xp.Field8 WHEN 8 THEN xp.Field9 WHEN 9 THEN xp.Field10 + ELSE 0 + END) + WHERE + xp.id = q.level { AND + q.id IN(?a) + }'; - $lastMax = $newMax; + $repQuery = ' + UPDATE + ?_quests q + LEFT JOIN + dbc_questfactionreward rep ON rep.id = IF(rewardFactionValue?d > 0, 1, 2) + SET + rewardFactionValue?d = (CASE ABS(rewardFactionValue?d) + WHEN 0 THEN rep.Field1 WHEN 1 THEN rep.Field2 WHEN 2 THEN rep.Field3 WHEN 3 THEN rep.Field4 WHEN 4 THEN rep.Field5 + WHEN 5 THEN rep.Field6 WHEN 6 THEN rep.Field7 WHEN 7 THEN rep.Field8 WHEN 8 THEN rep.Field9 WHEN 9 THEN rep.Field10 + ELSE 0 + END) + WHERE + ABS(rewardFactionValue?d) BETWEEN 1 AND 10 { AND + q.id IN(?a) + }'; - foreach ($quests as $q) - DB::Aowow()->query('REPLACE INTO ?_quests VALUES (?a)', array_values($q)); + + $lastMax = 0; + while ($quests = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + { + $newMax = max(array_column($quests, 'ID')); + + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + + $lastMax = $newMax; + + foreach ($quests as $q) + DB::Aowow()->query('REPLACE INTO ?_quests VALUES (?a)', array_values($q)); + } + + /* + just some random thoughts here .. + quest-custom-flags are derived from flags and specialFlags + since they are not used further than being sent to JS as wFlags this is fine.. + should they be saved to db anyway..? + same with QUEST_FLAG_UNAVAILABLE => CUSTOM_EXCLUDE_FOR_LISTVIEW + */ + + // unpack XP-reward + DB::Aowow()->query($xpQuery, $ids ?: DBSIMPLE_SKIP); + + // unpack Rep-rewards + for ($i = 1; $i < 6; $i++) + DB::Aowow()->query($repQuery, $i, $i, $i, $i, $ids ?: DBSIMPLE_SKIP); + + // zoneorsort for quests need updating + // partially points non-instanced area with identic name for instance quests + $subcats = array( + -221 => 440, // Treasure Map => Tanaris + -284 => 0, // Special => Misc (some quests get shuffled into seasonal) + 151 => 0, // Designer Island => Misc + 22 => 0, // Programmer Isle + 35 => 33, // Booty Bay => Stranglethorn Vale + 131 => 132, // Kharanos => Coldridge Valley + 24 => 9, // Northshire Abbey => Northshire Valley + 279 => 36, // Dalaran Crater => Alterac Mountains + 4342 => 4298, // Acherus: The Ebon Hold => The Scarlet Enclave + 2079 => 15, // Alcaz Island => Dustwallow Marsh + 1939 => 440, // Abyssal Sands => Tanaris + 393 => 363, // Darkspeer Strand => Valley of Trials + 702 => 141, // Rut'theran Village => Teldrassil + 221 => 220, // Camp Narache => Red Cloud Mesa + 1116 => 357, // Feathermoon Stronghold => Feralas + 236 => 209, // Shadowfang Keep + 4769 => 4742, // Hrothgar's Landing => Hrothgar's Landing + 4613 => 4395, // Dalaran City => Dalaran + 4522 => 210, // Icecrown Citadell => Icecrown + 3896 => 3703, // Aldor Rise => Shattrath City + 3696 => 3522, // The Barrier Hills => Blade's Edge Mountains + 2839 => 2597, // Alterac Valley + 19 => 1977, // Zul'Gurub + 4445 => 4273, // Ulduar + 2300 => 1941, // Caverns of Time + 3545 => 3535, // Hellfire Citadel + 2562 => 3457, // Karazhan + 3840 => 3959, // Black Temple + 1717 => 491, // Razorfen Kraul + 978 => 1176, // Zul'Farrak + 133 => 721, // Gnomeregan + 3607 => 3905, // Serpentshrine Cavern + 3845 => 3842, // Tempest Keep + 1517 => 1337 // Uldaman + ); + + foreach ($subcats as $child => $parent) + DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE zoneOrSortBak = ?d', $parent, $child); + + // move quests liked to holidays into appropirate quests-sorts. create dummy sorts as needed + $eventSet = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday <> 0'); + $holidaySorts = array( + 141 => -1001, 181 => -374, 201 => -1002, // Winter Veil Noblegarden Childrens Week + 321 => -1005, 324 => -1003, 404 => -375, // Harvest Fest. Hallows End Pilgrims Bounty + 327 => -366, 341 => -369, 372 => -370, // Lunar Fest. Midsummer Brewfest + 423 => -376 // Love is in the Air + ); + + foreach ($holidaySorts as $hId => $sort) + if (!empty($eventSet[$hId])) + DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE eventId = ?d{ AND id IN (?a)}', $sort, $eventSet[$hId], $ids ?: DBSIMPLE_SKIP); + + // 'special' special cases + // fishing quests to stranglethorn extravaganza + DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE id IN (?a){ AND id IN (?a)}', -101, [8228, 8229], $ids ?: DBSIMPLE_SKIP); + // dungeon quests to Misc/Dungeon Finder + DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE (specialFlags & ?d OR id IN (?a)){ AND id IN (?a)}', -1010, QUEST_FLAG_SPECIAL_DUNGEON_FINDER, [24789, 24791, 24923], $ids ?: DBSIMPLE_SKIP); + + return true; } - - /* - just some random thoughts here .. - quest-custom-flags are derived from flags and specialFlags - since they are not used further than being sent to JS as wFlags this is fine.. - should they be saved to db anyway..? - same with QUEST_FLAG_UNAVAILABLE => CUSTOM_EXCLUDE_FOR_LISTVIEW - */ - - // unpack XP-reward - DB::Aowow()->query($xpQuery, $ids ?: DBSIMPLE_SKIP); - - // unpack Rep-rewards - for ($i = 1; $i < 6; $i++) - DB::Aowow()->query($repQuery, $i, $i, $i, $i, $ids ?: DBSIMPLE_SKIP); - - // zoneorsort for quests need updating - // partially points non-instanced area with identic name for instance quests - $subcats = array( - -221 => 440, // Treasure Map => Tanaris - -284 => 0, // Special => Misc (some quests get shuffled into seasonal) - 151 => 0, // Designer Island => Misc - 22 => 0, // Programmer Isle - 35 => 33, // Booty Bay => Stranglethorn Vale - 131 => 132, // Kharanos => Coldridge Valley - 24 => 9, // Northshire Abbey => Northshire Valley - 279 => 36, // Dalaran Crater => Alterac Mountains - 4342 => 4298, // Acherus: The Ebon Hold => The Scarlet Enclave - 2079 => 15, // Alcaz Island => Dustwallow Marsh - 1939 => 440, // Abyssal Sands => Tanaris - 393 => 363, // Darkspeer Strand => Valley of Trials - 702 => 141, // Rut'theran Village => Teldrassil - 221 => 220, // Camp Narache => Red Cloud Mesa - 1116 => 357, // Feathermoon Stronghold => Feralas - 236 => 209, // Shadowfang Keep - 4769 => 4742, // Hrothgar's Landing => Hrothgar's Landing - 4613 => 4395, // Dalaran City => Dalaran - 4522 => 210, // Icecrown Citadell => Icecrown - 3896 => 3703, // Aldor Rise => Shattrath City - 3696 => 3522, // The Barrier Hills => Blade's Edge Mountains - 2839 => 2597, // Alterac Valley - 19 => 1977, // Zul'Gurub - 4445 => 4273, // Ulduar - 2300 => 1941, // Caverns of Time - 3545 => 3535, // Hellfire Citadel - 2562 => 3457, // Karazhan - 3840 => 3959, // Black Temple - 1717 => 491, // Razorfen Kraul - 978 => 1176, // Zul'Farrak - 133 => 721, // Gnomeregan - 3607 => 3905, // Serpentshrine Cavern - 3845 => 3842, // Tempest Keep - 1517 => 1337 // Uldaman - ); - - foreach ($subcats as $child => $parent) - DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE zoneOrSortBak = ?d', $parent, $child); - - // move quests liked to holidays into appropirate quests-sorts. create dummy sorts as needed - $eventSet = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday <> 0'); - $holidaySorts = array( - 141 => -1001, 181 => -374, 201 => -1002, // Winter Veil Noblegarden Childrens Week - 321 => -1005, 324 => -1003, 404 => -375, // Harvest Fest. Hallows End Pilgrims Bounty - 327 => -366, 341 => -369, 372 => -370, // Lunar Fest. Midsummer Brewfest - 423 => -376 // Love is in the Air - ); - - foreach ($holidaySorts as $hId => $sort) - if (!empty($eventSet[$hId])) - DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE eventId = ?d{ AND id IN (?a)}', $sort, $eventSet[$hId], $ids ?: DBSIMPLE_SKIP); - - // 'special' special cases - // fishing quests to stranglethorn extravaganza - DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE id IN (?a){ AND id IN (?a)}', -101, [8228, 8229], $ids ?: DBSIMPLE_SKIP); - // dungeon quests to Misc/Dungeon Finder - DB::Aowow()->query('UPDATE ?_quests SET zoneOrSort = ?d WHERE (specialFlags & ?d OR id IN (?a)){ AND id IN (?a)}', -1010, QUEST_FLAG_SPECIAL_DUNGEON_FINDER, [24789, 24791, 24923], $ids ?: DBSIMPLE_SKIP); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/quests_startend.func.php b/setup/tools/sqlgen/quests_startend.func.php index 391c038c..d807ba97 100644 --- a/setup/tools/sqlgen/quests_startend.func.php +++ b/setup/tools/sqlgen/quests_startend.func.php @@ -7,51 +7,42 @@ if (!CLI) die('not in cli mode'); -/* deps: - * creature_queststarter - * creature_questender - * game_event_creature_quest - * gameobject_queststarter - * gameobject_questender - * game_event_gameobject_quest - * item_template -*/ - - -$customData = array( -); -$reqDBC = array( -); - -function quests_startend(/* array $ids = [] */) +SqlGen::register(new class extends SetupScript { - $query['creature'] = ' - SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM creature_queststarter UNION - SELECT 1 AS type, id AS typeId, quest AS questId, 2 AS method, 0 AS eventId FROM creature_questender UNION - SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, eventEntry AS eventId FROM game_event_creature_quest'; + protected $command = 'quests_startend'; - $query['object'] = ' - SELECT 2 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM gameobject_queststarter UNION - SELECT 2 AS type, id AS typeId, quest AS questId, 2 AS method, 0 AS eventId FROM gameobject_questender UNION - SELECT 2 AS type, id AS typeId, quest AS questId, 1 AS method, eventEntry AS eventId FROM game_event_gameobject_quest'; + protected $tblDependancyTC = ['creature_queststarter', 'creature_questender', 'game_event_creature_quest', 'gameobject_queststarter', 'gameobject_questender', 'game_event_gameobject_quest', 'item_template']; - $query['item'] = 'SELECT 3 AS type, entry AS typeId, startquest AS questId, 1 AS method, 0 AS eventId FROM item_template WHERE startquest <> 0'; - - // always rebuild this table from scratch - // or how would i know what to fetch specifically - DB::Aowow()->query('TRUNCATE TABLE ?_quests_startend'); - - foreach ($query as $q) + public function generate(array $ids = []) : bool { - $data = DB::World()->select($q); - foreach ($data as $d) - DB::Aowow()->query('INSERT INTO ?_quests_startend (?#) VALUES (?a) ON DUPLICATE KEY UPDATE method = method | VALUES(method), eventId = IF(eventId = 0, VALUES(eventId), eventId)', array_keys($d), array_values($d)); + $query['creature'] = ' + SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM creature_queststarter UNION + SELECT 1 AS type, id AS typeId, quest AS questId, 2 AS method, 0 AS eventId FROM creature_questender UNION + SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, eventEntry AS eventId FROM game_event_creature_quest'; + + $query['object'] = ' + SELECT 2 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM gameobject_queststarter UNION + SELECT 2 AS type, id AS typeId, quest AS questId, 2 AS method, 0 AS eventId FROM gameobject_questender UNION + SELECT 2 AS type, id AS typeId, quest AS questId, 1 AS method, eventEntry AS eventId FROM game_event_gameobject_quest'; + + $query['item'] = 'SELECT 3 AS type, entry AS typeId, startquest AS questId, 1 AS method, 0 AS eventId FROM item_template WHERE startquest <> 0'; + + // always rebuild this table from scratch + // or how would i know what to fetch specifically + DB::Aowow()->query('TRUNCATE TABLE ?_quests_startend'); + + foreach ($query as $q) + { + $data = DB::World()->select($q); + foreach ($data as $d) + DB::Aowow()->query('INSERT INTO ?_quests_startend (?#) VALUES (?a) ON DUPLICATE KEY UPDATE method = method | VALUES(method), eventId = IF(eventId = 0, VALUES(eventId), eventId)', array_keys($d), array_values($d)); + } + + // update quests without start as unavailable + Db::Aowow()->query('UPDATE ?_quests q LEFT JOIN ?_quests_startend qse ON qse.questId = q.id AND qse.method & 1 SET q.cuFlags = q.cuFlags | ?d WHERE qse.questId IS NULL', CUSTOM_UNAVAILABLE); + + return true; } - - // update quests without start as unavailable - Db::Aowow()->query('UPDATE ?_quests q LEFT JOIN ?_quests_startend qse ON qse.questId = q.id AND qse.method & 1 SET q.cuFlags = q.cuFlags | ?d WHERE qse.questId IS NULL', CUSTOM_UNAVAILABLE); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/races.func.php b/setup/tools/sqlgen/races.func.php index 33ca09e8..675fc30e 100644 --- a/setup/tools/sqlgen/races.func.php +++ b/setup/tools/sqlgen/races.func.php @@ -7,45 +7,53 @@ if (!CLI) die('not in cli mode'); -$customData = array( - null, - ['leader' => 29611, 'factionId' => 72, 'startAreaId' => 12], - ['leader' => 4949, 'factionId' => 76, 'startAreaId' => 14], - ['leader' => 2784, 'factionId' => 47, 'startAreaId' => 1], - ['leader' => 7999, 'factionId' => 69, 'startAreaId' => 141], - ['leader' => 10181, 'factionId' => 68, 'startAreaId' => 85], - ['leader' => 3057, 'factionId' => 81, 'startAreaId' => 215], - ['leader' => 7937, 'factionId' => 54, 'startAreaId' => 1], - ['leader' => 10540, 'factionId' => 530, 'startAreaId' => 14], - null, - ['leader' => 16802, 'factionId' => 911, 'startAreaId' => 3430], - ['leader' => 17468, 'factionId' => 930, 'startAreaId' => 3524] -); -$reqDBC = ['chrraces', 'charbaseinfo']; - -function races() +SqlGen::register(new class extends SetupScript { - /**********/ - /* Basics */ - /**********/ + use TrCustomData; - $baseQuery = ' - REPLACE INTO - ?_races - SELECT - id, 0, flags, 0, factionId, 0, 0, baseLanguage, IF(side = 2, 0, side + 1), fileString, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, expansion - FROM - dbc_chrraces'; + protected $command = 'races'; - DB::Aowow()->query($baseQuery); + protected $dbcSourceFiles = ['chrraces', 'charbaseinfo']; - // add classMask - DB::Aowow()->query('UPDATE ?_races r JOIN (SELECT BIT_OR(1 << (classId - 1)) as classMask, raceId FROM dbc_charbaseinfo GROUP BY raceId) cbi ON cbi.raceId = r.id SET r.classMask = cbi.classMask'); + private $customData = array( + null, + ['leader' => 29611, 'factionId' => 72, 'startAreaId' => 12], + ['leader' => 4949, 'factionId' => 76, 'startAreaId' => 14], + ['leader' => 2784, 'factionId' => 47, 'startAreaId' => 1], + ['leader' => 7999, 'factionId' => 69, 'startAreaId' => 141], + ['leader' => 10181, 'factionId' => 68, 'startAreaId' => 85], + ['leader' => 3057, 'factionId' => 81, 'startAreaId' => 215], + ['leader' => 7937, 'factionId' => 54, 'startAreaId' => 1], + ['leader' => 10540, 'factionId' => 530, 'startAreaId' => 14], + null, + ['leader' => 16802, 'factionId' => 911, 'startAreaId' => 3430], + ['leader' => 17468, 'factionId' => 930, 'startAreaId' => 3524] + ); - // add cuFlags - DB::Aowow()->query('UPDATE ?_races SET cuFlags = ?d WHERE flags & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x1); + public function generate(array $ids = []) : bool + { + /**********/ + /* Basics */ + /**********/ - return true; -} + $baseQuery = ' + REPLACE INTO + ?_races + SELECT + id, 0, flags, 0, factionId, 0, 0, baseLanguage, IF(side = 2, 0, side + 1), fileString, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, expansion + FROM + dbc_chrraces'; + + DB::Aowow()->query($baseQuery); + + // add classMask + DB::Aowow()->query('UPDATE ?_races r JOIN (SELECT BIT_OR(1 << (classId - 1)) as classMask, raceId FROM dbc_charbaseinfo GROUP BY raceId) cbi ON cbi.raceId = r.id SET r.classMask = cbi.classMask'); + + // add cuFlags + DB::Aowow()->query('UPDATE ?_races SET cuFlags = ?d WHERE flags & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x1); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/scalingstatdistribution.func.php b/setup/tools/sqlgen/scalingstatdistribution.func.php new file mode 100644 index 00000000..f8be3f30 --- /dev/null +++ b/setup/tools/sqlgen/scalingstatdistribution.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/scalingstatvalues.func.php b/setup/tools/sqlgen/scalingstatvalues.func.php new file mode 100644 index 00000000..0b1fb582 --- /dev/null +++ b/setup/tools/sqlgen/scalingstatvalues.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/shapeshiftforms.func.php b/setup/tools/sqlgen/shapeshiftforms.func.php index 44531977..19acf730 100644 --- a/setup/tools/sqlgen/shapeshiftforms.func.php +++ b/setup/tools/sqlgen/shapeshiftforms.func.php @@ -7,22 +7,40 @@ if (!CLI) die('not in cli mode'); -$customData = array( - 1 => ['displayIdH' => 8571], - 15 => ['displayIdH' => 8571], - 5 => ['displayIdH' => 2289], - 8 => ['displayIdH' => 2289], - 14 => ['displayIdH' => 2289], - 27 => ['displayIdH' => 21244], - 29 => ['displayIdH' => 20872], -); -$reqDBC = ['spellshapeshiftform']; - -function shapeshiftforms() +SqlGen::register(new class extends SetupScript { - DB::Aowow()->query('REPLACE INTO ?_shapeshiftforms SELECT id, flags, creatureType, displayIdA, displayIdH, spellId1, spellId2, spellId3, spellId4, spellId5, spellId6, spellId7, spellId8, IF(name_loc0 = "", IF(name_loc2 = "", IF(name_loc3 = "", IF(name_loc6 = "", IF(name_loc8 = "", "???", name_loc8), name_loc6), name_loc3), name_loc2), name_loc0) FROM dbc_spellshapeshiftform'); + use TrCustomData; - return true; -} + protected $command = 'shapeshiftforms'; + + protected $dbcSourceFiles = ['spellshapeshiftform']; + + private $customData = array( + 1 => ['displayIdH' => 8571], + 15 => ['displayIdH' => 8571], + 5 => ['displayIdH' => 2289], + 8 => ['displayIdH' => 2289], + 14 => ['displayIdH' => 2289], + 27 => ['displayIdH' => 21244], + 29 => ['displayIdH' => 20872] + ); + + public function generate(array $ids = []) : bool + { + DB::Aowow()->query(' + REPLACE INTO + ?_shapeshiftforms + SELECT + id, flags, creatureType, + displayIdA, displayIdH, + spellId1, spellId2, spellId3, spellId4, spellId5, spellId6, spellId7, spellId8, + IF(name_loc0 = "", IF(name_loc2 = "", IF(name_loc3 = "", IF(name_loc6 = "", IF(name_loc8 = "", "???", name_loc8), name_loc6), name_loc3), name_loc2), name_loc0) + FROM + dbc_spellshapeshiftform' + ); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/skillline.func.php b/setup/tools/sqlgen/skillline.func.php index 9d63b159..b6728acc 100644 --- a/setup/tools/sqlgen/skillline.func.php +++ b/setup/tools/sqlgen/skillline.func.php @@ -6,71 +6,81 @@ if (!defined('AOWOW_REVISION')) if (!CLI) die('not in cli mode'); -$customData = array( - 393 => ['professionMask' => 0x0000], // Skinning - 171 => ['professionMask' => 0x0001, 'recipeSubClass' => 6, 'specializations' => '28677 28675 28672'], // Alchemy - 164 => ['professionMask' => 0x0002, 'recipeSubClass' => 4, 'specializations' => '9788 9787 17041 17040 17039'], // Blacksmithing - 185 => ['professionMask' => 0x0004, 'recipeSubClass' => 5], // Cooking - 333 => ['professionMask' => 0x0008, 'recipeSubClass' => 8], // Enchanting - 202 => ['professionMask' => 0x0010, 'recipeSubClass' => 3, 'specializations' => '20219 20222'], // Engineering - 129 => ['professionMask' => 0x0020, 'recipeSubClass' => 7], // First Aid - 755 => ['professionMask' => 0x0040, 'recipeSubClass' => 10], // Jewelcrafting - 165 => ['professionMask' => 0x0080, 'recipeSubClass' => 1, 'specializations' => '10656 10658 10660'], // Leatherworking - 186 => ['professionMask' => 0x0100], // Mining - 197 => ['professionMask' => 0x0200, 'recipeSubClass' => 2, 'specializations' => '26798 26801 26797'], // Tailoring - 356 => ['professionMask' => 0x0400, 'recipeSubClass' => 9], // Fishing - 182 => ['professionMask' => 0x0800], // Herbalism - 773 => ['professionMask' => 0x1000, 'recipeSubClass' => 11], // Inscription - 785 => ['name_loc0' => 'Pet - Wasp'], // Pet - Wasp - 781 => ['name_loc2' => 'Familier - diablosaure exotique'], // Pet - Exotic Devilsaur - 758 => ['name_loc6' => 'Mascota: Evento - Control remoto', 'name_loc3' => 'Tier - Ereignis Ferngesteuert', 'categoryId' => 7], // Pet - Event - Remote Control - 788 => ['categoryId' => 7], // Pet - Exotic Spirit Beast -); -$reqDBC = ['skillline', 'spell', 'skilllineability']; -function skillline() +SqlGen::register(new class extends SetupScript { - $baseQuery = ' - REPLACE INTO - ?_skillline - SELECT - id, categoryId, 0, categoryId, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, description_loc0, description_loc2, description_loc3, description_loc4, description_loc6, description_loc8, 0, iconId, 0, 0, "" - FROM - dbc_skillline'; + use TrCustomData; - DB::Aowow()->query($baseQuery); + protected $command = 'skillline'; - // categorization - DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -5 WHERE id = 777 OR (categoryId = 9 AND id NOT IN (356, 129, 185, 142, 155))'); - DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -4 WHERE categoryId = 9 AND name_loc0 LIKE "%racial%"'); - DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -6 WHERE id IN (778, 788, 758) OR (categoryId = 7 AND name_loc0 LIKE "%pet%")'); + protected $tblDependancyAowow = ['icons']; + protected $dbcSourceFiles = ['skillline', 'spell', 'skilllineability']; - // more complex fixups - DB::Aowow()->query('UPDATE ?_skillline SET name_loc8 = REPLACE(name_loc8, " - ", ": ") WHERE categoryId = 7 OR id IN (758, 788)'); - DB::Aowow()->query('UPDATE ?_skillline SET cuFlags = ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [142, 148, 149, 150, 152, 155, 183, 533, 553, 554, 713, 769]); + private $customData = array( + 393 => ['professionMask' => 0x0000], // Skinning + 171 => ['professionMask' => 0x0001, 'recipeSubClass' => 6, 'specializations' => '28677 28675 28672'], // Alchemy + 164 => ['professionMask' => 0x0002, 'recipeSubClass' => 4, 'specializations' => '9788 9787 17041 17040 17039'], // Blacksmithing + 185 => ['professionMask' => 0x0004, 'recipeSubClass' => 5], // Cooking + 333 => ['professionMask' => 0x0008, 'recipeSubClass' => 8], // Enchanting + 202 => ['professionMask' => 0x0010, 'recipeSubClass' => 3, 'specializations' => '20219 20222'], // Engineering + 129 => ['professionMask' => 0x0020, 'recipeSubClass' => 7], // First Aid + 755 => ['professionMask' => 0x0040, 'recipeSubClass' => 10], // Jewelcrafting + 165 => ['professionMask' => 0x0080, 'recipeSubClass' => 1, 'specializations' => '10656 10658 10660'], // Leatherworking + 186 => ['professionMask' => 0x0100], // Mining + 197 => ['professionMask' => 0x0200, 'recipeSubClass' => 2, 'specializations' => '26798 26801 26797'], // Tailoring + 356 => ['professionMask' => 0x0400, 'recipeSubClass' => 9], // Fishing + 182 => ['professionMask' => 0x0800], // Herbalism + 773 => ['professionMask' => 0x1000, 'recipeSubClass' => 11], // Inscription + 785 => ['name_loc0' => 'Pet - Wasp'], // Pet - Wasp + 781 => ['name_loc2' => 'Familier - diablosaure exotique'], // Pet - Exotic Devilsaur + 758 => ['name_loc6' => 'Mascota: Evento - Control remoto', 'name_loc3' => 'Tier - Ereignis Ferngesteuert', 'categoryId' => 7], // Pet - Event - Remote Control + 788 => ['categoryId' => 7], // Pet - Exotic Spirit Beast + ); - // apply icons - DB::Aowow()->query('UPDATE ?_skillline sl, ?_icons ic, dbc_spellicon si SET sl.iconId = ic.id WHERE sl.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1))'); - DB::Aowow()->query(' - UPDATE - ?_skillline sl, - dbc_spell s, - dbc_skilllineability sla, - ?_icons ic, - dbc_spellicon si - SET - sl.iconId = ic.id - WHERE - (s.effect1Id IN (25, 26, 40) OR s.effect2Id = 60) AND - ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AND - s.iconId = si.id AND - sla.spellId = s.id AND - sl.id = sla.skillLineId - '); - DB::Aowow()->query('UPDATE ?_skillline sl, ?_icons ic SET sl.iconId = ic.id WHERE ic.name = ? AND sl.id = ?d', 'inv_misc_pelt_wolf_01', 393); - DB::Aowow()->query('UPDATE ?_skillline sl, ?_icons ic SET sl.iconId = ic.id WHERE ic.name = ? AND sl.id = ?d', 'inv_misc_key_03', 633); + public function generate(array $ids = []) : bool + { + $baseQuery = ' + REPLACE INTO + ?_skillline + SELECT + id, categoryId, 0, categoryId, name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, description_loc0, description_loc2, description_loc3, description_loc4, description_loc6, description_loc8, 0, iconId, 0, 0, "" + FROM + dbc_skillline'; - return true; -} + DB::Aowow()->query($baseQuery); + + // categorization + DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -5 WHERE id = 777 OR (categoryId = 9 AND id NOT IN (356, 129, 185, 142, 155))'); + DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -4 WHERE categoryId = 9 AND name_loc0 LIKE "%racial%"'); + DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -6 WHERE id IN (778, 788, 758) OR (categoryId = 7 AND name_loc0 LIKE "%pet%")'); + + // more complex fixups + DB::Aowow()->query('UPDATE ?_skillline SET name_loc8 = REPLACE(name_loc8, " - ", ": ") WHERE categoryId = 7 OR id IN (758, 788)'); + DB::Aowow()->query('UPDATE ?_skillline SET cuFlags = ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [142, 148, 149, 150, 152, 155, 183, 533, 553, 554, 713, 769]); + + // apply icons + DB::Aowow()->query('UPDATE ?_skillline sl, ?_icons ic, dbc_spellicon si SET sl.iconId = ic.id WHERE sl.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1))'); + DB::Aowow()->query(' + UPDATE + ?_skillline sl, + dbc_spell s, + dbc_skilllineability sla, + ?_icons ic, + dbc_spellicon si + SET + sl.iconId = ic.id + WHERE + (s.effect1Id IN (25, 26, 40) OR s.effect2Id = 60) AND + ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AND + s.iconId = si.id AND + sla.spellId = s.id AND + sl.id = sla.skillLineId + '); + DB::Aowow()->query('UPDATE ?_skillline sl, ?_icons ic SET sl.iconId = ic.id WHERE ic.name = ? AND sl.id = ?d', 'inv_misc_pelt_wolf_01', 393); + DB::Aowow()->query('UPDATE ?_skillline sl, ?_icons ic SET sl.iconId = ic.id WHERE ic.name = ? AND sl.id = ?d', 'inv_misc_key_03', 633); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/sounds.func.php b/setup/tools/sqlgen/sounds.func.php index 0eee96e7..385e3196 100644 --- a/setup/tools/sqlgen/sounds.func.php +++ b/setup/tools/sqlgen/sounds.func.php @@ -7,421 +7,427 @@ if (!CLI) die('not in cli mode'); -$customData = array( - 15407 => ['cat' => 10] // UR_Algalon_Summon03 (this is not an item pickup) -); -$reqDBC = array( - // base emotes race - 'soundentries', 'emotestextsound', 'vocaluisounds', - // creatures - 'npcsounds', 'creaturesounddata', 'creaturedisplayinfo', 'creaturemodeldata', - // spells - 'spell', 'spellvisual', 'spellvisualkit', - // zones - 'soundambience', 'zonemusic', 'zoneintromusictable', 'worldstatezonesounds', 'areatable', - // items - 'material', 'itemgroupsounds', 'itemdisplayinfo', 'weaponimpactsounds', 'itemsubclass', 'weaponswingsounds2' /*, 'sheathesoundlookups' data is redundant with material..? */ -); - - -function sounds(/*array $ids = [] */) +SqlGen::register(new class extends SetupScript { - /* - okay, here's the thing. WMOAreaTable.dbc references WMO-files to get its position in the world (AreTable) and has sparse information on the related AreaTables themself. - Though it has sets for ZoneAmbience, ZoneMusic and ZoneIntroMusic, these can't be linked for this very reason and are omitted for now. - content: e.g. Tavern Music - */ + use TrCustomData; - // WMOAreaTable.dbc/id => AreaTable.dbc/id - $worldStateZoneSoundFix = array( - 18153 => 2119, - 18154 => 2119, - 47321 => 4273, // The Spark of Imagination - 43600 => 4273, // The Celestial Planetarium - 47478 => 4273 // The Prison of Yogg-Saron + protected $command = 'sounds'; + + protected $dbcSourceFiles = array( + // base emotes race + 'soundentries', 'emotestextsound', 'vocaluisounds', + // creatures + 'npcsounds', 'creaturesounddata', 'creaturedisplayinfo', 'creaturemodeldata', + // spells + 'spell', 'spellvisual', 'spellvisualkit', + // zones + 'soundambience', 'zonemusic', 'zoneintromusictable', 'worldstatezonesounds', 'areatable', + // items + 'material', 'itemgroupsounds', 'itemdisplayinfo', 'weaponimpactsounds', 'itemsubclass', 'weaponswingsounds2' /*, 'sheathesoundlookups' data is redundant with material..? */ ); + private $customData = array( + 15407 => ['cat' => 10] // UR_Algalon_Summon03 (this is not an item pickup) + ); - /***********/ - /* M A I N */ - /***********/ - - CLI::write(' - sounds main data'); - - // file extraction and conversion manually - // moving files in build step. data here is purely structural - // reality check ... thats probably gigabytes worth of sound.. only growing in size with every locale added on top (RedRocketSite didn't do it. Should i then?) - - // .wav => audio/ogg; codecs="vorbis" - // .mp3 => audio/mpeg - - $query = ' - SELECT id AS `id`, `type` AS `cat`, `name`, 0 AS cuFlags, - `file1` AS soundFile1, `file2` AS soundFile2, `file3` AS soundFile3, `file4` AS soundFile4, `file5` AS soundFile5, - `file6` AS soundFile6, `file7` AS soundFile7, `file8` AS soundFile8, `file9` AS soundFile9, `file10` AS soundFile10, - path, flags - FROM dbc_soundentries - WHERE id > ?d LIMIT ?d - '; - - DB::Aowow()->query('TRUNCATE ?_sounds'); - DB::Aowow()->query('TRUNCATE ?_sounds_files'); - - $lastMax = 0; - $soundFileIdx = 0; - $soundIndex = []; - while ($sounds = DB::Aowow()->select($query, $lastMax, SqlGen::$stepSize)) + public function generate(array $ids = []) : bool { - $newMax = max(array_column($sounds, 'id')); + /* + okay, here's the thing. WMOAreaTable.dbc references WMO-files to get its position in the world (AreTable) and has sparse information on the related AreaTables themself. + Though it has sets for ZoneAmbience, ZoneMusic and ZoneIntroMusic, these can't be linked for this very reason and are omitted for now. + content: e.g. Tavern Music + */ - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + // WMOAreaTable.dbc/id => AreaTable.dbc/id + $worldStateZoneSoundFix = array( + 18153 => 2119, + 18154 => 2119, + 47321 => 4273, // The Spark of Imagination + 43600 => 4273, // The Celestial Planetarium + 47478 => 4273 // The Prison of Yogg-Saron + ); - $lastMax = $newMax; - $groupSets = []; - foreach ($sounds as $s) + /***********/ + /* M A I N */ + /***********/ + + CLI::write(' - sounds main data'); + + // file extraction and conversion manually + // moving files in build step. data here is purely structural + // reality check ... thats probably gigabytes worth of sound.. only growing in size with every locale added on top (RedRocketSite didn't do it. Should i then?) + + // .wav => audio/ogg; codecs="vorbis" + // .mp3 => audio/mpeg + + $query = ' + SELECT id AS `id`, `type` AS `cat`, `name`, 0 AS cuFlags, + `file1` AS soundFile1, `file2` AS soundFile2, `file3` AS soundFile3, `file4` AS soundFile4, `file5` AS soundFile5, + `file6` AS soundFile6, `file7` AS soundFile7, `file8` AS soundFile8, `file9` AS soundFile9, `file10` AS soundFile10, + path, flags + FROM dbc_soundentries + WHERE id > ?d LIMIT ?d + '; + + DB::Aowow()->query('TRUNCATE ?_sounds'); + DB::Aowow()->query('TRUNCATE ?_sounds_files'); + + $lastMax = 0; + $soundFileIdx = 0; + $soundIndex = []; + while ($sounds = DB::Aowow()->select($query, $lastMax, SqlGen::$sqlBatchSize)) { - /* attention! + $newMax = max(array_column($sounds, 'id')); - one sound can be used in 20 or more locations but may appear as multiple files, - because of different cases, path being attached to file and other shenanigans + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); - build a usable path and create full index to compensate - 25.6k raw files => expect ~21k filtered files - */ + $lastMax = $newMax; - $fileSets = []; - $hasDupes = false; - for ($i = 1; $i < 11; $i++) + $groupSets = []; + foreach ($sounds as $s) { - $nicePath = CLI::nicePath($s['soundFile'.$i], $s['path']); - if ($s['soundFile'.$i] && array_key_exists($nicePath, $soundIndex)) + /* attention! + + one sound can be used in 20 or more locations but may appear as multiple files, + because of different cases, path being attached to file and other shenanigans + + build a usable path and create full index to compensate + 25.6k raw files => expect ~21k filtered files + */ + + $fileSets = []; + $hasDupes = false; + for ($i = 1; $i < 11; $i++) { - $s['soundFile'.$i] = $soundIndex[$nicePath]; - $hasDupes = true; + $nicePath = CLI::nicePath($s['soundFile'.$i], $s['path']); + if ($s['soundFile'.$i] && array_key_exists($nicePath, $soundIndex)) + { + $s['soundFile'.$i] = $soundIndex[$nicePath]; + $hasDupes = true; + continue; + } + + // convert to something web friendly => ogg + if (stristr($s['soundFile'.$i], '.wav')) + { + $soundIndex[$nicePath] = ++$soundFileIdx; + + $fileSets[] = array( + $soundFileIdx, + $s['soundFile'.$i], + $s['path'], + SOUND_TYPE_OGG + ); + $s['soundFile'.$i] = $soundFileIdx; + } + // mp3 .. keep as is + else if (stristr($s['soundFile'.$i], '.mp3')) + { + $soundIndex[$nicePath] = ++$soundFileIdx; + + $fileSets[] = array( + $soundFileIdx, + $s['soundFile'.$i], + $s['path'], + SOUND_TYPE_MP3 + ); + $s['soundFile'.$i] = $soundFileIdx; + } + // i call bullshit + else if ($s['soundFile'.$i]) + { + CLI::write(' - sound group #'.$s['id'].' "'.$s['name'].'" has invalid sound file "'.$s['soundFile'.$i].'" on index '.$i.'! Skipping...', CLI::LOG_WARN); + $s['soundFile'.$i] = null; + } + // empty case + else + $s['soundFile'.$i] = null; + } + + if (!$fileSets && !$hasDupes) + { + CLI::write(' - sound group #'.$s['id'].' "'.$s['name'].'" contains no sound files! Skipping...', CLI::LOG_WARN); continue; } + else if ($fileSets) + DB::Aowow()->query('INSERT INTO ?_sounds_files VALUES (?a)', array_values($fileSets)); - // convert to something web friendly => ogg - if (stristr($s['soundFile'.$i], '.wav')) - { - $soundIndex[$nicePath] = ++$soundFileIdx; + unset($s['path']); - $fileSets[] = array( - $soundFileIdx, - $s['soundFile'.$i], - $s['path'], - SOUND_TYPE_OGG - ); - $s['soundFile'.$i] = $soundFileIdx; - } - // mp3 .. keep as is - else if (stristr($s['soundFile'.$i], '.mp3')) - { - $soundIndex[$nicePath] = ++$soundFileIdx; - - $fileSets[] = array( - $soundFileIdx, - $s['soundFile'.$i], - $s['path'], - SOUND_TYPE_MP3 - ); - $s['soundFile'.$i] = $soundFileIdx; - } - // i call bullshit - else if ($s['soundFile'.$i]) - { - CLI::write(' - sound group #'.$s['id'].' "'.$s['name'].'" has invalid sound file "'.$s['soundFile'.$i].'" on index '.$i.'! Skipping...', CLI::LOG_WARN); - $s['soundFile'.$i] = null; - } - // empty case - else - $s['soundFile'.$i] = null; + $groupSets[] = array_values($s); } - if (!$fileSets && !$hasDupes) - { - CLI::write(' - sound group #'.$s['id'].' "'.$s['name'].'" contains no sound files! Skipping...', CLI::LOG_WARN); - continue; - } - else if ($fileSets) - DB::Aowow()->query('INSERT INTO ?_sounds_files VALUES (?a)', array_values($fileSets)); - - unset($s['path']); - - $groupSets[] = array_values($s); + DB::Aowow()->query('REPLACE INTO ?_sounds VALUES (?a)', array_values($groupSets)); } - DB::Aowow()->query('REPLACE INTO ?_sounds VALUES (?a)', array_values($groupSets)); - } + + /******************/ + /* VocalUI Sounds */ + /******************/ + + CLI::write(' - linking to race'); + + DB::Aowow()->query('TRUNCATE ?_races_sounds'); + DB::Aowow()->query('INSERT IGNORE INTO ?_races_sounds SELECT raceId, soundIdMale, 1 FROM dbc_vocaluisounds WHERE soundIdMale <> soundIdFemale AND soundIdMale > 0'); + DB::Aowow()->query('INSERT IGNORE INTO ?_races_sounds SELECT raceId, soundIdFemale, 2 FROM dbc_vocaluisounds WHERE soundIdMale <> soundIdFemale AND soundIdFemale > 0'); + + // ps: im too dumb to union this - /******************/ - /* VocalUI Sounds */ - /******************/ + /***************/ + /* Emote Sound */ + /***************/ - CLI::write(' - linking to race'); + CLI::write(' - linking to emotes'); - DB::Aowow()->query('TRUNCATE ?_races_sounds'); - DB::Aowow()->query('INSERT IGNORE INTO ?_races_sounds SELECT raceId, soundIdMale, 1 FROM dbc_vocaluisounds WHERE soundIdMale <> soundIdFemale AND soundIdMale > 0'); - DB::Aowow()->query('INSERT IGNORE INTO ?_races_sounds SELECT raceId, soundIdFemale, 2 FROM dbc_vocaluisounds WHERE soundIdMale <> soundIdFemale AND soundIdFemale > 0'); - - // ps: im too dumb to union this + DB::Aowow()->query('TRUNCATE ?_emotes_sounds'); + DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_sounds SELECT emotesTextId, raceId, gender + 1, soundId FROM dbc_emotestextsound'); - /***************/ - /* Emote Sound */ - /***************/ + /*******************/ + /* Creature Sounds */ + /*******************/ - CLI::write(' - linking to emotes'); + CLI::write(' - linking to creatures'); - DB::Aowow()->query('TRUNCATE ?_emotes_sounds'); - DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_sounds SELECT emotesTextId, raceId, gender + 1, soundId FROM dbc_emotestextsound'); + // currently ommitting: + // * footsteps (matrix of: creature + terrain + humidity) + // * fidget2 through 5 + // * customattack2 through 3 + // in case of conflicting data CreatureDisplayInfo overrides CreatureModelData (seems to be more specialized (Thral > MaleOrc / Maiden > FemaleTitan)) + + DB::Aowow()->query('TRUNCATE ?_creature_sounds'); + DB::Aowow()->query(' + INSERT INTO + ?_creature_sounds (`id`, `greeting`, `farewell`, `angry`, `exertion`, `exertioncritical`, `injury`, `injurycritical`, `death`, `stun`, `stand`, `aggro`, `wingflap`, `wingglide`, `alert`, `fidget`, `customattack`, `loop`, `jumpstart`, `jumpend`, `petattack`, `petorder`, `petdismiss`, `birth`, `spellcast`, `submerge`, `submerged`) + SELECT + cdi.id, + IFNULL(ns.greetSoundId, 0), + IFNULL(ns.byeSoundId, 0), + IFNULL(ns.angrySoundId, 0), + IF(csdA.exertion, csdA.exertion, IFNULL(csdB.exertion, 0)), + IF(csdA.exertionCritical, csdA.exertionCritical, IFNULL(csdB.exertionCritical, 0)), + IF(csdA.injury, csdA.injury, IFNULL(csdB.injury, 0)), + IF(csdA.injuryCritical, csdA.injuryCritical, IFNULL(csdB.injuryCritical, 0)), + IF(csdA.death, csdA.death, IFNULL(csdB.death, 0)), + IF(csdA.stun, csdA.stun, IFNULL(csdB.stun, 0)), + IF(csdA.stand, csdA.stand, IFNULL(csdB.stand, 0)), + IF(csdA.aggro, csdA.aggro, IFNULL(csdB.aggro, 0)), + IF(csdA.wingFlap, csdA.wingFlap, IFNULL(csdB.wingFlap, 0)), + IF(csdA.wingGlide, csdA.wingGlide, IFNULL(csdB.wingGlide, 0)), + IF(csdA.alert, csdA.alert, IFNULL(csdB.alert, 0)), + IF(csdA.fidget, csdA.fidget, IFNULL(csdB.fidget, 0)), + IF(csdA.customAttack, csdA.customAttack, IFNULL(csdB.customAttack, 0)), + IF(csdA.loop, csdA.loop, IFNULL(csdB.loop, 0)), + IF(csdA.jumpStart, csdA.jumpStart, IFNULL(csdB.jumpStart, 0)), + IF(csdA.jumpEnd, csdA.jumpEnd, IFNULL(csdB.jumpEnd, 0)), + IF(csdA.petAttack, csdA.petAttack, IFNULL(csdB.petAttack, 0)), + IF(csdA.petOrder, csdA.petOrder, IFNULL(csdB.petOrder, 0)), + IF(csdA.petDismiss, csdA.petDismiss, IFNULL(csdB.petDismiss, 0)), + IF(csdA.birth, csdA.birth, IFNULL(csdB.birth, 0)), + IF(csdA.spellcast, csdA.spellcast, IFNULL(csdB.spellcast, 0)), + IF(csdA.submerge, csdA.submerge, IFNULL(csdB.submerge, 0)), + IF(csdA.submerged, csdA.submerged, IFNULL(csdB.submerged, 0)) + FROM + dbc_creaturedisplayinfo cdi + LEFT JOIN + dbc_creaturemodeldata cmd ON cmd.id = cdi.modelId + LEFT JOIN + dbc_creaturesounddata csdA ON cdi.creatureSoundId = csdA.id + LEFT JOIN + dbc_creaturesounddata csdB ON cmd.creatureSoundId = csdB.id + LEFT JOIN + dbc_npcsounds ns ON cdi.npcSoundId = ns.id + '); - /*******************/ - /* Creature Sounds */ - /*******************/ + /****************/ + /* Spell Sounds */ + /****************/ - CLI::write(' - linking to creatures'); + CLI::write(' - linking to spells'); - // currently ommitting: - // * footsteps (matrix of: creature + terrain + humidity) - // * fidget2 through 5 - // * customattack2 through 3 - // in case of conflicting data CreatureDisplayInfo overrides CreatureModelData (seems to be more specialized (Thral > MaleOrc / Maiden > FemaleTitan)) + // issues: (probably because of 335-data) + // * animate is probably wrong + // * missile and impactarea not in js + // * ready, castertargeting, casterstate and targetstate not in dbc - DB::Aowow()->query('TRUNCATE ?_creature_sounds'); - DB::Aowow()->query(' - INSERT INTO - ?_creature_sounds (`id`, `greeting`, `farewell`, `angry`, `exertion`, `exertioncritical`, `injury`, `injurycritical`, `death`, `stun`, `stand`, `aggro`, `wingflap`, `wingglide`, `alert`, `fidget`, `customattack`, `loop`, `jumpstart`, `jumpend`, `petattack`, `petorder`, `petdismiss`, `birth`, `spellcast`, `submerge`, `submerged`) - SELECT - cdi.id, - IFNULL(ns.greetSoundId, 0), - IFNULL(ns.byeSoundId, 0), - IFNULL(ns.angrySoundId, 0), - IF(csdA.exertion, csdA.exertion, IFNULL(csdB.exertion, 0)), - IF(csdA.exertionCritical, csdA.exertionCritical, IFNULL(csdB.exertionCritical, 0)), - IF(csdA.injury, csdA.injury, IFNULL(csdB.injury, 0)), - IF(csdA.injuryCritical, csdA.injuryCritical, IFNULL(csdB.injuryCritical, 0)), - IF(csdA.death, csdA.death, IFNULL(csdB.death, 0)), - IF(csdA.stun, csdA.stun, IFNULL(csdB.stun, 0)), - IF(csdA.stand, csdA.stand, IFNULL(csdB.stand, 0)), - IF(csdA.aggro, csdA.aggro, IFNULL(csdB.aggro, 0)), - IF(csdA.wingFlap, csdA.wingFlap, IFNULL(csdB.wingFlap, 0)), - IF(csdA.wingGlide, csdA.wingGlide, IFNULL(csdB.wingGlide, 0)), - IF(csdA.alert, csdA.alert, IFNULL(csdB.alert, 0)), - IF(csdA.fidget, csdA.fidget, IFNULL(csdB.fidget, 0)), - IF(csdA.customAttack, csdA.customAttack, IFNULL(csdB.customAttack, 0)), - IF(csdA.loop, csdA.loop, IFNULL(csdB.loop, 0)), - IF(csdA.jumpStart, csdA.jumpStart, IFNULL(csdB.jumpStart, 0)), - IF(csdA.jumpEnd, csdA.jumpEnd, IFNULL(csdB.jumpEnd, 0)), - IF(csdA.petAttack, csdA.petAttack, IFNULL(csdB.petAttack, 0)), - IF(csdA.petOrder, csdA.petOrder, IFNULL(csdB.petOrder, 0)), - IF(csdA.petDismiss, csdA.petDismiss, IFNULL(csdB.petDismiss, 0)), - IF(csdA.birth, csdA.birth, IFNULL(csdB.birth, 0)), - IF(csdA.spellcast, csdA.spellcast, IFNULL(csdB.spellcast, 0)), - IF(csdA.submerge, csdA.submerge, IFNULL(csdB.submerge, 0)), - IF(csdA.submerged, csdA.submerged, IFNULL(csdB.submerged, 0)) - FROM - dbc_creaturedisplayinfo cdi - LEFT JOIN - dbc_creaturemodeldata cmd ON cmd.id = cdi.modelId - LEFT JOIN - dbc_creaturesounddata csdA ON cdi.creatureSoundId = csdA.id - LEFT JOIN - dbc_creaturesounddata csdB ON cmd.creatureSoundId = csdB.id - LEFT JOIN - dbc_npcsounds ns ON cdi.npcSoundId = ns.id - '); + DB::Aowow()->query('TRUNCATE ?_spell_sounds'); + DB::Aowow()->query(' + INSERT INTO + ?_spell_sounds (`id`, `precast`, `cast`, `impact`, `state`, `statedone`, `channel`, `missile`, `animation`, `casterimpact`, `targetimpact`, `missiletargeting`, `instantarea`, `impactarea`, `persistentarea`) + SELECT + sv.id, + IFNULL(svk1.soundId, 0), + IFNULL(svk2.soundId, 0), + IFNULL(svk3.soundId, 0), + IFNULL(svk4.soundId, 0), + IFNULL(svk5.soundId, 0), + IFNULL(svk6.soundId, 0), + missileSoundId, + animationSoundId, + IFNULL(svk7.soundId, 0), + IFNULL(svk8.soundId, 0), + IFNULL(svk9.soundId, 0), + IFNULL(svk10.soundId, 0), + IFNULL(svk11.soundId, 0), + IFNULL(svk12.soundId, 0) + FROM + dbc_spellvisual sv + LEFT JOIN + dbc_spellvisualkit svk1 ON svk1.id = sv.precastKitId + LEFT JOIN + dbc_spellvisualkit svk2 ON svk2.id = sv.castKitId + LEFT JOIN + dbc_spellvisualkit svk3 ON svk3.id = sv.impactKitId + LEFT JOIN + dbc_spellvisualkit svk4 ON svk4.id = sv.stateKitId + LEFT JOIN + dbc_spellvisualkit svk5 ON svk5.id = sv.statedoneKitId + LEFT JOIN + dbc_spellvisualkit svk6 ON svk6.id = sv.channelKitId + LEFT JOIN + dbc_spellvisualkit svk7 ON svk7.id = sv.casterImpactKitId + LEFT JOIN + dbc_spellvisualkit svk8 ON svk8.id = sv.targetImpactKitId + LEFT JOIN + dbc_spellvisualkit svk9 ON svk9.id = sv.missileTargetingKitId + LEFT JOIN + dbc_spellvisualkit svk10 ON svk10.id = sv.instantAreaKitId + LEFT JOIN + dbc_spellvisualkit svk11 ON svk11.id = sv.impactAreaKitId + LEFT JOIN + dbc_spellvisualkit svk12 ON svk12.id = sv.persistentAreaKitId + '); - /****************/ - /* Spell Sounds */ - /****************/ + /***************/ + /* Zone Sounds */ + /***************/ - CLI::write(' - linking to spells'); + CLI::write(' - linking to zones'); - // issues: (probably because of 335-data) - // * animate is probably wrong - // * missile and impactarea not in js - // * ready, castertargeting, casterstate and targetstate not in dbc + // omiting data from WMOAreaTable, as its at the moment impossible to link to actual zones - DB::Aowow()->query('TRUNCATE ?_spell_sounds'); - DB::Aowow()->query(' - INSERT INTO - ?_spell_sounds (`id`, `precast`, `cast`, `impact`, `state`, `statedone`, `channel`, `missile`, `animation`, `casterimpact`, `targetimpact`, `missiletargeting`, `instantarea`, `impactarea`, `persistentarea`) - SELECT - sv.id, - IFNULL(svk1.soundId, 0), - IFNULL(svk2.soundId, 0), - IFNULL(svk3.soundId, 0), - IFNULL(svk4.soundId, 0), - IFNULL(svk5.soundId, 0), - IFNULL(svk6.soundId, 0), - missileSoundId, - animationSoundId, - IFNULL(svk7.soundId, 0), - IFNULL(svk8.soundId, 0), - IFNULL(svk9.soundId, 0), - IFNULL(svk10.soundId, 0), - IFNULL(svk11.soundId, 0), - IFNULL(svk12.soundId, 0) - FROM - dbc_spellvisual sv - LEFT JOIN - dbc_spellvisualkit svk1 ON svk1.id = sv.precastKitId - LEFT JOIN - dbc_spellvisualkit svk2 ON svk2.id = sv.castKitId - LEFT JOIN - dbc_spellvisualkit svk3 ON svk3.id = sv.impactKitId - LEFT JOIN - dbc_spellvisualkit svk4 ON svk4.id = sv.stateKitId - LEFT JOIN - dbc_spellvisualkit svk5 ON svk5.id = sv.statedoneKitId - LEFT JOIN - dbc_spellvisualkit svk6 ON svk6.id = sv.channelKitId - LEFT JOIN - dbc_spellvisualkit svk7 ON svk7.id = sv.casterImpactKitId - LEFT JOIN - dbc_spellvisualkit svk8 ON svk8.id = sv.targetImpactKitId - LEFT JOIN - dbc_spellvisualkit svk9 ON svk9.id = sv.missileTargetingKitId - LEFT JOIN - dbc_spellvisualkit svk10 ON svk10.id = sv.instantAreaKitId - LEFT JOIN - dbc_spellvisualkit svk11 ON svk11.id = sv.impactAreaKitId - LEFT JOIN - dbc_spellvisualkit svk12 ON svk12.id = sv.persistentAreaKitId - '); + DB::Aowow()->query('TRUNCATE ?_zones_sounds'); + DB::Aowow()->query(' + INSERT INTO + ?_zones_sounds (id, ambienceDay, ambienceNight, musicDay, musicNight, intro, worldStateId, worldStateValue) + SELECT + a.id, + IFNULL(sa1.soundIdDay, 0), + IFNULL(sa1.soundIdNight, 0), + IFNULL(zm1.soundIdDay, 0), + IFNULL(zm1.soundIdNight, 0), + IFNULL(zimt1.soundId, 0), + 0, + 0 + FROM + dbc_areatable a + LEFT JOIN + dbc_soundambience sa1 ON sa1.id = a.soundAmbience + LEFT JOIN + dbc_zonemusic zm1 ON zm1.id = a.zoneMusic + LEFT JOIN + dbc_zoneintromusictable zimt1 ON zimt1.id = a.zoneIntroMusic + WHERE + a.soundAmbience > 0 OR a.zoneMusic > 0 OR a.zoneIntroMusic + UNION + SELECT + IF(wszs.areaId, wszs.areaId, wszs.wmoAreaId), + IFNULL(sa2.soundIdDay, 0), + IFNULL(sa2.soundIdNight, 0), + IFNULL(zm2.soundIdDay, 0), + IFNULL(zm2.soundIdNight, 0), + IFNULL(zimt2.soundId, 0), + wszs.stateId, + wszs.value + FROM + dbc_worldstatezonesounds wszs + LEFT JOIN + dbc_soundambience sa2 ON sa2.id = wszs.soundAmbienceId + LEFT JOIN + dbc_zonemusic zm2 ON zm2.id = wszs.zoneMusicId + LEFT JOIN + dbc_zoneintromusictable zimt2 ON zimt2.id = wszs.zoneIntroMusicId + WHERE + wszs.zoneMusicId > 0 AND (wszs.areaId OR wszs.wmoAreaId IN (?a)) + ', array_keys($worldStateZoneSoundFix)); + + // apply post-fix + foreach ($worldStateZoneSoundFix as $old => $new) + DB::Aowow()->query('UPDATE ?_zones_sounds SET id = ?d WHERE id = ?d', $new, $old); - /***************/ - /* Zone Sounds */ - /***************/ + /***************/ + /* Item Sounds */ + /***************/ - CLI::write(' - linking to zones'); + CLI::write(' - linking to items'); - // omiting data from WMOAreaTable, as its at the moment impossible to link to actual zones + DB::Aowow()->query(' + UPDATE + ?_items i + LEFT JOIN + dbc_itemdisplayinfo idi ON + idi.id = i.displayId + LEFT JOIN + dbc_itemgroupsounds igs ON + igs.id = idi.groupSoundId + LEFT JOIN + dbc_material m ON + m.id = i.material + SET + i.spellVisualId = IFNULL(idi.spellVisualId, 0), + i.pickUpSoundId = IFNULL(igs.pickUpSoundId, 0), + i.dropDownSoundId = IFNULL(igs.dropDownSoundId, 0), + i.sheatheSoundId = IFNULL(m.sheatheSoundId, 0), + i.unsheatheSoundId = IFNULL(m.unsheatheSoundId, 0) + '); - DB::Aowow()->query('TRUNCATE ?_zones_sounds'); - DB::Aowow()->query(' - INSERT INTO - ?_zones_sounds (id, ambienceDay, ambienceNight, musicDay, musicNight, intro, worldStateId, worldStateValue) - SELECT - a.id, - IFNULL(sa1.soundIdDay, 0), - IFNULL(sa1.soundIdNight, 0), - IFNULL(zm1.soundIdDay, 0), - IFNULL(zm1.soundIdNight, 0), - IFNULL(zimt1.soundId, 0), - 0, - 0 - FROM - dbc_areatable a - LEFT JOIN - dbc_soundambience sa1 ON sa1.id = a.soundAmbience - LEFT JOIN - dbc_zonemusic zm1 ON zm1.id = a.zoneMusic - LEFT JOIN - dbc_zoneintromusictable zimt1 ON zimt1.id = a.zoneIntroMusic - WHERE - a.soundAmbience > 0 OR a.zoneMusic > 0 OR a.zoneIntroMusic - UNION - SELECT - IF(wszs.areaId, wszs.areaId, wszs.wmoAreaId), - IFNULL(sa2.soundIdDay, 0), - IFNULL(sa2.soundIdNight, 0), - IFNULL(zm2.soundIdDay, 0), - IFNULL(zm2.soundIdNight, 0), - IFNULL(zimt2.soundId, 0), - wszs.stateId, - wszs.value - FROM - dbc_worldstatezonesounds wszs - LEFT JOIN - dbc_soundambience sa2 ON sa2.id = wszs.soundAmbienceId - LEFT JOIN - dbc_zonemusic zm2 ON zm2.id = wszs.zoneMusicId - LEFT JOIN - dbc_zoneintromusictable zimt2 ON zimt2.id = wszs.zoneIntroMusicId - WHERE - wszs.zoneMusicId > 0 AND (wszs.areaId OR wszs.wmoAreaId IN (?a)) - ', array_keys($worldStateZoneSoundFix)); + DB::Aowow()->query('TRUNCATE ?_items_sounds'); - // apply post-fix - foreach ($worldStateZoneSoundFix as $old => $new) - DB::Aowow()->query('UPDATE ?_zones_sounds SET id = ?d WHERE id = ?d', $new, $old); - - - /***************/ - /* Item Sounds */ - /***************/ - - CLI::write(' - linking to items'); - - DB::Aowow()->query(' - UPDATE - ?_items i - LEFT JOIN - dbc_itemdisplayinfo idi ON - idi.id = i.displayId - LEFT JOIN - dbc_itemgroupsounds igs ON - igs.id = idi.groupSoundId - LEFT JOIN - dbc_material m ON - m.id = i.material - SET - i.spellVisualId = IFNULL(idi.spellVisualId, 0), - i.pickUpSoundId = IFNULL(igs.pickUpSoundId, 0), - i.dropDownSoundId = IFNULL(igs.dropDownSoundId, 0), - i.sheatheSoundId = IFNULL(m.sheatheSoundId, 0), - i.unsheatheSoundId = IFNULL(m.unsheatheSoundId, 0) - '); - - DB::Aowow()->query('TRUNCATE ?_items_sounds'); - - $fields = ['hit', 'crit']; - foreach ($fields as $f) - { - for ($i = 1; $i <= 10; $i++) + $fields = ['hit', 'crit']; + foreach ($fields as $f) { - DB::Aowow()->query(' - INSERT INTO - ?_items_sounds - SELECT - ?#, - (1 << wis.subClass) - FROM - dbc_weaponimpactsounds wis - WHERE - ?# > 0 - ON DUPLICATE KEY UPDATE - subClassMask = subClassMask | (1 << wis.subClass) - ', $f.$i, $f.$i); + for ($i = 1; $i <= 10; $i++) + { + DB::Aowow()->query(' + INSERT INTO + ?_items_sounds + SELECT + ?#, + (1 << wis.subClass) + FROM + dbc_weaponimpactsounds wis + WHERE + ?# > 0 + ON DUPLICATE KEY UPDATE + subClassMask = subClassMask | (1 << wis.subClass) + ', $f.$i, $f.$i); + } } + + DB::Aowow()->query(' + INSERT INTO + ?_items_sounds + SELECT + wss.soundId, + (1 << isc.subClass) + FROM + dbc_itemsubclass isc + JOIN + dbc_weaponswingsounds2 wss ON + wss.weaponSize = isc.weaponSize + WHERE + isc.class = 2 + ON DUPLICATE KEY UPDATE + subClassMask = subClassMask | (1 << isc.subClass) + '); + + return true; } - - - DB::Aowow()->query(' - INSERT INTO - ?_items_sounds - SELECT - wss.soundId, - (1 << isc.subClass) - FROM - dbc_itemsubclass isc - JOIN - dbc_weaponswingsounds2 wss ON - wss.weaponSize = isc.weaponSize - WHERE - isc.class = 2 - ON DUPLICATE KEY UPDATE - subClassMask = subClassMask | (1 << isc.subClass) - '); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/source.func.php b/setup/tools/sqlgen/source.func.php index c21b7631..f7eec211 100644 --- a/setup/tools/sqlgen/source.func.php +++ b/setup/tools/sqlgen/source.func.php @@ -7,49 +7,15 @@ if (!CLI) die('not in cli mode'); -/* deps: - * reference_loot_template - * item_loot_template - * creature_loot_template - * gameobject_loot_template - * mail_loot_template - * disenchant_loot_template - * fishing_loot_template - * skinning_loot_template - * milling_loot_template - * prospecting_loot_template - * pickpocketing_loot_template - - * item_template - * creature_template - * gameobject_template - * quest_template - * quest_template_addon - * skill_perfect_item_template - - * npc_trainer - * npc_vendor - * game_event_npc_vendor - * creature - - * playercreateinfo_item - * playercreateinfo_skill - * achievement_reward - * skill_discovery_template -*/ - -$customData = array( -); -$reqDBC = ['charstartoutfit', 'talent', 'spell', 'skilllineability', 'itemextendedcost', 'lock']; - -function source(array $ids = []) +SqlGen::register(new class extends SetupScript { - $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)'; + protected $command = 'source'; - // please note, this workes without checks, because we do not use strings here - function queryfy($ph, array $data, $query) + protected $tblDependancyAowow = ['spell', 'achievement']; + protected $tblDependancyTC = ['playercreateinfo_skills', 'playercreateinfo_item', 'skill_discovery_template', 'achievement_reward', 'skill_perfect_item_template', 'item_template', 'gameobject_template', 'quest_template', 'quest_template_addon', 'creature_template', 'creature', 'npc_trainer', 'npc_vendor', 'game_event_npc_vendor', 'reference_loot_template', 'item_loot_template', 'creature_loot_template', 'gameobject_loot_template', 'mail_loot_template', 'disenchant_loot_template', 'fishing_loot_template', 'skinning_loot_template', 'milling_loot_template', 'prospecting_loot_template', 'pickpocketing_loot_template']; + protected $dbcSourceFiles = ['charstartoutfit', 'talent', 'spell', 'skilllineability', 'itemextendedcost', 'lock']; + + private function queryfy(array $data, string $query) : string { $buff = []; @@ -61,10 +27,10 @@ function source(array $ids = []) foreach ($data as $d) $buff[] = '('.implode(', ', $d ?: 'NULL').')'; - return str_replace($ph, implode(', ', $buff), $query); + return str_replace('[V]', implode(', ', $buff), $query); } - function pushBuffer(&$buff, $type, $typeId, $mType = 0, $mTypeId = 0, $src = 1) + private function pushBuffer(array &$buff, int $type, int $typeId, int $mType = 0, int $mTypeId = 0, int $src = 1) : void { $b = &$buff[$typeId]; @@ -81,7 +47,7 @@ function source(array $ids = []) $b = [$type, $typeId, $src, null, null]; } - function taughtSpell($item) + private function taughtSpell(array $item) : int { # spelltrigger_X (0: onUse; 6: onLearnSpell) # spell: 483 & 55884 are learn spells @@ -101,1113 +67,1120 @@ function source(array $ids = []) 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 */ - /***************************/ - - CLI::write(' - Items & Spells [inherited]'); - # also everything from items that teach spells, is src of spell - # todo: check if items have learn-spells (effect: 36) - - CLI::write(' * 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) + public function generate(array $ids = []) : bool { - $hasChanged = false; - foreach ($refLoot as $entry => &$refData) - { - foreach ($refData as $itemOrRef => $data) - { - if ($itemOrRef > 0) - continue; + $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)'; - if (!empty($refLoot[-$itemOrRef])) + // 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 */ + /***************************/ + + CLI::write(' - Items & Spells [inherited]'); + # also everything from items that teach spells, is src of spell + # todo: check if items have learn-spells (effect: 36) + + CLI::write(' * 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) { - foreach ($refLoot[-$itemOrRef] AS $key => $data) + if ($itemOrRef > 0) + continue; + + if (!empty($refLoot[-$itemOrRef])) { - if (!empty($refData[$key])) - $refData[$key]['qty'] += $data['qty']; - else - $refLoot[-$itemOrRef][$key] = $data; + 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 # + ############### + CLI::write(' * #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] + ); + + // assume unique craft spells per item + if ($perfItems = DB::World()->selectCol('SELECT perfectItemType AS ARRAY_KEY, spellId AS spell FROM skill_perfect_item_template')) + foreach ($perfItems AS $item => $spell) + $itemSpells[$item] = $spell; + + $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 ($_ = $this->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($this->queryfy($itemBuff, $insMore), 1, 1, 1); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 1, 1, 1); + + + ############ + # 2: Drop # + ############ + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); } - unset($refData[$itemOrRef]); - $hasChanged = true; - } - } - } - - - ############### - # 1: Crafted # - ############### - CLI::write(' * #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] - ); - - // assume unique craft spells per item - if ($perfItems = DB::World()->selectCol('SELECT perfectItemType AS ARRAY_KEY, spellId AS spell FROM skill_perfect_item_template')) - foreach ($perfItems AS $item => $spell) - $itemSpells[$item] = $spell; - - $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 # - ############ - CLI::write(' * #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'] /*, $lootmode */); - - pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); - } - - continue; - } - - if ($_ = taughtSpell($l)) - pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); - - pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); - } - - $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) - ########### - CLI::write(' * #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 # - ############# - CLI::write(' * #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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardItem4 > 0 GROUP BY item UNION - SELECT StartItem AS item, ID, COUNT(1) AS qty, IF(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE StartItem > 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.AllowableRaces & 0x2B2 AND !(qt.AllowableRaces & 0x44D), 2, IF(qt.AllowableRaces & 0x44D AND !(qt.AllowableRaces & 0x2B2), 1, 3))) AS side - FROM - mail_loot_template mlt - JOIN - quest_template_addon qta ON qta.RewardMailTemplateId = mlt.entry - JOIN - quest_template qt ON qt.ID = qta.ID - LEFT JOIN - item_template it ON it.entry = mlt.Item AND mlt.Reference <= 0 - WHERE - qta.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) - ############## - CLI::write(' * #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 # - ############### - CLI::write(' * #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 # - ################### - CLI::write(' * #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.ItemID) AS item, ar.ID AS entry - FROM achievement_reward ar LEFT JOIN mail_loot_template mlt ON mlt.entry = ar.MailTemplateID - WHERE ar.MailTemplateID > 0 OR ar.ItemID > 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 # - #################### - CLI::write(' * #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 # - ############## - CLI::write(' * #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 # - ################ - CLI::write(' * #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 # - ############## - CLI::write(' * #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 # - ############# - CLI::write(' * #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 # - ################## - CLI::write(' * #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 # - ################## - CLI::write(' * #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 # - ################ - CLI::write(' * #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 # - ############### - CLI::write(' * #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); - - - // flagging aowow_items for source (note: this is not exact! creatures dropping items may not be spawnd, quests granting items may be disabled) - DB::Aowow()->query('UPDATE ?_items SET cuFlags = cuFlags & ?d', ~CUSTOM_UNAVAILABLE); - DB::Aowow()->query('UPDATE ?_items i LEFT JOIN ?_source s ON s.typeId = i.id AND s.type = ?d SET i.cuFlags = i.cuFlags | ?d WHERE s.typeId IS NULL', TYPE_ITEM, CUSTOM_UNAVAILABLE); - - /*********/ - /* Spell */ - /*********/ - - CLI::write(' - Spells [original]'); - - # 4: Quest - CLI::write(' * #4 Quest'); - $quests = DB::World()->select(' - SELECT spell AS ARRAY_KEY, id, SUM(qty) AS qty, BIT_OR(side) AS side FROM ( - SELECT IF(RewardSpell = 0, RewardDisplaySpell, RewardSpell) AS spell, ID, COUNT(1) AS qty, IF(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE IF(RewardSpell = 0, RewardDisplaySpell, RewardSpell) > 0 GROUP BY spell - UNION - SELECT qta.SourceSpellId AS spell, qt.ID, COUNT(1) AS qty, IF(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template qt JOIN quest_template_addon qta ON qta.ID = qt.ID WHERE qta.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 - CLI::write(' * #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); + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry'] /*, $lootmode */); } - DB::Aowow()->query(queryfy('[V]', $buff, $insMore), 6, 6, 6); - } + $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 + ); - # 7: Discovery - CLI::write(' * #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 - CLI::write(' * #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) - { - CLI::write(' - '.++$n.'. pass'); - - $recurse = []; - foreach ($tSpells as $tId => $spell) + foreach ($objectLoot as $roi => $l) { - for ($i = 1; $i <= 3; $i++) - if ($spell['effect'.$i.'Id'] == 36) // effect: learnSpell - $recurse[$spell['effect'.$i.'TriggerSpell']] = $tId; + if ($roi < 0 && !empty($refLoot[-$roi])) + { + foreach ($refLoot[-$roi] as $iId => $r) + { + if ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); - if (array_search($tId, $recurse)) - unset($tSpells[$tId]); + $objectOT[] = $iId; + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); + + $objectOT[] = $roi; + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); } - foreach ($tSpells as $tId => $__) - $buff[$tId] = [TYPE_SPELL, $tId, 1]; + $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 + '); - if (!$recurse) - break; + foreach ($itemLoot as $roi => $l) + { + if ($roi < 0 && !empty($refLoot[-$roi])) + { + foreach ($refLoot[-$roi] as $iId => $r) + { + if ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']); - $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)); + $itemOT[] = $iId; + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']); + + $itemOT[] = $roi; + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_ITEM, $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 2, 2, 2); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($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) + ########### + CLI::write(' * #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 ($_ = $this->taughtSpell($v)) + $spellBuff[$_] = [TYPE_SPELL, $_, 1]; + + $itemBuff[$iId] = [TYPE_ITEM, $iId, 1]; + } + + foreach (DB::World()->select($vendorQuery, $xCostH, $xCostH) as $iId => $v) + { + if ($_ = $this->taughtSpell($v)) + $spellBuff[$_] = [TYPE_SPELL, $_, 2]; + + $itemBuff[$iId] = [TYPE_ITEM, $iId, 2]; + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insBasic), 3, 3, 3); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insBasic), 3, 3, 3); + + + ############# + # 4: Quest # + ############# + CLI::write(' * #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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 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(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE RewardItem4 > 0 GROUP BY item UNION + SELECT StartItem AS item, ID, COUNT(1) AS qty, IF(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE StartItem > 0 GROUP BY item + ) n JOIN item_template it ON it.entry = n.item + GROUP BY item' + ); + foreach ($quests as $iId => $q) + { + if ($_ = $this->taughtSpell($q)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $q['qty'] > 1 ? 0 : TYPE_QUEST, $q['quest'], $q['side']); + + $this->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.AllowableRaces & 0x2B2 AND !(qt.AllowableRaces & 0x44D), 2, IF(qt.AllowableRaces & 0x44D AND !(qt.AllowableRaces & 0x2B2), 1, 3))) AS side + FROM + mail_loot_template mlt + JOIN + quest_template_addon qta ON qta.RewardMailTemplateId = mlt.entry + JOIN + quest_template qt ON qt.ID = qta.ID + LEFT JOIN + item_template it ON it.entry = mlt.Item AND mlt.Reference <= 0 + WHERE + qta.RewardMailTemplateId > 0 + GROUP BY + ARRAY_KEY + '); + + foreach ($mailLoot as $roi => $l) + { + if ($roi < 0 && !empty($refLoot[-$roi])) + { + foreach ($refLoot[-$roi] as $iId => $r) + { + if ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']); + + $itemOT[] = $iId; + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']); + + $itemOT[] = $roi; + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_QUEST, $l['entry'], $l['side']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 4, 4, 4); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 4, 4, 4); + + + ############## + # 5: Vendor # (w/o xCost Arena/Honor) + ############## + CLI::write(' * #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 ($_ = $this->taughtSpell($v)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $v['qty'] > 1 ? 0 : TYPE_NPC, $v['npc']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $v['qty'] > 1 ? 0 : TYPE_NPC, $v['npc']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 5, 5, 5); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 5, 5, 5); + + + ############### + # 10: Starter # + ############### + CLI::write(' * #10 Starter'); + + if ($pcii = DB::World()->select('SELECT ?d, itemid, 1 FROM playercreateinfo_item', TYPE_ITEM)) + DB::Aowow()->query($this->queryfy($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 # + ################### + CLI::write(' * #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.ItemID) AS item, ar.ID AS entry + FROM achievement_reward ar LEFT JOIN mail_loot_template mlt ON mlt.entry = ar.MailTemplateID + WHERE ar.MailTemplateID > 0 OR ar.ItemID > 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 ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $xItems[$iId]['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $xItems[$iId]['entry']); + + $this->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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $l['qty'] > 1 ? 0 : TYPE_ACHIEVEMENT, $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 12, 12, 12); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 12, 12, 12); + + + #################### + # 15: Disenchanted # + #################### + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 15, 15, 15); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 15, 15, 15); + + + ############## + # 16: Fished # + ############## + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_OBJECT, $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 16, 16, 16); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 16, 16, 16); + + + ################ + # 17: Gathered # + ################ + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 17, 17, 17); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 17, 17, 17); + + + ############## + # 18: Milled # + ############## + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 18, 18, 18); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 18, 18, 18); + + + ############# + # 19: Mined # + ############# + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : $l['srcType'], $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 19, 19, 19); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 19, 19, 19); + + + ################## + # 20: Prospected # + ################## + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 20, 20, 20); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 20, 20, 20); + + + ################## + # 21: Pickpocket # + ################## + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 21, 21, 21); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 21, 21, 21); + + + ################ + # 22: Salvaged # + ################ + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 22, 22, 22); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 22, 22, 22); + + + ############### + # 23: Skinned # + ############### + CLI::write(' * #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 ($_ = $this->taughtSpell($r)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $iId, $r['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + } + + continue; + } + + if ($_ = $this->taughtSpell($l)) + $this->pushBuffer($spellBuff, TYPE_SPELL, $_, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + + $this->pushBuffer($itemBuff, TYPE_ITEM, $roi, $l['qty'] > 1 ? 0 : TYPE_NPC, $l['entry']); + } + + if ($itemBuff) + DB::Aowow()->query($this->queryfy($itemBuff, $insMore), 23, 23, 23); + + if ($spellBuff) + DB::Aowow()->query($this->queryfy($spellBuff, $insMore), 23, 23, 23); + + + // flagging aowow_items for source (note: this is not exact! creatures dropping items may not be spawnd, quests granting items may be disabled) + DB::Aowow()->query('UPDATE ?_items SET cuFlags = cuFlags & ?d', ~CUSTOM_UNAVAILABLE); + DB::Aowow()->query('UPDATE ?_items i LEFT JOIN ?_source s ON s.typeId = i.id AND s.type = ?d SET i.cuFlags = i.cuFlags | ?d WHERE s.typeId IS NULL', TYPE_ITEM, CUSTOM_UNAVAILABLE); + + /*********/ + /* Spell */ + /*********/ + + CLI::write(' - Spells [original]'); + + # 4: Quest + CLI::write(' * #4 Quest'); + $quests = DB::World()->select(' + SELECT spell AS ARRAY_KEY, id, SUM(qty) AS qty, BIT_OR(side) AS side FROM ( + SELECT IF(RewardSpell = 0, RewardDisplaySpell, RewardSpell) AS spell, ID, COUNT(1) AS qty, IF(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template WHERE IF(RewardSpell = 0, RewardDisplaySpell, RewardSpell) > 0 GROUP BY spell + UNION + SELECT qta.SourceSpellId AS spell, qt.ID, COUNT(1) AS qty, IF(AllowableRaces & 0x2B2 AND !(AllowableRaces & 0x44D), 2, IF(AllowableRaces & 0x44D AND !(AllowableRaces & 0x2B2), 1, 3)) AS side FROM quest_template qt JOIN quest_template_addon qta ON qta.ID = qt.ID WHERE qta.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; + + $this->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($this->queryfy($buff, $insMore), 4, 4, 4); + } + + # 6: Trainer + CLI::write(' * #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; + $this->pushBuffer($buff, TYPE_SPELL, $effects['effect'.$i.'TriggerSpell'], $trainerId ? TYPE_NPC : 0, $trainerId); + } + + if (!$triggered) + $this->pushBuffer($buff, TYPE_SPELL, $spellId, $trainerId ? TYPE_NPC : 0, $trainerId); + } + + DB::Aowow()->query($this->queryfy($buff, $insMore), 6, 6, 6); + } + + # 7: Discovery + CLI::write(' * #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($this->queryfy($disco, $insBasic), 7, 7, 7); + + # 9: Talent + CLI::write(' * #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) + { + CLI::write(' - '.++$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($this->queryfy($buff, $insBasic), 9, 9, 9); + + # 10: Starter + CLI::write(' * #10 Starter'); + /* acquireMethod + ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, learnedAt = 1 && source10 = 1 + ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 + */ + + $pcis = DB::World()->selectCol('SELECT DISTINCT skill FROM playercreateinfo_skills'); + $subSkills = DB::Aowow()->subquery('SELECT ?d, spellId, 1, NULL AS m, NULL AS mt FROM dbc_skilllineability WHERE {(skillLineId IN (?a) AND acquireMethod = 2) OR} (acquireMethod = 1 AND (reqSkillLevel = 1 OR skillLineId = 129)) GROUP BY spellId', TYPE_SPELL, $pcis ?: DBSIMPLE_SKIP); + DB::Aowow()->query($insSub, 10, $subSkills, 10, 10); + + + /**********/ + /* Titles */ + /**********/ + + CLI::write(' - Titles'); + + # 4: Quest + CLI::write(' * #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($this->queryfy($quests, $insMore), 4, 4, 4); + + # 12: Achievement + CLI::write(' * #12 Achievement'); + $sets = DB::World()->select(' + SELECT titleId AS ARRAY_KEY, MIN(ID) AS srcId, NULLIF(MAX(ID), MIN(ID)) AS altSrcId FROM ( + SELECT TitleA AS `titleId`, ID FROM achievement_reward WHERE TitleA <> 0 + UNION + SELECT TitleH AS `titleId`, ID FROM achievement_reward WHERE TitleH <> 0 + ) AS x GROUP BY titleId' + ); + foreach ($sets as $tId => $set) + { + DB::Aowow()->query($this->queryfy([[TYPE_TITLE, $tId, 1, TYPE_ACHIEVEMENT, $set['srcId']]], $insMore), 12, 12, 12); + + if ($set['altSrcId']) + DB::Aowow()->query('UPDATE ?_titles SET src12Ext = ?d WHERE id = ?d', $set['altSrcId'], $tId); + } + + # 13: Source-String + CLI::write(' * #13 cuStrings'); + $src13 = [null, 42, 52, 71, 80, 157, 163, 167, 169, 177]; + foreach ($src13 as $src => $tId) + if ($tId) + DB::Aowow()->query($this->queryfy([[TYPE_TITLE, $tId, $src]], $insBasic), 13, 13, 13); + + return true; } - - DB::Aowow()->query(queryfy('[V]', $buff, $insBasic), 9, 9, 9); - - # 10: Starter - CLI::write(' * #10 Starter'); - /* acquireMethod - ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, learnedAt = 1 && source10 = 1 - ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 - */ - - $pcis = DB::World()->selectCol('SELECT DISTINCT skill FROM playercreateinfo_skills'); - $subSkills = DB::Aowow()->subquery('SELECT ?d, spellId, 1, NULL AS m, NULL AS mt FROM dbc_skilllineability WHERE {(skillLineId IN (?a) AND acquireMethod = 2) OR} (acquireMethod = 1 AND (reqSkillLevel = 1 OR skillLineId = 129)) GROUP BY spellId', TYPE_SPELL, $pcis ?: DBSIMPLE_SKIP); - DB::Aowow()->query($insSub, 10, $subSkills, 10, 10); - - - /**********/ - /* Titles */ - /**********/ - - CLI::write(' - Titles'); - - # 4: Quest - CLI::write(' * #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 - CLI::write(' * #12 Achievement'); - $sets = DB::World()->select(' - SELECT titleId AS ARRAY_KEY, MIN(ID) AS srcId, NULLIF(MAX(ID), MIN(ID)) AS altSrcId FROM ( - SELECT TitleA AS `titleId`, ID FROM achievement_reward WHERE TitleA <> 0 - UNION - SELECT TitleH AS `titleId`, ID FROM achievement_reward WHERE TitleH <> 0 - ) AS x GROUP BY titleId' - ); - foreach ($sets as $tId => $set) - { - DB::Aowow()->query(queryfy('[V]', [[TYPE_TITLE, $tId, 1, TYPE_ACHIEVEMENT, $set['srcId']]], $insMore), 12, 12, 12); - - if ($set['altSrcId']) - DB::Aowow()->query('UPDATE ?_titles SET src12Ext = ?d WHERE id = ?d', $set['altSrcId'], $tId); - } - - # 13: Source-String - CLI::write(' * #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; -} +}); ?> diff --git a/setup/tools/sqlgen/spawns.func.php b/setup/tools/sqlgen/spawns.func.php index ba051563..94833176 100644 --- a/setup/tools/sqlgen/spawns.func.php +++ b/setup/tools/sqlgen/spawns.func.php @@ -7,28 +7,60 @@ if (!CLI) die('not in cli mode'); -// requires https://github.com/TrinityCore/TrinityCore/commit/f989c7182c4cc30f1d0ffdc566c7624a5e108a2f +// requires https://github.com/TrinityCore/TrinityCore/commit/f989c7182c4cc30f1d0ffdc566c7624a5e108a2f to have been used at least once -/* deps: - * creature - * creature_addon - * gameobject - * gameobject_template - * vehicle_accessory - * vehicle_accessory_template - * script_waypoint - * waypoints - * waypoint_data -*/ - -$customData = array( -); -$reqDBC = ['worldmaparea', 'map', 'dungeonmap', 'taxipathnode', 'soundemitters', 'areatrigger']; - -function spawns() // and waypoints +SqlGen::register(new class extends SetupScript { - $alphaMapCache = []; - $alphaMapCheck = function ($areaId, array &$set) use (&$alphaMapCache) + protected $command = 'spawns'; // and waypoints + + protected $tblDependancyTC = ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data']; + protected $dbcSourceFiles = ['worldmaparea', 'map', 'dungeonmap', 'taxipathnode', 'soundemitters', 'areatrigger']; + + private $querys = array( + 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 creature spawns'], + + 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 gameobject spawns'], + + 3 => ['SELECT id AS "guid", 19 AS "type", soundId AS typeId, 0 AS respawn, 0 AS phaseMask, 0 AS areaId, mapId AS "map", 0 AS pathId, posX, posY ' . + 'FROM dbc_soundemitters', + ' - assembling sound emitter spawns'], + + 4 => ['SELECT id AS "guid", 503 AS "type", id AS typeId, 0 AS respawn, 0 AS phaseMask, 0 AS areaId, mapId AS "map", 0 AS pathId, posX, posY ' . + 'FROM dbc_areatrigger', + ' - assembling areatrigger spawns'], + + 5 => ['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 table script_waypoint'], + + 6 => ['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 table waypoints'], + + 7 => ['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 WHERE ca.path_id <> 0', + ' - assembling waypoints from table waypoint_data'] + ); + + private $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, 571) OR wma.areaId = 4395), 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'; + + private $alphaMapCache = []; + + private function alphaMapCheck(int $areaId, array &$set) : bool { $file = 'setup/generated/alphaMaps/'.$areaId.'.png'; if (!file_exists($file)) // file does not exist (probably instanced area) @@ -41,28 +73,28 @@ function spawns() // and waypoints return true; } - if (empty($alphaMapCache[$areaId])) - $alphaMapCache[$areaId] = imagecreatefrompng($file); + if (empty($this->alphaMapCache[$areaId])) + $this->alphaMapCache[$areaId] = imagecreatefrompng($file); // alphaMaps are 1000 x 1000, adapt points [black => valid point] - if (!imagecolorat($alphaMapCache[$areaId], $set['posX'] * 10, $set['posY'] * 10)) + if (!imagecolorat($this->alphaMapCache[$areaId], $set['posX'] * 10, $set['posY'] * 10)) $set = null; return true; - }; + } - $checkCoords = function ($points) use($alphaMapCheck) + private function checkCoords(array $points) : array { $result = []; - $capitals = array( // capitals take precedence over their surroundings - 1497, 1637, 1638, 3487, // Undercity, Ogrimmar, Thunder Bluff, Silvermoon City - 1519, 1537, 1657, 3557, // Stormwind City, Ironforge, Darnassus, The Exodar - 3703, 4395 // Shattrath City, Dalaran + $capitals = array( // capitals take precedence over their surroundings + 1497, 1637, 1638, 3487, // Undercity, Ogrimmar, Thunder Bluff, Silvermoon City + 1519, 1537, 1657, 3557, // Stormwind City, Ironforge, Darnassus, The Exodar + 3703, 4395 // Shattrath City, Dalaran ); foreach ($points as $res) { - if ($alphaMapCheck($res['areaId'], $res)) + if ($this->alphaMapCheck($res['areaId'], $res)) { if (!$res) continue; @@ -74,9 +106,9 @@ function spawns() // and waypoints 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 + 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 + else if (empty($result)) // add with lowest quality if alpha map is missing $result = [1.0, $res]; } @@ -88,198 +120,161 @@ function spawns() // and waypoints } 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 '.CLI::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 '.CLI::bold('gameobject').' spawns']; - - $query[3] = ['SELECT id AS "guid", 19 AS "type", soundId AS typeId, 0 AS respawn, 0 AS phaseMask, 0 AS areaId, mapId AS "map", 0 AS pathId, posX, posY ' . - 'FROM dbc_soundemitters', - ' - assembling '.CLI::bold('sound emitter').' spawns']; - - $query[4] = ['SELECT id AS "guid", 503 AS "type", id AS typeId, 0 AS respawn, 0 AS phaseMask, 0 AS areaId, mapId AS "map", 0 AS pathId, posX, posY ' . - 'FROM dbc_areatrigger', - ' - assembling '.CLI::bold('areatrigger').' spawns']; - - $query[5] = ['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 '.CLI::bold('script_waypoint')]; - - $query[6] = ['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 '.CLI::bold('waypoints')]; - - $query[7] = ['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 WHERE ca.path_id <> 0', - ' - assembling waypoints from '.CLI::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, 571) OR wma.areaId = 4395), 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) + public function generate(array $ids = []) : bool { - CLI::write($q[1]); + /*********************/ + /* truncate old data */ + /*********************/ - $n = 0; - $sum = 0; + DB::Aowow()->query('TRUNCATE TABLE ?_spawns'); + DB::Aowow()->query('TRUNCATE TABLE ?_creature_waypoints'); - if ($idx == 3 || $idx == 4) - $queryResult = DB::Aowow()->select($q[0]); - else - $queryResult = DB::World()->select($q[0]); - foreach ($queryResult as $spawn) + /**************************/ + /* 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 ($this->querys as $idx => $q) { - if (!$n) - CLI::write(' * sets '.($sum + 1).' - '.($sum += SqlGen::$stepSize)); + CLI::write($q[1]); - if ($n++ > SqlGen::$stepSize) - $n = 0; + $n = 0; + $sum = 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) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris)) - { - CLI::write('GUID '.$spawn['guid'].($idx < 5 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLI::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 < 5) - { - $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)); - } + if ($idx == 3 || $idx == 4) + $queryResult = DB::Aowow()->select($q[0]); else - { - $set = array( - 'creatureOrPath' => $spawn['npcOrPath'], - 'point' => $spawn['point'], - 'wait' => $spawn['wait'], - 'areaId' => $final['areaId'], - 'floor' => $final['floor'], - 'posX' => $final['posX'], - 'posY' => $final['posY'] - ); + $queryResult = DB::World()->select($q[0]); - DB::Aowow()->query('REPLACE INTO ?_creature_waypoints (?#) VALUES (?a)', array_keys($set), array_values($set)); + foreach ($queryResult as $spawn) + { + if (!$n) + CLI::write(' * sets '.($sum + 1).' - '.($sum += SqlGen::$sqlBatchSize)); + + if ($n++ > SqlGen::$sqlBatchSize) + $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($this->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($this->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) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris)) + { + CLI::write('GUID '.$spawn['guid'].($idx < 5 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLI::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 < 5) + { + $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 */ - /*****************************/ + /*****************************/ + /* 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'); + // 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) + // 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) { - $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 = 0; + foreach ($accessories as $idx => $data) { - $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']); + $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); - unset($accessories[$idx]); + 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) + CLI::write(' * assigned '.$matches.' accessories on '.++$n.'. pass on vehicle accessories'); } - if ($matches) - CLI::write(' * assigned '.$matches.' accessories on '.++$n.'. pass on vehicle accessories'); + if ($accessories) + CLI::write(count($accessories).' accessories could not be fitted onto a spawned vehicle.', CLI::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; } - if ($accessories) - CLI::write(count($accessories).' accessories could not be fitted onto a spawned vehicle.', CLI::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; -} +}); ?> diff --git a/setup/tools/sqlgen/spell.func.php b/setup/tools/sqlgen/spell.func.php index 2e4ff158..7a329436 100644 --- a/setup/tools/sqlgen/spell.func.php +++ b/setup/tools/sqlgen/spell.func.php @@ -7,770 +7,750 @@ if (!CLI) die('not in cli mode'); -/* deps: - * item_template - * creature_template - * creature_template_addon - * smart_scripts - * npc_trainer - * disables - * spell_ranks - * spell_dbc - * skill_discovery_template -*/ - -$customData = array( -); -$reqDBC = [ - 'spell', - 'spellradius', - 'spellduration', - 'spellrunecost', - 'spellcasttimes', - 'skillline', - 'skilllineability', - 'skillraceclassinfo', - 'talent', - 'talenttab', - 'glyphproperties', - 'spellicon' -]; - -function spell() +SqlGen::register(new class extends SetupScript { - $ssQuery = ' - SELECT - id AS ARRAY_KEY, - id, - 0 AS category, - Dispel, - Mechanic, - Attributes, AttributesEx, AttributesEx2, AttributesEx3, AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, - Stances, StancesNot, - Targets, - 0 AS spellFocus, - CastingTimeIndex, - 0 AS recoveryTime, 0 AS recoveryTimeCategory, - ProcChance, ProcCharges, - MaxLevel, BaseLevel, SpellLevel, - DurationIndex, - 0 AS powerType, - 0 AS powerCost, - 0 AS powerCostPerLevel, - 0 AS powerPerSecond, - 0 AS powerPerSecondPerLevel, - RangeIndex, - StackAmount, - 0 AS tool1, 0 AS tool2, - 0 AS reagent1, 0 AS reagent2, 0 AS reagent3, 0 AS reagent4, 0 AS reagent5, 0 AS reagent6, 0 AS reagent7, 0 AS reagent8, - 0 AS reagentCount1, 0 AS reagentCount2, 0 AS reagentCount3, 0 AS reagentCount4, 0 AS reagentCount5, 0 AS reagentCount6, 0 AS reagentCount7, 0 AS reagentCount8, - EquippedItemClass, - EquippedItemSubClassMask, - EquippedItemInventoryTypeMask, - Effect1, Effect2, Effect3, - EffectDieSides1, EffectDieSides2, EffectDieSides3, - EffectRealPointsPerLevel1, EffectRealPointsPerLevel2, EffectRealPointsPerLevel3, - EffectBasePoints1, EffectBasePoints2, EffectBasePoints3, - EffectMechanic1, EffectMechanic2, EffectMechanic3, - EffectImplicitTargetA1, EffectImplicitTargetA2, EffectImplicitTargetA3, - EffectImplicitTargetB1, EffectImplicitTargetB2, EffectImplicitTargetB3, - EffectRadiusIndex1, EffectRadiusIndex2, EffectRadiusIndex3, - EffectApplyAuraName1, EffectApplyAuraName2, EffectApplyAuraName3, - EffectAmplitude1, EffectAmplitude2, EffectAmplitude3, - EffectMultipleValue1, EffectMultipleValue2, EffectMultipleValue3, - 0 AS effect1ChainTarget, 0 AS effect2ChainTarget, 0 AS effect3ChainTarget, - EffectItemType1, EffectItemType2, EffectItemType3, - EffectMiscValue1, EffectMiscValue2, EffectMiscValue3, - EffectMiscValueB1, EffectMiscValueB2, EffectMiscValueB3, - EffectTriggerSpell1, EffectTriggerSpell2, EffectTriggerSpell3, - 0 AS effect1PointsPerComboPoint, 0 AS effect2PointsPerComboPoint, 0 AS effect3PointsPerComboPoint, - EffectSpellClassMaskA1, EffectSpellClassMaskA2, EffectSpellClassMaskA3, - EffectSpellClassMaskB1, EffectSpellClassMaskB2, EffectSpellClassMaskB3, - EffectSpellClassMaskC1, EffectSpellClassMaskC2, EffectSpellClassMaskC3, - 0 AS iconId, 0 AS iconIdAlt, - 0 AS rankId, 0 AS spellVisualId1, - CONCAT("Serverside - ",Comment) AS name_loc0,CONCAT("Serverside - ",Comment) AS name_loc2,CONCAT("Serverside - ",Comment) AS name_loc3,CONCAT("Serverside - ",Comment) AS name_loc4,CONCAT("Serverside - ",Comment) AS name_loc6,CONCAT("Serverside - ",Comment) AS name_loc8, - "" AS rank_loc0, "" AS rank_loc2, "" AS rank_loc3, "" AS rank_loc4, "" AS rank_loc6, "" AS rank_loc8, - "" AS description_loc0, "" AS description_loc2, "" AS description_loc3, "" AS description_loc4, "" AS description_loc6, "" AS description_loc8, - "" AS buff_loc0, "" AS buff_loc2, "" AS buff_loc3, "" AS buff_loc4, "" AS buff_loc6, "" AS buff_loc8, - 0 AS powerCostPercent, - 0 AS startRecoveryCategory, - 0 AS startRecoveryTime, - MaxTargetLevel, - SpellFamilyName, - SpellFamilyFlags1, - SpellFamilyFlags2, - SpellFamilyFlags3, - MaxAffectedTargets, - DmgClass, - DmgMultiplier1, DmgMultiplier2, DmgMultiplier3, - 0 AS toolCategory1, 0 AS toolCategory2, - SchoolMask, - 0 AS runeCostId, - 0 AS powerDisplayId, - 0 AS effect1BonusMultiplier, 0 AS effect2BonusMultiplier, 0 AS effect3BonusMultiplier, - 0 AS spellDescriptionVariable, - 0 AS spellDifficulty - FROM - spell_dbc - WHERE - id > ?d - LIMIT - ?d'; + protected $command = 'spell'; - $baseQuery = ' - SELECT - s.id, - category, - dispelType, - mechanic, - attributes0, attributes1, attributes2, attributes3, attributes4, attributes5, attributes6, attributes7, - 0 AS cuFlags, - 0 AS typeCat, - stanceMask, stanceMaskNot, - targets, - spellFocus, - IFNULL(sct.baseTime, 0) / 1000 AS castTime, - recoveryTime, recoveryTimeCategory, - startRecoveryTime, startRecoveryCategory, - procChance, procCharges, - 0 AS procCustom, 0 AS procCooldown, - maxLevel, baseLevel, spellLevel, 0 AS talentLevel, - IF (sd.baseTime <> -1, ABS(sd.baseTime), -1) AS duration, - IF (powerDisplayId, -powerDisplayId, powerType) AS powerType, - powerCost, - powerCostPerLevel, - powerCostPercent, - powerPerSecond, - powerPerSecondPerLevel, - IFNULL (src.runicPowerGain, 0) AS powerGainRunicPower, - IF (src.id IS NULL, 0, (src.costFrost << 8) | (src.costUnholy << 4) | src.costBlood) AS powerCostRunes, - rangeId, - stackAmount, - tool1, tool2, - toolCategory1, toolCategory2, - reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8, - reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8, - equippedItemClass, - equippedItemSubClassMask, - equippedItemInventoryTypeMask, - effect1Id, effect2Id, effect3Id, - effect1DieSides, effect2DieSides, effect3DieSides, - effect1RealPointsPerLevel, effect2RealPointsPerLevel, effect3RealPointsPerLevel, - effect1BasePoints, effect2BasePoints, effect3BasePoints, - effect1Mechanic, effect2Mechanic, effect3Mechanic, - effect1ImplicitTargetA, effect2ImplicitTargetA, effect3ImplicitTargetA, - effect1ImplicitTargetB, effect2ImplicitTargetB, effect3ImplicitTargetB, - IFNULL (sr1.radiusMin, 0) AS effect1RadiusMin, IFNULL (sr1.radiusMax, 0) AS effect1RadiusMax, - IFNULL (sr2.radiusMin, 0) AS effect2RadiusMin, IFNULL (sr2.radiusMax, 0) AS effect2RadiusMax, - IFNULL (sr3.radiusMin, 0) AS effect3RadiusMin, IFNULL (sr3.radiusMax, 0) AS effect3RadiusMax, - effect1AuraId, effect2AuraId, effect3AuraId, - effect1Periode, effect2Periode, effect3Periode, - effect1ValueMultiplier, effect2ValueMultiplier, effect3ValueMultiplier, - effect1ChainTarget, effect2ChainTarget, effect3ChainTarget, - effect1CreateItemId, effect2CreateItemId, effect3CreateItemId, - effect1MiscValue, effect2MiscValue, effect3MiscValue, - effect1MiscValueB, effect2MiscValueB, effect3MiscValueB, - effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell, - effect1PointsPerComboPoint, effect2PointsPerComboPoint, effect3PointsPerComboPoint, - effect1SpellClassMaskA, effect2SpellClassMaskA, effect3SpellClassMaskA, - effect1SpellClassMaskB, effect2SpellClassMaskB, effect3SpellClassMaskB, - effect1SpellClassMaskC, effect2SpellClassMaskC, effect3SpellClassMaskC, - effect1DamageMultiplier, effect2DamageMultiplier, effect3DamageMultiplier, - effect1BonusMultiplier, effect2BonusMultiplier, effect3BonusMultiplier, - 0 AS iconId, iconId AS iconIdBak, 0 AS iconIdAlt, - 0 AS rankId, spellVisualId1, - name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, - rank_loc0, rank_loc2, rank_loc3, rank_loc4, rank_loc6, rank_loc8, - description_loc0, description_loc2, description_loc3, description_loc4, description_loc6, description_loc8, - buff_loc0, buff_loc2, buff_loc3, buff_loc4, buff_loc6, buff_loc8, - maxTargetLevel, - spellFamilyId, - spellFamilyFlags1, spellFamilyFlags2, spellFamilyFlags3, - maxAffectedTargets, - damageClass, - 0 AS skillLine1, - 0 AS skillLine2OrMask, - 0 AS reqRaceMask, - 0 AS reqClassMask, - 0 AS reqSpellId, - 0 AS reqSkillLevel, - 0 AS learnedAt, - 0 AS skillLevelGrey, - 0 AS skillLevelYellow, - schoolMask, - spellDescriptionVariable, - 0 AS trainingCost - FROM - dbc_spell s - LEFT JOIN - dbc_spellcasttimes sct ON s.castTimeId = sct.id - LEFT JOIN - dbc_spellrunecost src ON s.runeCostId = src.id - LEFT JOIN - dbc_spellduration sd ON s.durationId = sd.id - LEFT JOIN - dbc_spellradius sr1 ON s.effect1RadiusId = sr1.id - LEFT JOIN - dbc_spellradius sr2 ON s.effect2RadiusId = sr2.id - LEFT JOIN - dbc_spellradius sr3 ON s.effect3RadiusId = sr3.id - WHERE - s.id > ?d - LIMIT - ?d'; + protected $tblDependancyAowow = ['icons']; + protected $tblDependancyTC = ['item_template', 'creature_template', 'creature_template_addon', 'smart_scripts', 'npc_trainer', 'disables', 'spell_ranks', 'spell_dbc', 'skill_discovery_template']; + protected $dbcSourceFiles = ['spell', 'spellradius', 'spellduration', 'spellrunecost', 'spellcasttimes', 'skillline', 'skilllineability', 'skillraceclassinfo', 'talent', 'talenttab', 'glyphproperties', 'spellicon']; - $serverside = []; - - // merge serverside spells into dbc_spell (should not affect other scripts) - $lastMax = 0; - CLI::write(' - merging serverside spells into spell.dbc'); - while ($spells = DB::World()->select($ssQuery, $lastMax, SqlGen::$stepSize)) + public function generate(array $ids = []) : bool { - $newMax = max(array_column($spells, 'id')); + $ssQuery = ' + SELECT + id AS ARRAY_KEY, + id, + 0 AS category, + Dispel, + Mechanic, + Attributes, AttributesEx, AttributesEx2, AttributesEx3, AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, + Stances, StancesNot, + Targets, + 0 AS spellFocus, + CastingTimeIndex, + 0 AS recoveryTime, 0 AS recoveryTimeCategory, + ProcChance, ProcCharges, + MaxLevel, BaseLevel, SpellLevel, + DurationIndex, + 0 AS powerType, + 0 AS powerCost, + 0 AS powerCostPerLevel, + 0 AS powerPerSecond, + 0 AS powerPerSecondPerLevel, + RangeIndex, + StackAmount, + 0 AS tool1, 0 AS tool2, + 0 AS reagent1, 0 AS reagent2, 0 AS reagent3, 0 AS reagent4, 0 AS reagent5, 0 AS reagent6, 0 AS reagent7, 0 AS reagent8, + 0 AS reagentCount1, 0 AS reagentCount2, 0 AS reagentCount3, 0 AS reagentCount4, 0 AS reagentCount5, 0 AS reagentCount6, 0 AS reagentCount7, 0 AS reagentCount8, + EquippedItemClass, + EquippedItemSubClassMask, + EquippedItemInventoryTypeMask, + Effect1, Effect2, Effect3, + EffectDieSides1, EffectDieSides2, EffectDieSides3, + EffectRealPointsPerLevel1, EffectRealPointsPerLevel2, EffectRealPointsPerLevel3, + EffectBasePoints1, EffectBasePoints2, EffectBasePoints3, + EffectMechanic1, EffectMechanic2, EffectMechanic3, + EffectImplicitTargetA1, EffectImplicitTargetA2, EffectImplicitTargetA3, + EffectImplicitTargetB1, EffectImplicitTargetB2, EffectImplicitTargetB3, + EffectRadiusIndex1, EffectRadiusIndex2, EffectRadiusIndex3, + EffectApplyAuraName1, EffectApplyAuraName2, EffectApplyAuraName3, + EffectAmplitude1, EffectAmplitude2, EffectAmplitude3, + EffectMultipleValue1, EffectMultipleValue2, EffectMultipleValue3, + 0 AS effect1ChainTarget, 0 AS effect2ChainTarget, 0 AS effect3ChainTarget, + EffectItemType1, EffectItemType2, EffectItemType3, + EffectMiscValue1, EffectMiscValue2, EffectMiscValue3, + EffectMiscValueB1, EffectMiscValueB2, EffectMiscValueB3, + EffectTriggerSpell1, EffectTriggerSpell2, EffectTriggerSpell3, + 0 AS effect1PointsPerComboPoint, 0 AS effect2PointsPerComboPoint, 0 AS effect3PointsPerComboPoint, + EffectSpellClassMaskA1, EffectSpellClassMaskA2, EffectSpellClassMaskA3, + EffectSpellClassMaskB1, EffectSpellClassMaskB2, EffectSpellClassMaskB3, + EffectSpellClassMaskC1, EffectSpellClassMaskC2, EffectSpellClassMaskC3, + 0 AS iconId, 0 AS iconIdAlt, + 0 AS rankId, 0 AS spellVisualId1, + CONCAT("Serverside - ",Comment) AS name_loc0,CONCAT("Serverside - ",Comment) AS name_loc2,CONCAT("Serverside - ",Comment) AS name_loc3,CONCAT("Serverside - ",Comment) AS name_loc4,CONCAT("Serverside - ",Comment) AS name_loc6,CONCAT("Serverside - ",Comment) AS name_loc8, + "" AS rank_loc0, "" AS rank_loc2, "" AS rank_loc3, "" AS rank_loc4, "" AS rank_loc6, "" AS rank_loc8, + "" AS description_loc0, "" AS description_loc2, "" AS description_loc3, "" AS description_loc4, "" AS description_loc6, "" AS description_loc8, + "" AS buff_loc0, "" AS buff_loc2, "" AS buff_loc3, "" AS buff_loc4, "" AS buff_loc6, "" AS buff_loc8, + 0 AS powerCostPercent, + 0 AS startRecoveryCategory, + 0 AS startRecoveryTime, + MaxTargetLevel, + SpellFamilyName, + SpellFamilyFlags1, + SpellFamilyFlags2, + SpellFamilyFlags3, + MaxAffectedTargets, + DmgClass, + DmgMultiplier1, DmgMultiplier2, DmgMultiplier3, + 0 AS toolCategory1, 0 AS toolCategory2, + SchoolMask, + 0 AS runeCostId, + 0 AS powerDisplayId, + 0 AS effect1BonusMultiplier, 0 AS effect2BonusMultiplier, 0 AS effect3BonusMultiplier, + 0 AS spellDescriptionVariable, + 0 AS spellDifficulty + FROM + spell_dbc + WHERE + id > ?d + LIMIT + ?d'; - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + $baseQuery = ' + SELECT + s.id, + category, + dispelType, + mechanic, + attributes0, attributes1, attributes2, attributes3, attributes4, attributes5, attributes6, attributes7, + 0 AS cuFlags, + 0 AS typeCat, + stanceMask, stanceMaskNot, + targets, + spellFocus, + IFNULL(sct.baseTime, 0) / 1000 AS castTime, + recoveryTime, recoveryTimeCategory, + startRecoveryTime, startRecoveryCategory, + procChance, procCharges, + 0 AS procCustom, 0 AS procCooldown, + maxLevel, baseLevel, spellLevel, 0 AS talentLevel, + IF (sd.baseTime <> -1, ABS(sd.baseTime), -1) AS duration, + IF (powerDisplayId, -powerDisplayId, powerType) AS powerType, + powerCost, + powerCostPerLevel, + powerCostPercent, + powerPerSecond, + powerPerSecondPerLevel, + IFNULL (src.runicPowerGain, 0) AS powerGainRunicPower, + IF (src.id IS NULL, 0, (src.costFrost << 8) | (src.costUnholy << 4) | src.costBlood) AS powerCostRunes, + rangeId, + stackAmount, + tool1, tool2, + toolCategory1, toolCategory2, + reagent1, reagent2, reagent3, reagent4, reagent5, reagent6, reagent7, reagent8, + reagentCount1, reagentCount2, reagentCount3, reagentCount4, reagentCount5, reagentCount6, reagentCount7, reagentCount8, + equippedItemClass, + equippedItemSubClassMask, + equippedItemInventoryTypeMask, + effect1Id, effect2Id, effect3Id, + effect1DieSides, effect2DieSides, effect3DieSides, + effect1RealPointsPerLevel, effect2RealPointsPerLevel, effect3RealPointsPerLevel, + effect1BasePoints, effect2BasePoints, effect3BasePoints, + effect1Mechanic, effect2Mechanic, effect3Mechanic, + effect1ImplicitTargetA, effect2ImplicitTargetA, effect3ImplicitTargetA, + effect1ImplicitTargetB, effect2ImplicitTargetB, effect3ImplicitTargetB, + IFNULL (sr1.radiusMin, 0) AS effect1RadiusMin, IFNULL (sr1.radiusMax, 0) AS effect1RadiusMax, + IFNULL (sr2.radiusMin, 0) AS effect2RadiusMin, IFNULL (sr2.radiusMax, 0) AS effect2RadiusMax, + IFNULL (sr3.radiusMin, 0) AS effect3RadiusMin, IFNULL (sr3.radiusMax, 0) AS effect3RadiusMax, + effect1AuraId, effect2AuraId, effect3AuraId, + effect1Periode, effect2Periode, effect3Periode, + effect1ValueMultiplier, effect2ValueMultiplier, effect3ValueMultiplier, + effect1ChainTarget, effect2ChainTarget, effect3ChainTarget, + effect1CreateItemId, effect2CreateItemId, effect3CreateItemId, + effect1MiscValue, effect2MiscValue, effect3MiscValue, + effect1MiscValueB, effect2MiscValueB, effect3MiscValueB, + effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell, + effect1PointsPerComboPoint, effect2PointsPerComboPoint, effect3PointsPerComboPoint, + effect1SpellClassMaskA, effect2SpellClassMaskA, effect3SpellClassMaskA, + effect1SpellClassMaskB, effect2SpellClassMaskB, effect3SpellClassMaskB, + effect1SpellClassMaskC, effect2SpellClassMaskC, effect3SpellClassMaskC, + effect1DamageMultiplier, effect2DamageMultiplier, effect3DamageMultiplier, + effect1BonusMultiplier, effect2BonusMultiplier, effect3BonusMultiplier, + 0 AS iconId, iconId AS iconIdBak, 0 AS iconIdAlt, + 0 AS rankId, spellVisualId1, + name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8, + rank_loc0, rank_loc2, rank_loc3, rank_loc4, rank_loc6, rank_loc8, + description_loc0, description_loc2, description_loc3, description_loc4, description_loc6, description_loc8, + buff_loc0, buff_loc2, buff_loc3, buff_loc4, buff_loc6, buff_loc8, + maxTargetLevel, + spellFamilyId, + spellFamilyFlags1, spellFamilyFlags2, spellFamilyFlags3, + maxAffectedTargets, + damageClass, + 0 AS skillLine1, + 0 AS skillLine2OrMask, + 0 AS reqRaceMask, + 0 AS reqClassMask, + 0 AS reqSpellId, + 0 AS reqSkillLevel, + 0 AS learnedAt, + 0 AS skillLevelGrey, + 0 AS skillLevelYellow, + schoolMask, + spellDescriptionVariable, + 0 AS trainingCost + FROM + dbc_spell s + LEFT JOIN + dbc_spellcasttimes sct ON s.castTimeId = sct.id + LEFT JOIN + dbc_spellrunecost src ON s.runeCostId = src.id + LEFT JOIN + dbc_spellduration sd ON s.durationId = sd.id + LEFT JOIN + dbc_spellradius sr1 ON s.effect1RadiusId = sr1.id + LEFT JOIN + dbc_spellradius sr2 ON s.effect2RadiusId = sr2.id + LEFT JOIN + dbc_spellradius sr3 ON s.effect3RadiusId = sr3.id + WHERE + s.id > ?d + LIMIT + ?d'; - $lastMax = $newMax; + $serverside = []; - foreach ($spells as $id => $spell) + // merge serverside spells into dbc_spell (should not affect other scripts) + $lastMax = 0; + CLI::write(' - merging serverside spells into spell.dbc'); + while ($spells = DB::World()->select($ssQuery, $lastMax, SqlGen::$sqlBatchSize)) { - $serverside[] = $id; - DB::Aowow()->query('REPLACE INTO dbc_spell VALUES (?a)', array_values($spell)); - } - } + $newMax = max(array_column($spells, 'id')); - // merge everything into aowow_spell - $lastMax = 0; - CLI::write(' - filling aowow_spell'); - while ($spells = DB::Aowow()->select($baseQuery, $lastMax, SqlGen::$stepSize)) - { - $newMax = max(array_column($spells, 'id')); + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + $lastMax = $newMax; - $lastMax = $newMax; - - foreach ($spells as $spell) - DB::Aowow()->query('REPLACE INTO ?_spell VALUES (?a)', array_values($spell)); - } - - // apply flag: CUSTOM_SERVERSIDE - if ($serverside) - DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_SERVERSIDE, $serverside); - - // apply flag: CUSTOM_DISABLED [0xD: players (0x1), pets (0x4), general (0x8); only generally disabled spells] - if ($disables = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 0 AND params_0 = "" AND params_1 = "" AND flags & 0xD')) - DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_DISABLED, $disables); - - // apply spell ranks (can't use skilllineability.dbc, as it does not contain ranks for non-player/pet spells) - $ranks = DB::World()->selectCol('SELECT first_spell_id AS ARRAY_KEY, spell_id AS ARRAY_KEY2, rank FROM spell_ranks'); - foreach ($ranks as $firstSpell => $sets) - { - // apply flag: SPELL_CU_FIRST_RANK - DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_FIRST_RANK, $firstSpell); - - foreach ($sets as $spell => $rank) - DB::Aowow()->query('UPDATE ?_spell SET rankNo = ?d WHERE id = ?d', $rank, $spell); - - // apply flag: SPELL_CU_LAST_RANK - end($sets); - DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_LAST_RANK, key($sets)); - } - - - /*************************************/ - /* merge SkillLineAbility into Spell */ - /*************************************/ - - /* acquireMethod - ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, learnedAt = 1 - ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 not used for now - */ - - CLI::write(' - linking with skillineability'); - - $results = DB::Aowow()->select('SELECT spellId AS ARRAY_KEY, id AS ARRAY_KEY2, skillLineId, reqRaceMask, reqClassMask, reqSkillLevel, acquireMethod, skillLevelGrey, skillLevelYellow FROM dbc_skilllineability sla'); - foreach ($results as $spellId => $sets) - { - $names = array_keys(current($sets)); - $lines = []; - $trainer = false; - $update = array( - 'skillLine1' => 0, - 'skillLine2OrMask' => 0, - 'reqRaceMask' => 0, - 'reqClassMask' => 0, - 'reqSkillLevel' => 0, - 'skillLevelGrey' => 0, - 'skillLevelYellow' => 0 - ); - - foreach ($sets as $set) - { - $i = 0; - while (isset($names[$i])) + foreach ($spells as $id => $spell) { - $field = $set[$names[$i]]; - switch ($names[$i]) - { - case 'acquireMethod': - if ($field == 1) - $trainer = true; - break; - case 'skillLineId': // array - if (!in_array($field, $lines)) - $lines[] = $field; - break; - case 'reqRaceMask': // mask - case 'reqClassMask': - if (((int)$update[$names[$i]] & (int)$field) != $field) - (int)$update[$names[$i]] |= (int)$field; - break; - case 'reqSkillLevel': // max - case 'skillLevelYellow': - case 'skillLevelGrey': - if ($update[$names[$i]] < $field) - $update[$names[$i]] = $field; - break; - } - $i++; + $serverside[] = $id; + DB::Aowow()->query('REPLACE INTO dbc_spell VALUES (?a)', array_values($spell)); } } - if ($trainer) - DB::Aowow()->query('UPDATE ?_spell SET learnedAt = 1 WHERE id = ?d', $spellId); - - // check skillLineId against mask - switch (count($lines)) + // merge everything into aowow_spell + $lastMax = 0; + CLI::write(' - filling aowow_spell'); + while ($spells = DB::Aowow()->select($baseQuery, $lastMax, SqlGen::$sqlBatchSize)) { - case 2: - $update['skillLine2OrMask'] = $lines[1]; - case 1: - $update['skillLine1'] = $lines[0]; - break; - default: - for ($i = -count(Game::$skillLineMask); $i < 0; $i++) + $newMax = max(array_column($spells, 'id')); + + CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); + + $lastMax = $newMax; + + foreach ($spells as $spell) + DB::Aowow()->query('REPLACE INTO ?_spell VALUES (?a)', array_values($spell)); + } + + // apply flag: CUSTOM_SERVERSIDE + if ($serverside) + DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_SERVERSIDE, $serverside); + + // apply flag: CUSTOM_DISABLED [0xD: players (0x1), pets (0x4), general (0x8); only generally disabled spells] + if ($disables = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 0 AND params_0 = "" AND params_1 = "" AND flags & 0xD')) + DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_DISABLED, $disables); + + // apply spell ranks (can't use skilllineability.dbc, as it does not contain ranks for non-player/pet spells) + $ranks = DB::World()->selectCol('SELECT first_spell_id AS ARRAY_KEY, spell_id AS ARRAY_KEY2, rank FROM spell_ranks'); + foreach ($ranks as $firstSpell => $sets) + { + // apply flag: SPELL_CU_FIRST_RANK + DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_FIRST_RANK, $firstSpell); + + foreach ($sets as $spell => $rank) + DB::Aowow()->query('UPDATE ?_spell SET rankNo = ?d WHERE id = ?d', $rank, $spell); + + // apply flag: SPELL_CU_LAST_RANK + end($sets); + DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE id = ?d', SPELL_CU_LAST_RANK, key($sets)); + } + + + /*************************************/ + /* merge SkillLineAbility into Spell */ + /*************************************/ + + /* acquireMethod + ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, learnedAt = 1 + ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 not used for now + */ + + CLI::write(' - linking with skillineability'); + + $results = DB::Aowow()->select('SELECT spellId AS ARRAY_KEY, id AS ARRAY_KEY2, skillLineId, reqRaceMask, reqClassMask, reqSkillLevel, acquireMethod, skillLevelGrey, skillLevelYellow FROM dbc_skilllineability sla'); + foreach ($results as $spellId => $sets) + { + $names = array_keys(current($sets)); + $lines = []; + $trainer = false; + $update = array( + 'skillLine1' => 0, + 'skillLine2OrMask' => 0, + 'reqRaceMask' => 0, + 'reqClassMask' => 0, + 'reqSkillLevel' => 0, + 'skillLevelGrey' => 0, + 'skillLevelYellow' => 0 + ); + + foreach ($sets as $set) + { + $i = 0; + while (isset($names[$i])) { - foreach (Game::$skillLineMask[$i] as $k => $pair) + $field = $set[$names[$i]]; + switch ($names[$i]) { - if (in_array($pair[1], $lines)) + case 'acquireMethod': + if ($field == 1) + $trainer = true; + break; + case 'skillLineId': // array + if (!in_array($field, $lines)) + $lines[] = $field; + break; + case 'reqRaceMask': // mask + case 'reqClassMask': + if (((int)$update[$names[$i]] & (int)$field) != $field) + (int)$update[$names[$i]] |= (int)$field; + break; + case 'reqSkillLevel': // max + case 'skillLevelYellow': + case 'skillLevelGrey': + if ($update[$names[$i]] < $field) + $update[$names[$i]] = $field; + break; + } + $i++; + } + } + + if ($trainer) + DB::Aowow()->query('UPDATE ?_spell SET learnedAt = 1 WHERE id = ?d', $spellId); + + // check skillLineId against mask + switch (count($lines)) + { + case 2: + $update['skillLine2OrMask'] = $lines[1]; + case 1: + $update['skillLine1'] = $lines[0]; + break; + default: + for ($i = -count(Game::$skillLineMask); $i < 0; $i++) + { + foreach (Game::$skillLineMask[$i] as $k => $pair) { - $update['skillLine1'] = $i; - $update['skillLine2OrMask'] |= 1 << $k; + if (in_array($pair[1], $lines)) + { + $update['skillLine1'] = $i; + $update['skillLine2OrMask'] |= 1 << $k; + } } } - } + } + + DB::Aowow()->query('UPDATE ?_spell SET ?a WHERE id = ?d', $update, $spellId); } - DB::Aowow()->query('UPDATE ?_spell SET ?a WHERE id = ?d', $update, $spellId); - } - - // fill learnedAt, trainingCost from trainer - if ($trainer = DB::World()->select('SELECT SpellID AS ARRAY_KEY, MIN(ReqSkillRank) AS reqSkill, MIN(MoneyCost) AS cost, COUNT(*) AS count FROM npc_trainer GROUP BY SpellID')) - { - $spells = DB::Aowow()->select('SELECT id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE id IN (?a)', array_keys($trainer)); - $links = []; - - // todo (med): this skips some spells (e.g. riding) - foreach ($trainer as $spell => $tData) + // fill learnedAt, trainingCost from trainer + if ($trainer = DB::World()->select('SELECT SpellID AS ARRAY_KEY, MIN(ReqSkillRank) AS reqSkill, MIN(MoneyCost) AS cost, COUNT(*) AS count FROM npc_trainer GROUP BY SpellID')) { - if (!isset($spells[$spell])) - continue; + $spells = DB::Aowow()->select('SELECT id AS ARRAY_KEY, effect1Id, effect2Id, effect3Id, effect1TriggerSpell, effect2TriggerSpell, effect3TriggerSpell FROM dbc_spell WHERE id IN (?a)', array_keys($trainer)); + $links = []; - $triggered = false; - $effects = $spells[$spell]; - - for ($i = 1; $i <= 3; $i++) + // todo (med): this skips some spells (e.g. riding) + foreach ($trainer as $spell => $tData) { - if ($effects['effect'.$i.'Id'] != 36) // effect: learnSpell + if (!isset($spells[$spell])) continue; - $triggered = true; + $triggered = false; + $effects = $spells[$spell]; - $l = &$links[$effects['effect'.$i.'TriggerSpell']]; + for ($i = 1; $i <= 3; $i++) + { + if ($effects['effect'.$i.'Id'] != 36) // effect: learnSpell + continue; - if (!isset($l)) - $l = [$tData['reqSkill'], $tData['cost']]; + $triggered = true; - if ($tData['reqSkill'] < $l[0]) - $l[0] = $tData['reqSkill']; + $l = &$links[$effects['effect'.$i.'TriggerSpell']]; - if ($tData['cost'] < $l[1]) - $l[1] = $tData['cost']; + if (!isset($l)) + $l = [$tData['reqSkill'], $tData['cost']]; + + if ($tData['reqSkill'] < $l[0]) + $l[0] = $tData['reqSkill']; + + if ($tData['cost'] < $l[1]) + $l[1] = $tData['cost']; + } + + if (!$triggered) + { + $l = &$links[$spell]; + + if (!isset($l)) + $l = [$tData['reqSkill'], $tData['cost']]; + + if ($tData['reqSkill'] < $l[0]) + $l[0] = $tData['reqSkill']; + + if ($tData['cost'] < $l[1]) + $l[1] = $tData['cost']; + } } - if (!$triggered) - { - $l = &$links[$spell]; - - if (!isset($l)) - $l = [$tData['reqSkill'], $tData['cost']]; - - if ($tData['reqSkill'] < $l[0]) - $l[0] = $tData['reqSkill']; - - if ($tData['cost'] < $l[1]) - $l[1] = $tData['cost']; - } + foreach ($links as $spell => $link) + DB::Aowow()->query("UPDATE ?_spell s SET s.learnedAt = ?d, s.trainingCost = ?d WHERE s.id = ?d", $link[0], $link[1], $spell); } - foreach ($links as $spell => $link) - DB::Aowow()->query("UPDATE ?_spell s SET s.learnedAt = ?d, s.trainingCost = ?d WHERE s.id = ?d", $link[0], $link[1], $spell); - } + // fill learnedAt from recipe-items + $recipes = DB::World()->selectCol('SELECT IF(spelltrigger_2 = 6, spellid_2, spellid_1) AS ARRAY_KEY, MIN(RequiredSkillRank) FROM item_template WHERE `class` = 9 AND spelltrigger_1 <> 1 AND RequiredSkillRank > 0 GROUP BY ARRAY_KEY'); + foreach ($recipes as $spell => $reqSkill) + DB::Aowow()->query('UPDATE ?_spell SET learnedAt = IF(learnedAt = 0 OR learnedAt > ?d, ?d, learnedAt) WHERE id = ?d', $reqSkill, $reqSkill, $spell); - // fill learnedAt from recipe-items - $recipes = DB::World()->selectCol('SELECT IF(spelltrigger_2 = 6, spellid_2, spellid_1) AS ARRAY_KEY, MIN(RequiredSkillRank) FROM item_template WHERE `class` = 9 AND spelltrigger_1 <> 1 AND RequiredSkillRank > 0 GROUP BY ARRAY_KEY'); - foreach ($recipes as $spell => $reqSkill) - DB::Aowow()->query('UPDATE ?_spell SET learnedAt = IF(learnedAt = 0 OR learnedAt > ?d, ?d, learnedAt) WHERE id = ?d', $reqSkill, $reqSkill, $spell); + // fill learnedAt from Discovery + // 61756: Northrend Inscription Research (FAST QA VERSION); + // 64323: Book of Glyph Mastery (todo: get reqSkill from item [425]) + // 28571 - 28576: $element Protection Potion (todo: get reqSkill from teaching spell [360]) + $discovery = DB::World()->selectCol(' + SELECT spellId AS ARRAY_KEY, + IF(reqSpell = ?d, ?d, + IF(reqSpell BETWEEN ?d AND ?d, ?d, + IF(reqSkillValue, reqSkillValue, 1))) + FROM skill_discovery_template WHERE reqSpell NOT IN (?a)', 64323, 425, 28571, 28576, 360, [61756]); + foreach ($discovery as $spell => $reqSkill) + DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell); - // fill learnedAt from Discovery - // 61756: Northrend Inscription Research (FAST QA VERSION); - // 64323: Book of Glyph Mastery (todo: get reqSkill from item [425]) - // 28571 - 28576: $element Protection Potion (todo: get reqSkill from teaching spell [360]) - $discovery = DB::World()->selectCol(' - SELECT spellId AS ARRAY_KEY, - IF(reqSpell = ?d, ?d, - IF(reqSpell BETWEEN ?d AND ?d, ?d, - IF(reqSkillValue, reqSkillValue, 1))) - FROM skill_discovery_template WHERE reqSpell NOT IN (?a)', 64323, 425, 28571, 28576, 360, [61756]); - foreach ($discovery as $spell => $reqSkill) - DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell); - - // calc reqSkill for gethering-passives (herbing, mining, skinning) (on second thought .. it is set in skilllineability >.<) - $sets = DB::World()->selectCol('SELECT spell_id AS ARRAY_KEY, rank * 75 AS reqSkill FROM spell_ranks WHERE first_spell_id IN (?a)', [55428, 53120, 53125]); - foreach ($sets as $spell => $reqSkill) - DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell); + // calc reqSkill for gethering-passives (herbing, mining, skinning) (on second thought .. it is set in skilllineability >.<) + $sets = DB::World()->selectCol('SELECT spell_id AS ARRAY_KEY, rank * 75 AS reqSkill FROM spell_ranks WHERE first_spell_id IN (?a)', [55428, 53120, 53125]); + foreach ($sets as $spell => $reqSkill) + DB::Aowow()->query('UPDATE ?_spell SET learnedAt = ?d WHERE id = ?d', $reqSkill, $spell); - /******************/ - /* talent related */ - /******************/ + /******************/ + /* talent related */ + /******************/ - CLI::write(' - linking with talent'); + CLI::write(' - linking with talent'); - for ($i = 1; $i < 6; $i++) - { - // classMask - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.reqClassMask = tt.classMask WHERE tt.creatureFamilyMask = 0 AND tt.id = t.tabId AND t.rank?d = s.id', $i); - // talentLevel - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 5) + 10 + (?d * 1) WHERE tt.id = t.tabId AND tt.creatureFamilyMask = 0 AND t.rank?d = s.id', $i - 1, $i); - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 12) + 20 + (?d * 4) WHERE tt.id = t.tabId AND tt.creatureFamilyMask <> 0 AND t.rank?d = s.id', $i - 1, $i); - } + for ($i = 1; $i < 6; $i++) + { + // classMask + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.reqClassMask = tt.classMask WHERE tt.creatureFamilyMask = 0 AND tt.id = t.tabId AND t.rank?d = s.id', $i); + // talentLevel + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 5) + 10 + (?d * 1) WHERE tt.id = t.tabId AND tt.creatureFamilyMask = 0 AND t.rank?d = s.id', $i - 1, $i); + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t, dbc_talenttab tt SET s.talentLevel = (t.row * 12) + 20 + (?d * 4) WHERE tt.id = t.tabId AND tt.creatureFamilyMask <> 0 AND t.rank?d = s.id', $i - 1, $i); + } - // passive talent - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 0 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENT); + // passive talent + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 0 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENT); - // spell taught by talent - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 1 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENTSPELL); + // spell taught by talent + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.cuFlags = s.cuFlags | ?d WHERE t.talentSpell = 1 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)', SPELL_CU_TALENTSPELL); - /*********/ - /* Other */ - /*********/ + /*********/ + /* Other */ + /*********/ - CLI::write(' - misc fixups & icons'); + CLI::write(' - misc fixups & icons'); - // FU [FixUps] - DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask = ?d WHERE skillLine1 = ?d', 1 << 10, 760); // Draenai Racials - DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask = ?d WHERE skillLine1 = ?d', 1 << 9, 756); // Bloodelf Racials - DB::Aowow()->query('UPDATE ?_spell SET reqClassMask = ?d WHERE id = ?d', 1 << 7, 30449); // Mage - Spellsteal + // FU [FixUps] + DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask = ?d WHERE skillLine1 = ?d', 1 << 10, 760); // Draenai Racials + DB::Aowow()->query('UPDATE ?_spell SET reqRaceMask = ?d WHERE skillLine1 = ?d', 1 << 9, 756); // Bloodelf Racials + DB::Aowow()->query('UPDATE ?_spell SET reqClassMask = ?d WHERE id = ?d', 1 << 7, 30449); // Mage - Spellsteal - // triggered by spell - DB::Aowow()->query(' - UPDATE - ?_spell a - JOIN ( - SELECT effect1TriggerSpell as id FROM ?_spell WHERE effect1Id NOT IN (36, 57, 133) AND effect1TriggerSpell <> 0 UNION - SELECT effect2TriggerSpell as id FROM ?_spell WHERE effect2Id NOT IN (36, 57, 133) AND effect2TriggerSpell <> 0 UNION - SELECT effect3TriggerSpell as id FROM ?_spell WHERE effect3Id NOT IN (36, 57, 133) AND effect3TriggerSpell <> 0 - ) as b - SET - cuFlags = cuFlags | ?d - WHERE a.id = b.id', - SPELL_CU_TRIGGERED); - - // altIcons and quality for craftSpells - $itemSpells = DB::Aowow()->selectCol(' - SELECT s.id AS ARRAY_KEY, effect1CreateItemId - FROM dbc_spell s - LEFT JOIN dbc_talent t1 ON t1.rank1 = s.id - LEFT JOIN dbc_talent t2 ON t2.rank2 = s.id - LEFT JOIN dbc_talent t3 ON t3.rank3 = s.id - WHERE effect1CreateItemId > 0 AND effect1Id <> 53 AND t1.id IS NULL AND t2.id IS NULL AND t3.id IS NULL - '); // no enchant-spells & no talents! - $itemInfo = DB::World()->select('SELECT entry AS ARRAY_KEY, displayId AS d, Quality AS q FROM item_template WHERE entry IN (?a)', $itemSpells); - foreach ($itemSpells as $sId => $itemId) - if (isset($itemInfo[$itemId])) - DB::Aowow()->query('UPDATE ?_spell s, ?_icons ic, dbc_spellicon si SET s.iconIdAlt = ?d, s.cuFlags = s.cuFlags | ?d WHERE s.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AND s.id = ?d', -$itemInfo[$itemId]['d'], ((7 - $itemInfo[$itemId]['q']) << 8), $sId); - - // apply specializations [trainerTemplate => reqSpell] - $specs = array( - 201007 => 9788, - 201008 => 9787, - 201015 => 20222, - 201016 => 20219, - 201030 => 10660, - 201031 => 10656, - 201032 => 10658 - ); - foreach ($specs as $tt => $req) - if ($spells = DB::World()->selectCol('SELECT SpellID FROM npc_trainer WHERE ID = ?d', $tt)) - DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE id IN (?a)', $req, $spells); - - $itemReqs = DB::World()->selectCol('SELECT entry AS ARRAY_KEY, requiredSpell FROM item_template WHERE requiredSpell NOT IN (?a)', [0, 34090, 34091]); // not riding - foreach ($itemReqs AS $itemId => $req) - DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE skillLine1 IN (?a) AND effect1CreateItemId = ?d', $req, [164, 165, 197, 202], $itemId); - - DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = id WHERE id IN (?a)', [9788, 9787, 20222, 20219, 10660, 10656, 10658, 26797, 26798, 26801, 17039, 17040, 17041]); - - // setting icons - DB::Aowow()->query('UPDATE ?_spell s, ?_icons ic, dbc_spellicon si SET s.iconId = ic.id WHERE s.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1))'); - - // hide internal stuff from listviews - // QA*; *DND*; square brackets anything; *(NYI)*; *(TEST)* - // cant catch raw: NYI (uNYIelding); PH (PHasing) - DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE name_loc0 LIKE "QA%" OR name_loc0 LIKE "%DND%" OR name_loc0 LIKE "%[%" OR name_loc0 LIKE "%(NYI)%" OR name_loc0 LIKE "%(TEST)%"', CUSTOM_EXCLUDE_FOR_LISTVIEW); - - - /**************/ - /* Categories */ - /**************/ - - CLI::write(' - applying categories'); - - // player talents (-2) - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -2 WHERE t.tabId NOT IN (409, 410, 411) AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)'); - - // pet spells (-3) - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -3 WHERE (s.cuFlags & 0x3) = 0 AND s.skillline1 IN (?a)', - array_merge( - array_column(Game::$skillLineMask[-1], 1), // hunter pets - array_column(Game::$skillLineMask[-2], 1), // warlock pets - [270, 782], // hunter generic, DK - Ghoul - [-1, -2] // super categories - ) - ); - - // racials (-4) - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -4 WHERE s.skillLine1 IN (101, 124, 125, 126, 220, 733, 753, 754, 756, 760)'); - - // mounts (-5) - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -5 WHERE s.effect1AuraId = 78 AND (s.skillLine1 IN (354, 594, 772, 777) OR (s.skillLine1 > 0 AND s.skillLine2OrMask = 777))'); - - // companions (-6) - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -6 WHERE s.skillLine1 = 778'); - - // pet talents (-7) - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x10 WHERE t.tabId = 409 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3)'); - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x08 WHERE t.tabId = 410 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3)'); - DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x20 WHERE t.tabId = 411 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3)'); - - // internal (-9) by faaaaaar not complete - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.skillLine1 = 769'); - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.typeCat = 0 AND s.cuFlags = 0 AND ( - s.name_loc0 LIKE "%qa%" OR - s.name_loc0 LIKE "%debug%" OR - s.name_loc0 LIKE "%internal%" OR - s.name_loc0 LIKE "%(NYI)%" OR - s.name_loc0 LIKE "%(TEST)%" OR - s.name_loc0 LIKE "%(OLD)%")' - ); - - // proficiencies (-11) - DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = -11 WHERE s.skillLine1 = sl.id AND sl.categoryId IN (6, 8, 10)'); - - // glyphs (-13) - DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.cuFlags = s.cuFlags | IF(gp.typeFlags, ?d, ?d), s.typeCat = -13 WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74', SPELL_CU_GLYPH_MINOR, SPELL_CU_GLYPH_MAJOR); - $glyphs = DB::World()->selectCol('SELECT it.spellid_1 AS ARRAY_KEY, it.AllowableClass FROM item_template it WHERE it.class = 16'); - foreach ($glyphs as $spell => $classMask) - DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.reqClassMask = ?d WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74 AND s.id = ?d', $classMask, $spell); - - // class Spells (7) - DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = 7 WHERE s.typeCat = 0 AND s.skillLine1 = sl.id AND sl.categoryId = 7'); - - // hide some internal/unused stuffs - DB::Aowow()->query('UPDATE ?_spell s SET s.cuFlags = ?d WHERE s.typeCat = 7 AND ( - s.name_loc0 LIKE "%passive%" OR s.name_loc0 LIKE "%effect%" OR s.name_loc0 LIKE "%improved%" OR s.name_loc0 LIKE "%prototype%" OR -- can probably be extended - (s.id NOT IN (47241, 59879, 59671) AND s.baseLevel <= 1 AND s.reqclassMask = 0) OR -- can probably still be extended - (s.SpellFamilyId = 15 AND s.SpellFamilyFlags1 & 0x2000 AND s.SpellDescriptionVariableId <> 84) OR -- DK: Skill Coil - (s.SpellFamilyId = 10 AND s.SpellFamilyFlags2 & 0x1000000 AND s.attributes1 = 0) OR -- Paladin: Bacon of Light hmm.. Bacon.... :] - (s.SpellFamilyId = 6 AND s.SpellFamilyFlags3 & 0x4000) OR -- Priest: Lolwell Renew - (s.SpellFamilyId = 6 AND s.SpellFamilyFlags1 & 0x8000000 AND s.rank_loc0 <> "") OR -- Priest: Bling Bling - (s.SpellFamilyId = 8 AND s.attributes0 = 0x50 AND s.attributes1 & 0x400) OR -- Rogue: Intuition (dropped Talent..? looks nice though) - (s.SpellfamilyId = 11 AND s.SpellFamilyFlags1 & 3 AND s.attributes1 = 1024) OR -- Shaman: Lightning Overload procs - (s.attributes0 = 0x20000000 AND s.attributes3 = 0x10000000) OR -- Master Demonologist (FamilyId = 0) - s.id IN (47633, 22845, 29442, 31643, 44450, 32841, 20154, 34919, 27813, 27817, 27818, 30708, 30874, 379, 21169, 19483, 29886, 58889, 23885, 29841, 29842, 64380, 58427) OR -- Misc - s.id IN (48954, 17567, 66175, 66122, 66123, 66124, 52374, 49575, 56816, 50536) -- Misc cont. - )', CUSTOM_EXCLUDE_FOR_LISTVIEW); - - foreach ([1, 2, 3, 4, 5, 6, 7, 8, 9, 11] as $classId) + // triggered by spell DB::Aowow()->query(' UPDATE - ?_spell s, - dbc_skillline sl, - dbc_skillraceclassinfo srci + ?_spell a + JOIN ( + SELECT effect1TriggerSpell as id FROM ?_spell WHERE effect1Id NOT IN (36, 57, 133) AND effect1TriggerSpell <> 0 UNION + SELECT effect2TriggerSpell as id FROM ?_spell WHERE effect2Id NOT IN (36, 57, 133) AND effect2TriggerSpell <> 0 UNION + SELECT effect3TriggerSpell as id FROM ?_spell WHERE effect3Id NOT IN (36, 57, 133) AND effect3TriggerSpell <> 0 + ) as b SET - s.reqClassMask = srci.classMask - WHERE - s.typeCat IN (-2, 7) AND - (s.attributes0 & 0x80) = 0 AND - s.skillLine1 = srci.skillLine AND - sl.categoryId = 7 AND - srci.skillline <> 769 AND - srci.skillline = sl.id AND - srci.flags & 0x90 AND - srci.classMask & ?d', - 1 << ($classId - 1) + cuFlags = cuFlags | ?d + WHERE a.id = b.id', + SPELL_CU_TRIGGERED); + + // altIcons and quality for craftSpells + $itemSpells = DB::Aowow()->selectCol(' + SELECT s.id AS ARRAY_KEY, effect1CreateItemId + FROM dbc_spell s + LEFT JOIN dbc_talent t1 ON t1.rank1 = s.id + LEFT JOIN dbc_talent t2 ON t2.rank2 = s.id + LEFT JOIN dbc_talent t3 ON t3.rank3 = s.id + WHERE effect1CreateItemId > 0 AND effect1Id <> 53 AND t1.id IS NULL AND t2.id IS NULL AND t3.id IS NULL + '); // no enchant-spells & no talents! + $itemInfo = DB::World()->select('SELECT entry AS ARRAY_KEY, displayId AS d, Quality AS q FROM item_template WHERE entry IN (?a)', $itemSpells); + foreach ($itemSpells as $sId => $itemId) + if (isset($itemInfo[$itemId])) + DB::Aowow()->query('UPDATE ?_spell s, ?_icons ic, dbc_spellicon si SET s.iconIdAlt = ?d, s.cuFlags = s.cuFlags | ?d WHERE s.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AND s.id = ?d', -$itemInfo[$itemId]['d'], ((7 - $itemInfo[$itemId]['q']) << 8), $sId); + + // apply specializations [trainerTemplate => reqSpell] + $specs = array( + 201007 => 9788, + 201008 => 9787, + 201015 => 20222, + 201016 => 20219, + 201030 => 10660, + 201031 => 10656, + 201032 => 10658 + ); + foreach ($specs as $tt => $req) + if ($spells = DB::World()->selectCol('SELECT SpellID FROM npc_trainer WHERE ID = ?d', $tt)) + DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE id IN (?a)', $req, $spells); + + $itemReqs = DB::World()->selectCol('SELECT entry AS ARRAY_KEY, requiredSpell FROM item_template WHERE requiredSpell NOT IN (?a)', [0, 34090, 34091]); // not riding + foreach ($itemReqs AS $itemId => $req) + DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = ?d WHERE skillLine1 IN (?a) AND effect1CreateItemId = ?d', $req, [164, 165, 197, 202], $itemId); + + DB::Aowow()->query('UPDATE ?_spell SET reqSpellId = id WHERE id IN (?a)', [9788, 9787, 20222, 20219, 10660, 10656, 10658, 26797, 26798, 26801, 17039, 17040, 17041]); + + // setting icons + DB::Aowow()->query('UPDATE ?_spell s, ?_icons ic, dbc_spellicon si SET s.iconId = ic.id WHERE s.iconIdBak = si.id AND ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1))'); + + // hide internal stuff from listviews + // QA*; *DND*; square brackets anything; *(NYI)*; *(TEST)* + // cant catch raw: NYI (uNYIelding); PH (PHasing) + DB::Aowow()->query('UPDATE ?_spell SET cuFlags = cuFlags | ?d WHERE name_loc0 LIKE "QA%" OR name_loc0 LIKE "%DND%" OR name_loc0 LIKE "%[%" OR name_loc0 LIKE "%(NYI)%" OR name_loc0 LIKE "%(TEST)%"', CUSTOM_EXCLUDE_FOR_LISTVIEW); + + + /**************/ + /* Categories */ + /**************/ + + CLI::write(' - applying categories'); + + // player talents (-2) + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -2 WHERE t.tabId NOT IN (409, 410, 411) AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3 OR s.id = t.rank4 OR s.id = t.rank5)'); + + // pet spells (-3) + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -3 WHERE (s.cuFlags & 0x3) = 0 AND s.skillline1 IN (?a)', + array_merge( + array_column(Game::$skillLineMask[-1], 1), // hunter pets + array_column(Game::$skillLineMask[-2], 1), // warlock pets + [270, 782], // hunter generic, DK - Ghoul + [-1, -2] // super categories + ) ); - // secondary Skills (9) - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 9 WHERE s.typeCat = 0 AND (s.skillLine1 IN (129, 185, 356, 762) OR (s.skillLine1 > 0 AND s.skillLine2OrMask IN (129, 185, 356, 762)))'); + // racials (-4) + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -4 WHERE s.skillLine1 IN (101, 124, 125, 126, 220, 733, 753, 754, 756, 760)'); - // primary Skills (11) - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 11 WHERE s.typeCat = 0 AND s.skillLine1 IN (164, 165, 171, 182, 186, 197, 202, 333, 393, 755, 773)'); + // mounts (-5) + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -5 WHERE s.effect1AuraId = 78 AND (s.skillLine1 IN (354, 594, 772, 777) OR (s.skillLine1 > 0 AND s.skillLine2OrMask = 777))'); - // npc spells (-8) (run as last! .. missing from npc_scripts? "enum Spells { \s+(\w\d_)+\s+=\s(\d+) }" and "#define SPELL_(\d\w_)+\s+(\d+)") // RAID_MODE(1, 2[, 3, 4]) - macro still not considered - $world = DB::World()->selectCol(' - SELECT ss.action_param1 FROM smart_scripts ss WHERE ss.action_type IN (11, 75, 85, 86) UNION - SELECT ct.spell1 FROM creature_template ct WHERE ct.spell1 <> 0 UNION - SELECT ct.spell2 FROM creature_template ct WHERE ct.spell2 <> 0 UNION - SELECT ct.spell3 FROM creature_template ct WHERE ct.spell3 <> 0 UNION - SELECT ct.spell4 FROM creature_template ct WHERE ct.spell4 <> 0 UNION - SELECT ct.spell5 FROM creature_template ct WHERE ct.spell5 <> 0 UNION - SELECT ct.spell6 FROM creature_template ct WHERE ct.spell6 <> 0 UNION - SELECT ct.spell7 FROM creature_template ct WHERE ct.spell7 <> 0 UNION - SELECT ct.spell8 FROM creature_template ct WHERE ct.spell8 <> 0' - ); + // companions (-6) + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -6 WHERE s.skillLine1 = 778'); - $auras = DB::World()->selectCol('SELECT cta.auras FROM creature_template_addon cta WHERE auras <> ""'); - foreach ($auras as $a) - foreach (explode(' ', $a ) as $spell) - $world[] = $spell; + // pet talents (-7) + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x10 WHERE t.tabId = 409 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3)'); + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x08 WHERE t.tabId = 410 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3)'); + DB::Aowow()->query('UPDATE ?_spell s, dbc_talent t SET s.typeCat = -7, s.cuFlags = s.cuFlags | 0x20 WHERE t.tabId = 411 AND (s.id = t.rank1 OR s.id = t.rank2 OR s.id = t.rank3)'); - DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -8 WHERE s.typeCat = 0 AND s.id In (?a)', $world); + // internal (-9) by faaaaaar not complete + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.skillLine1 = 769'); + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -9 WHERE s.typeCat = 0 AND s.cuFlags = 0 AND ( + s.name_loc0 LIKE "%qa%" OR + s.name_loc0 LIKE "%debug%" OR + s.name_loc0 LIKE "%internal%" OR + s.name_loc0 LIKE "%(NYI)%" OR + s.name_loc0 LIKE "%(TEST)%" OR + s.name_loc0 LIKE "%(OLD)%")' + ); + + // proficiencies (-11) + DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = -11 WHERE s.skillLine1 = sl.id AND sl.categoryId IN (6, 8, 10)'); + + // glyphs (-13) + DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.cuFlags = s.cuFlags | IF(gp.typeFlags, ?d, ?d), s.typeCat = -13 WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74', SPELL_CU_GLYPH_MINOR, SPELL_CU_GLYPH_MAJOR); + $glyphs = DB::World()->selectCol('SELECT it.spellid_1 AS ARRAY_KEY, it.AllowableClass FROM item_template it WHERE it.class = 16'); + foreach ($glyphs as $spell => $classMask) + DB::Aowow()->query('UPDATE ?_spell s, dbc_glyphproperties gp SET s.reqClassMask = ?d WHERE gp.typeFlags IN (0, 1) AND gp.id = s.effect1MiscValue AND s.effect1Id = 74 AND s.id = ?d', $classMask, $spell); + + // class Spells (7) + DB::Aowow()->query('UPDATE ?_spell s, dbc_skillline sl SET s.typeCat = 7 WHERE s.typeCat = 0 AND s.skillLine1 = sl.id AND sl.categoryId = 7'); + + // hide some internal/unused stuffs + DB::Aowow()->query('UPDATE ?_spell s SET s.cuFlags = ?d WHERE s.typeCat = 7 AND ( + s.name_loc0 LIKE "%passive%" OR s.name_loc0 LIKE "%effect%" OR s.name_loc0 LIKE "%improved%" OR s.name_loc0 LIKE "%prototype%" OR -- can probably be extended + (s.id NOT IN (47241, 59879, 59671) AND s.baseLevel <= 1 AND s.reqclassMask = 0) OR -- can probably still be extended + (s.SpellFamilyId = 15 AND s.SpellFamilyFlags1 & 0x2000 AND s.SpellDescriptionVariableId <> 84) OR -- DK: Skill Coil + (s.SpellFamilyId = 10 AND s.SpellFamilyFlags2 & 0x1000000 AND s.attributes1 = 0) OR -- Paladin: Bacon of Light hmm.. Bacon.... :] + (s.SpellFamilyId = 6 AND s.SpellFamilyFlags3 & 0x4000) OR -- Priest: Lolwell Renew + (s.SpellFamilyId = 6 AND s.SpellFamilyFlags1 & 0x8000000 AND s.rank_loc0 <> "") OR -- Priest: Bling Bling + (s.SpellFamilyId = 8 AND s.attributes0 = 0x50 AND s.attributes1 & 0x400) OR -- Rogue: Intuition (dropped Talent..? looks nice though) + (s.SpellfamilyId = 11 AND s.SpellFamilyFlags1 & 3 AND s.attributes1 = 1024) OR -- Shaman: Lightning Overload procs + (s.attributes0 = 0x20000000 AND s.attributes3 = 0x10000000) OR -- Master Demonologist (FamilyId = 0) + s.id IN (47633, 22845, 29442, 31643, 44450, 32841, 20154, 34919, 27813, 27817, 27818, 30708, 30874, 379, 21169, 19483, 29886, 58889, 23885, 29841, 29842, 64380, 58427) OR -- Misc + s.id IN (48954, 17567, 66175, 66122, 66123, 66124, 52374, 49575, 56816, 50536) -- Misc cont. + )', CUSTOM_EXCLUDE_FOR_LISTVIEW); + + foreach ([1, 2, 3, 4, 5, 6, 7, 8, 9, 11] as $classId) + DB::Aowow()->query(' + UPDATE + ?_spell s, + dbc_skillline sl, + dbc_skillraceclassinfo srci + SET + s.reqClassMask = srci.classMask + WHERE + s.typeCat IN (-2, 7) AND + (s.attributes0 & 0x80) = 0 AND + s.skillLine1 = srci.skillLine AND + sl.categoryId = 7 AND + srci.skillline <> 769 AND + srci.skillline = sl.id AND + srci.flags & 0x90 AND + srci.classMask & ?d', + 1 << ($classId - 1) + ); + + // secondary Skills (9) + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 9 WHERE s.typeCat = 0 AND (s.skillLine1 IN (129, 185, 356, 762) OR (s.skillLine1 > 0 AND s.skillLine2OrMask IN (129, 185, 356, 762)))'); + + // primary Skills (11) + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = 11 WHERE s.typeCat = 0 AND s.skillLine1 IN (164, 165, 171, 182, 186, 197, 202, 333, 393, 755, 773)'); + + // npc spells (-8) (run as last! .. missing from npc_scripts? "enum Spells { \s+(\w\d_)+\s+=\s(\d+) }" and "#define SPELL_(\d\w_)+\s+(\d+)") // RAID_MODE(1, 2[, 3, 4]) - macro still not considered + $world = DB::World()->selectCol(' + SELECT ss.action_param1 FROM smart_scripts ss WHERE ss.action_type IN (11, 75, 85, 86) UNION + SELECT ct.spell1 FROM creature_template ct WHERE ct.spell1 <> 0 UNION + SELECT ct.spell2 FROM creature_template ct WHERE ct.spell2 <> 0 UNION + SELECT ct.spell3 FROM creature_template ct WHERE ct.spell3 <> 0 UNION + SELECT ct.spell4 FROM creature_template ct WHERE ct.spell4 <> 0 UNION + SELECT ct.spell5 FROM creature_template ct WHERE ct.spell5 <> 0 UNION + SELECT ct.spell6 FROM creature_template ct WHERE ct.spell6 <> 0 UNION + SELECT ct.spell7 FROM creature_template ct WHERE ct.spell7 <> 0 UNION + SELECT ct.spell8 FROM creature_template ct WHERE ct.spell8 <> 0' + ); + + $auras = DB::World()->selectCol('SELECT cta.auras FROM creature_template_addon cta WHERE auras <> ""'); + foreach ($auras as $a) + foreach (explode(' ', $a ) as $spell) + $world[] = $spell; + + DB::Aowow()->query('UPDATE ?_spell s SET s.typeCat = -8 WHERE s.typeCat = 0 AND s.id In (?a)', $world); - /**********/ - /* Glyphs */ - /**********/ + /**********/ + /* Glyphs */ + /**********/ - CLI::write(' - fixing glyph data'); + CLI::write(' - fixing glyph data'); - // glyphSpell => affectedSpell - $glyphAffects = array( - 63959 => 50842, // Pestilence - 58723 => 55090, // Scourge Strike - 58721 => 46584, // Raise Dead - 58711 => 52375, // Death Coil - 54857 => 33876, // Mangle (Cat) - 56881 => 13165, // Aspect of the Hawk - 56598 => 27101, // Conjure Mana Gem (Rank 5) - 63871 => 1038, // Hand of Salvation - 55003 => 53407, // Judgement of Justice - 63873 => 47788, // Guardian Spirit - 58258 => 2983, // Sprint - 55535 => 52127, // Water Shield - 55558 => 16190, // Mana Tide Totem - 56302 => 697, // Summon Voidwalker - 56299 => 712, // Summon Succubus - 58272 => 126, // Summon Eye of Kilrogg - 56292 => 688, // Summon Imp - 56286 => 691, // Summon Felhunter - 56285 => 30146, // Summon Felguard - 58275 => 29893, // Ritual of Souls - 63941 => 1454, // Life Tap - 56289 => 5699, // Create Healthstone - 56297 => 693, // Create Soulstone - 58271 => 1120, // Drain Soul - 58281 => 34428, // Victory Rush - 58397 => 23922, // Shield Slam - 63949 => 50720 // Vigilance - ); + // glyphSpell => affectedSpell + $glyphAffects = array( + 63959 => 50842, // Pestilence + 58723 => 55090, // Scourge Strike + 58721 => 46584, // Raise Dead + 58711 => 52375, // Death Coil + 54857 => 33876, // Mangle (Cat) + 56881 => 13165, // Aspect of the Hawk + 56598 => 27101, // Conjure Mana Gem (Rank 5) + 63871 => 1038, // Hand of Salvation + 55003 => 53407, // Judgement of Justice + 63873 => 47788, // Guardian Spirit + 58258 => 2983, // Sprint + 55535 => 52127, // Water Shield + 55558 => 16190, // Mana Tide Totem + 56302 => 697, // Summon Voidwalker + 56299 => 712, // Summon Succubus + 58272 => 126, // Summon Eye of Kilrogg + 56292 => 688, // Summon Imp + 56286 => 691, // Summon Felhunter + 56285 => 30146, // Summon Felguard + 58275 => 29893, // Ritual of Souls + 63941 => 1454, // Life Tap + 56289 => 5699, // Create Healthstone + 56297 => 693, // Create Soulstone + 58271 => 1120, // Drain Soul + 58281 => 34428, // Victory Rush + 58397 => 23922, // Shield Slam + 63949 => 50720 // Vigilance + ); - $queryIcons = ' - SELECT s.id, s.name_loc0, s.skillLine1 as skill, ic.id as icon, s.typeCat * s.typeCat AS prio - FROM ?_spell s - LEFT JOIN dbc_spellicon si ON s.iconIdBak = si.id - LEFT JOIN ?_icons ic ON ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) - WHERE [WHERE] AND (s.cuFlags & ?d) = 0 AND s.typeCat IN (0, 7, -2) -- not triggered; class spells first, talents second, unk last - ORDER BY prio DESC - '; + $queryIcons = ' + SELECT s.id, s.name_loc0, s.skillLine1 as skill, ic.id as icon, s.typeCat * s.typeCat AS prio + FROM ?_spell s + LEFT JOIN dbc_spellicon si ON s.iconIdBak = si.id + LEFT JOIN ?_icons ic ON ic.name = LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) + WHERE [WHERE] AND (s.cuFlags & ?d) = 0 AND s.typeCat IN (0, 7, -2) -- not triggered; class spells first, talents second, unk last + ORDER BY prio DESC + '; - $effects = DB::Aowow()->select(' - SELECT - s2.id AS ARRAY_KEY, - s1.id, - s1.name_loc0, - s1.spellFamilyId, - s1.spellFamilyFlags1, s1.spellFamilyFlags2, s1.spellFamilyFlags3, - s1.effect1Id, s1.effect2Id, s1.effect3Id, - s1.effect1SpellClassMaskA, s1.effect1SpellClassMaskB, s1.effect1SpellClassMaskC, - s1.effect2SpellClassMaskA, s1.effect2SpellClassMaskB, s1.effect2SpellClassMaskC, - s1.effect3SpellClassMaskA, s1.effect3SpellClassMaskB, s1.effect3SpellClassMaskC - FROM - dbc_glyphproperties gp - JOIN - ?_spell s1 ON s1.id = gp.spellId - JOIN - ?_spell s2 ON s2.effect1MiscValue = gp.id AND s2.effect1Id = 74 - WHERE - gp.typeFlags IN (0, 1) -- AND s2.id In (58271, 56297, 56289, 63941, 58275) - '); + $effects = DB::Aowow()->select(' + SELECT + s2.id AS ARRAY_KEY, + s1.id, + s1.name_loc0, + s1.spellFamilyId, + s1.spellFamilyFlags1, s1.spellFamilyFlags2, s1.spellFamilyFlags3, + s1.effect1Id, s1.effect2Id, s1.effect3Id, + s1.effect1SpellClassMaskA, s1.effect1SpellClassMaskB, s1.effect1SpellClassMaskC, + s1.effect2SpellClassMaskA, s1.effect2SpellClassMaskB, s1.effect2SpellClassMaskC, + s1.effect3SpellClassMaskA, s1.effect3SpellClassMaskB, s1.effect3SpellClassMaskC + FROM + dbc_glyphproperties gp + JOIN + ?_spell s1 ON s1.id = gp.spellId + JOIN + ?_spell s2 ON s2.effect1MiscValue = gp.id AND s2.effect1Id = 74 + WHERE + gp.typeFlags IN (0, 1) -- AND s2.id In (58271, 56297, 56289, 63941, 58275) + '); - foreach ($effects as $applyId => $glyphEffect) - { - $l = [null, 'A', 'B', 'C']; - $i = 0; - $icons = []; - $fam = $glyphEffect['spellFamilyId']; - - // first: manuall replace - if ($applyId == 57144) // has no skillLine.. :/ + foreach ($effects as $applyId => $glyphEffect) { - DB::Aowow()->query('UPDATE ?_spell s, ?_icons ic SET s.skillLine1 = ?d, s.iconIdAlt = ic.id WHERE s.id = ?d AND ic.name = ?', 253, 57144, 'ability_poisonsting'); - continue; - } + $l = [null, 'A', 'B', 'C']; + $i = 0; + $icons = []; + $fam = $glyphEffect['spellFamilyId']; - // second: search by name and family equality - if (!$icons) - { - $search = !empty($glyphAffects[$applyId]) ? $glyphAffects[$applyId] : str_replace('Glyph of ', '', $glyphEffect['name_loc0']); - if (is_int($search)) - $where = "?d AND s.id = ?d"; - else - $where = "s.SpellFamilyId = ?d AND s.name_loc0 LIKE ?"; - - $qry = str_replace('[WHERE]', $where, $queryIcons); - $icons = DB::Aowow()->selectRow($qry, $fam ?: 1, $search, SPELL_CU_TRIGGERED); - } - - // third: match by SpellFamily affect mask - while (empty($icons) && $i < 3) - { - $i++; - $m1 = $glyphEffect['effect1SpellClassMask'.$l[$i]]; - $m2 = $glyphEffect['effect2SpellClassMask'.$l[$i]]; - $m3 = $glyphEffect['effect3SpellClassMask'.$l[$i]]; - - if ($glyphEffect['effect'.$i.'Id'] != 6 || (!$m1 && !$m2 && !$m3)) + // first: manuall replace + if ($applyId == 57144) // has no skillLine.. :/ + { + DB::Aowow()->query('UPDATE ?_spell s, ?_icons ic SET s.skillLine1 = ?d, s.iconIdAlt = ic.id WHERE s.id = ?d AND ic.name = ?', 253, 57144, 'ability_poisonsting'); continue; + } - $where = "s.SpellFamilyId = ?d AND (s.SpellFamilyFlags1 & ?d OR s.SpellFamilyFlags2 & ?d OR s.SpellFamilyFlags3 & ?d)"; + // second: search by name and family equality + if (!$icons) + { + $search = !empty($glyphAffects[$applyId]) ? $glyphAffects[$applyId] : str_replace('Glyph of ', '', $glyphEffect['name_loc0']); + if (is_int($search)) + $where = "?d AND s.id = ?d"; + else + $where = "s.SpellFamilyId = ?d AND s.name_loc0 LIKE ?"; - $icons = DB::Aowow()->selectRow(str_replace('[WHERE]', $where, $queryIcons), $fam, $m1, $m2, $m3, SPELL_CU_TRIGGERED); + $qry = str_replace('[WHERE]', $where, $queryIcons); + $icons = DB::Aowow()->selectRow($qry, $fam ?: 1, $search, SPELL_CU_TRIGGERED); + } + + // third: match by SpellFamily affect mask + while (empty($icons) && $i < 3) + { + $i++; + $m1 = $glyphEffect['effect1SpellClassMask'.$l[$i]]; + $m2 = $glyphEffect['effect2SpellClassMask'.$l[$i]]; + $m3 = $glyphEffect['effect3SpellClassMask'.$l[$i]]; + + if ($glyphEffect['effect'.$i.'Id'] != 6 || (!$m1 && !$m2 && !$m3)) + continue; + + $where = "s.SpellFamilyId = ?d AND (s.SpellFamilyFlags1 & ?d OR s.SpellFamilyFlags2 & ?d OR s.SpellFamilyFlags3 & ?d)"; + + $icons = DB::Aowow()->selectRow(str_replace('[WHERE]', $where, $queryIcons), $fam, $m1, $m2, $m3, SPELL_CU_TRIGGERED); + } + + if ($icons) + DB::Aowow()->query('UPDATE ?_spell s SET s.skillLine1 = ?d, s.iconIdAlt = ?d WHERE s.id = ?d', $icons['skill'], $icons['icon'], $applyId); + else + CLI::write('could not match '.$glyphEffect['name_loc0'].' ('.$glyphEffect['id'].') with affected spells', CLI::LOG_WARN); } - if ($icons) - DB::Aowow()->query('UPDATE ?_spell s SET s.skillLine1 = ?d, s.iconIdAlt = ?d WHERE s.id = ?d', $icons['skill'], $icons['icon'], $applyId); - else - CLI::write('could not match '.$glyphEffect['name_loc0'].' ('.$glyphEffect['id'].') with affected spells', CLI::LOG_WARN); + // hide unused glyphs + DB::Aowow()->query('UPDATE ?_spell SET skillLine1 = 0, iconIdAlt = 0, cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [60460, 58166, 58239, 58240, 58261, 58262, 54910]); + + return true; } - - // hide unused glyphs - DB::Aowow()->query('UPDATE ?_spell SET skillLine1 = 0, iconIdAlt = 0, cuFlags = cuFlags | ?d WHERE id IN (?a)', CUSTOM_EXCLUDE_FOR_LISTVIEW, [60460, 58166, 58239, 58240, 58261, 58262, 54910]); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/spelldifficulty.func.php b/setup/tools/sqlgen/spelldifficulty.func.php index bb3ac1b5..1efb15ed 100644 --- a/setup/tools/sqlgen/spelldifficulty.func.php +++ b/setup/tools/sqlgen/spelldifficulty.func.php @@ -7,26 +7,26 @@ if (!CLI) die('not in cli mode'); -/* deps: - * spelldifficulty_dbc -*/ - -$customData = array( -); -$reqDBC = ['spelldifficulty']; - -function spelldifficulty(array $ids = []) +SqlGen::register(new class extends SetupScript { - // has no unique keys.. - DB::Aowow()->query('TRUNCATE TABLE ?_spelldifficulty'); + protected $command = 'spelldifficulty'; - DB::Aowow()->query('INSERT INTO ?_spelldifficulty SELECT * FROM dbc_spelldifficulty'); + protected $tblDependancyTC = ['spelldifficulty_dbc']; + protected $dbcSourceFiles = ['spelldifficulty']; - $rows = DB::World()->select('SELECT spellid0, spellid1, spellid2, spellid3 FROM spelldifficulty_dbc'); - foreach ($rows as $r) - DB::Aowow()->query('INSERT INTO ?_spelldifficulty VALUES (?a)', array_values($r)); + public function generate(array $ids = []) : bool + { + // has no unique keys.. + DB::Aowow()->query('TRUNCATE TABLE ?_spelldifficulty'); - return true; -} + DB::Aowow()->query('INSERT INTO ?_spelldifficulty SELECT * FROM dbc_spelldifficulty'); + + $rows = DB::World()->select('SELECT spellid0, spellid1, spellid2, spellid3 FROM spelldifficulty_dbc'); + foreach ($rows as $r) + DB::Aowow()->query('INSERT INTO ?_spelldifficulty VALUES (?a)', array_values($r)); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/spellfocusobject.func.php b/setup/tools/sqlgen/spellfocusobject.func.php new file mode 100644 index 00000000..f34f8704 --- /dev/null +++ b/setup/tools/sqlgen/spellfocusobject.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/spelloverride.func.php b/setup/tools/sqlgen/spelloverride.func.php new file mode 100644 index 00000000..42ee3461 --- /dev/null +++ b/setup/tools/sqlgen/spelloverride.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/spellrange.func.php b/setup/tools/sqlgen/spellrange.func.php new file mode 100644 index 00000000..e9a32b29 --- /dev/null +++ b/setup/tools/sqlgen/spellrange.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/spellvariables.func.php b/setup/tools/sqlgen/spellvariables.func.php new file mode 100644 index 00000000..12d45aa3 --- /dev/null +++ b/setup/tools/sqlgen/spellvariables.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/talents.func.php b/setup/tools/sqlgen/talents.func.php index 443b0c4c..f9940ffe 100644 --- a/setup/tools/sqlgen/talents.func.php +++ b/setup/tools/sqlgen/talents.func.php @@ -7,35 +7,38 @@ if (!CLI) die('not in cli mode'); -$customData = array( -); -$reqDBC = ['talent', 'talenttab']; - -function talents() +SqlGen::register(new class extends SetupScript { - // class: 0 => hunter pets - for ($i = 1; $i < 6; $i++) - DB::Aowow()->query(' - REPLACE INTO - ?_talents - SELECT - t.id, - IF(tt.classMask <> 0, LOG(2, tt.classMask) + 1, 0), - tt.creatureFamilyMask, - IF(tt.creaturefamilyMask <> 0, LOG(2, tt.creaturefamilyMask), tt.tabNumber), - t.row, - t.column, - t.rank?d, - ?d - FROM - dbc_talenttab tt - JOIN - dbc_talent t ON tt.id = t.tabId - WHERE - t.rank?d <> 0 - ', $i, $i, $i); + protected $command = 'talents'; - return true; -} + protected $dbcSourceFiles = ['talent', 'talenttab']; + + public function generate(array $ids = []) : bool + { + // class: 0 => hunter pets + for ($i = 1; $i < 6; $i++) + DB::Aowow()->query(' + REPLACE INTO + ?_talents + SELECT + t.id, + IF(tt.classMask <> 0, LOG(2, tt.classMask) + 1, 0), + tt.creatureFamilyMask, + IF(tt.creaturefamilyMask <> 0, LOG(2, tt.creaturefamilyMask), tt.tabNumber), + t.row, + t.column, + t.rank?d, + ?d + FROM + dbc_talenttab tt + JOIN + dbc_talent t ON tt.id = t.tabId + WHERE + t.rank?d <> 0 + ', $i, $i, $i); + + return true; + } +}); ?> diff --git a/setup/tools/sqlgen/taxi.func.php b/setup/tools/sqlgen/taxi.func.php index 80c7bf51..022b7b10 100644 --- a/setup/tools/sqlgen/taxi.func.php +++ b/setup/tools/sqlgen/taxi.func.php @@ -7,170 +7,169 @@ if (!CLI) die('not in cli mode'); -/* deps - * creature_template - * creature -*/ - -$customData = array( -); -$reqDBC = ['taxipath', 'taxinodes', 'worldmaparea', 'worldmaptransforms', 'factiontemplate']; - -function taxi() // path & nodes +SqlGen::register(new class extends SetupScript { - /*********/ - /* paths */ - /*********/ + protected $command = 'taxi'; // path & nodes - DB::Aowow()->query('REPLACE INTO ?_taxipath SELECT tp.id, tp.startNodeId, tp.endNodeId FROM dbc_taxipath tp WHERE tp.startNodeId > 0 AND tp.EndNodeId > 0'); + protected $tblDependancyTC = ['creature', 'creature_template']; + protected $dbcSourceFiles = ['taxipath', 'taxinodes', 'worldmaparea', 'worldmaptransforms', 'factiontemplate']; - // paths are monodirectional and thus exist twice for regular flight travel (which is bidirectional) - $paths = DB::Aowow()->select('SELECT id AS ARRAY_KEY, tp.* FROM ?_taxipath tp'); - foreach ($paths as $i => $p) + public function generate(array $ids = []) : bool { - foreach ($paths as $j => $_) + /*********/ + /* paths */ + /*********/ + + DB::Aowow()->query('REPLACE INTO ?_taxipath SELECT tp.id, tp.startNodeId, tp.endNodeId FROM dbc_taxipath tp WHERE tp.startNodeId > 0 AND tp.EndNodeId > 0'); + + // paths are monodirectional and thus exist twice for regular flight travel (which is bidirectional) + $paths = DB::Aowow()->select('SELECT id AS ARRAY_KEY, tp.* FROM ?_taxipath tp'); + foreach ($paths as $i => $p) { - if ($_['startNodeId'] == $p['endNodeId'] AND $_['endNodeId'] == $p['startNodeId']) + foreach ($paths as $j => $_) { - DB::Aowow()->query('DELETE FROM ?_taxipath WHERE id = ?d', $j); - unset($paths[$j]); - unset($paths[$i]); - break; + if ($_['startNodeId'] == $p['endNodeId'] AND $_['endNodeId'] == $p['startNodeId']) + { + DB::Aowow()->query('DELETE FROM ?_taxipath WHERE id = ?d', $j); + unset($paths[$j]); + unset($paths[$i]); + break; + } } } - } - /*********/ - /* nodes */ - /*********/ + /*********/ + /* nodes */ + /*********/ - // all sensible nodes - $fNodes = DB::Aowow()->select( - 'SELECT - tn.id, - tn.mapId, - 100 - ROUND((tn.posY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, - 100 - ROUND((tn.posX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, - 1 AS type, - 0 AS typeId, - 1 AS reactA, - 1 AS reactH, - tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, - tn.mapId AS origMap, - tn.posX AS origPosX, - tn.posY AS origPosY, - IF (tn.id NOT IN (15, 148, 225, 235) AND - ( - tn.id IN (64, 250) OR + // all sensible nodes + $fNodes = DB::Aowow()->select( + 'SELECT + tn.id, + tn.mapId, + 100 - ROUND((tn.posY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, + 100 - ROUND((tn.posX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, + 1 AS type, + 0 AS typeId, + 1 AS reactA, + 1 AS reactH, + tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, + tn.mapId AS origMap, + tn.posX AS origPosX, + tn.posY AS origPosY, + IF (tn.id NOT IN (15, 148, 225, 235) AND ( - tn.name_loc0 NOT LIKE "%Transport%" AND - tn.name_loc0 NOT LIKE "%Quest%" AND - tn.name_loc0 NOT LIKE "%Start%" AND - tn.name_loc0 NOT LIKE "%End%" - ) - ), 0, 1) AS scripted - FROM - dbc_taxinodes tn - JOIN - dbc_worldmaparea wma ON ( tn.mapId = wma.mapId AND tn.posX BETWEEN wma.bottom AND wma.top AND tn.posY BETWEEN wma.right AND wma.left) - WHERE - wma.areaId = 0 AND - wma.mapId = tn.mapId - UNION - SELECT - tn.id, - wmt.targetMapId, - 100 - ROUND((tn.posY + wmt.offsetY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, - 100 - ROUND((tn.posX + wmt.offsetX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, - 1 AS type, - 0 AS typeId, - 1 AS reactA, - 1 AS reactH, - tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, - tn.mapId AS origMap, - tn.posX AS origPosX, - tn.posY AS origPosY, - IF (tn.name_loc0 NOT LIKE "%Transport%" AND tn.name_loc0 NOT LIKE "%Quest%" AND tn.name_loc0 NOT LIKE "%Start%" AND tn.name_loc0 NOT LIKE "%End%", - 0, - 1 - ) AS scripted - FROM - dbc_taxinodes tn - JOIN - dbc_worldmaptransforms wmt ON ( tn.mapId = wmt.sourceMapId AND tn.posX BETWEEN wmt.minX AND wmt.maxX AND tn.posY BETWEEN wmt.minY AND wmt.maxY) - JOIN - dbc_worldmaparea wma ON ( wmt.targetMapId = wma.mapId AND tn.posX + wmt.offsetX BETWEEN wma.bottom AND wma.top AND tn.posY + wmt.offsetY BETWEEN wma.right AND wma.left) - WHERE - wma.areaId = 0 AND - wmt.sourcemapId = tn.mapId' - ); + tn.id IN (64, 250) OR + ( + tn.name_loc0 NOT LIKE "%Transport%" AND + tn.name_loc0 NOT LIKE "%Quest%" AND + tn.name_loc0 NOT LIKE "%Start%" AND + tn.name_loc0 NOT LIKE "%End%" + ) + ), 0, 1) AS scripted + FROM + dbc_taxinodes tn + JOIN + dbc_worldmaparea wma ON ( tn.mapId = wma.mapId AND tn.posX BETWEEN wma.bottom AND wma.top AND tn.posY BETWEEN wma.right AND wma.left) + WHERE + wma.areaId = 0 AND + wma.mapId = tn.mapId + UNION + SELECT + tn.id, + wmt.targetMapId, + 100 - ROUND((tn.posY + wmt.offsetY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, + 100 - ROUND((tn.posX + wmt.offsetX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, + 1 AS type, + 0 AS typeId, + 1 AS reactA, + 1 AS reactH, + tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, + tn.mapId AS origMap, + tn.posX AS origPosX, + tn.posY AS origPosY, + IF (tn.name_loc0 NOT LIKE "%Transport%" AND tn.name_loc0 NOT LIKE "%Quest%" AND tn.name_loc0 NOT LIKE "%Start%" AND tn.name_loc0 NOT LIKE "%End%", + 0, + 1 + ) AS scripted + FROM + dbc_taxinodes tn + JOIN + dbc_worldmaptransforms wmt ON ( tn.mapId = wmt.sourceMapId AND tn.posX BETWEEN wmt.minX AND wmt.maxX AND tn.posY BETWEEN wmt.minY AND wmt.maxY) + JOIN + dbc_worldmaparea wma ON ( wmt.targetMapId = wma.mapId AND tn.posX + wmt.offsetX BETWEEN wma.bottom AND wma.top AND tn.posY + wmt.offsetY BETWEEN wma.right AND wma.left) + WHERE + wma.areaId = 0 AND + wmt.sourcemapId = tn.mapId' + ); - // all available flightmaster - $fMaster = DB::World()->select( - 'SELECT ct.entry, ct.faction, c.map, c.position_x AS posX, c.position_y AS posY FROM creature_template ct JOIN creature c ON c.id = ct.entry WHERE ct.npcflag & ?d OR c.npcflag & ?d', - NPC_FLAG_FLIGHT_MASTER, NPC_FLAG_FLIGHT_MASTER - ); + // all available flightmaster + $fMaster = DB::World()->select( + 'SELECT ct.entry, ct.faction, c.map, c.position_x AS posX, c.position_y AS posY FROM creature_template ct JOIN creature c ON c.id = ct.entry WHERE ct.npcflag & ?d OR c.npcflag & ?d', + NPC_FLAG_FLIGHT_MASTER, NPC_FLAG_FLIGHT_MASTER + ); - // assign nearest flightmaster to node - foreach ($fNodes as &$n) - { - foreach ($fMaster as &$c) + // assign nearest flightmaster to node + foreach ($fNodes as &$n) { - if ($c['map'] != $n['origMap']) - continue; - - $dist = pow($c['posX'] - $n['origPosX'], 2) + pow($c['posY'] - $n['origPosY'], 2); - if ($dist > 1000) - continue; - - if (!isset($n['dist']) || $n['dist'] < $dist) + foreach ($fMaster as &$c) { - $n['dist'] = $dist; - $n['typeId'] = $c['entry']; - $n['faction'] = $c['faction']; + if ($c['map'] != $n['origMap']) + continue; + + $dist = pow($c['posX'] - $n['origPosX'], 2) + pow($c['posY'] - $n['origPosY'], 2); + if ($dist > 1000) + continue; + + if (!isset($n['dist']) || $n['dist'] < $dist) + { + $n['dist'] = $dist; + $n['typeId'] = $c['entry']; + $n['faction'] = $c['faction']; + } } } - } - unset($n); + unset($n); - // fetch reactions per faction - $factions = DB::Aowow()->query(' - SELECT - id AS ARRAY_KEY, - IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 1) AS reactA, - IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 1) AS reactH - FROM - dbc_factiontemplate - WHERE - id IN (?a)', - array_column($fNodes, 'faction') - ); + // fetch reactions per faction + $factions = DB::Aowow()->query(' + SELECT + id AS ARRAY_KEY, + IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 1) AS reactA, + IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 1) AS reactH + FROM + dbc_factiontemplate + WHERE + id IN (?a)', + array_column($fNodes, 'faction') + ); - foreach ($fNodes as $n) - { - // if (empty($n['faction'])) - // { - // CLI::write(' - ['.$n['id'].'] "'.$n['name_loc0'].'" has no NPC assigned ... skipping', CLI::LOG_WARN); - // continue; - // } - - if ($n['scripted'] || empty($n['faction'])) - $n['type'] = $n['typeId'] = 0; - else if (isset($factions[$n['faction']])) + foreach ($fNodes as $n) { - $n['reactA'] = $factions[$n['faction']]['reactA']; - $n['reactH'] = $factions[$n['faction']]['reactH']; + // if (empty($n['faction'])) + // { + // CLI::write(' - ['.$n['id'].'] "'.$n['name_loc0'].'" has no NPC assigned ... skipping', CLI::LOG_WARN); + // continue; + // } + + if ($n['scripted'] || empty($n['faction'])) + $n['type'] = $n['typeId'] = 0; + else if (isset($factions[$n['faction']])) + { + $n['reactA'] = $factions[$n['faction']]['reactA']; + $n['reactH'] = $factions[$n['faction']]['reactH']; + } + + unset($n['faction'], $n['origMap'], $n['origPosX'], $n['origPosY'], $n['dist'], $n['scripted']); + + DB::Aowow()->query('REPLACE INTO ?_taxinodes VALUES (?a)', array_values($n)); } - unset($n['faction'], $n['origMap'], $n['origPosX'], $n['origPosY'], $n['dist'], $n['scripted']); - DB::Aowow()->query('REPLACE INTO ?_taxinodes VALUES (?a)', array_values($n)); + return true; } - - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/titles.func.php b/setup/tools/sqlgen/titles.func.php index 23625b47..07e52cec 100644 --- a/setup/tools/sqlgen/titles.func.php +++ b/setup/tools/sqlgen/titles.func.php @@ -6,22 +6,22 @@ if (!defined('AOWOW_REVISION')) if (!CLI) die('not in cli mode'); -/* deps: - * quest_template - * game_event_seasonal_questrelation - * game_event - * achievement_reward -*/ -$customData = array( - 137 => ['gender' => 2], - 138 => ['gender' => 1], -); -$reqDBC = ['chartitles']; - -function titles() +SqlGen::register(new class extends SetupScript { - $titleHoliday = array( + use TrCustomData; + + protected $command = 'titles'; + + protected $tblDependancyTC = ['quest_template', 'game_event_seasonal_questrelation', 'game_event', 'achievement_reward']; + protected $dbcSourceFiles = ['chartitles']; + + private $customData = array( + 137 => ['gender' => 2], + 138 => ['gender' => 1] + ); + + private $titleHoliday = array( 137 => 201, 138 => 201, 124 => 324, @@ -35,69 +35,72 @@ function titles() 168 => 404 ); - $questQuery = ' - SELECT - qt.RewardTitle AS ARRAY_KEY, - qt.AllowableRaces, - IFNULL(ge.eventEntry, 0) AS eventEntry - FROM - quest_template qt - LEFT JOIN - game_event_seasonal_questrelation sq ON sq.questId = qt.ID - LEFT JOIN - game_event ge ON ge.eventEntry = sq.eventEntry - WHERE - qt.RewardTitle <> 0'; - - DB::Aowow()->query('REPLACE INTO ?_titles SELECT id, 0, 0, 0, 0, 0, 0, 0, bitIdx, male_loc0, male_loc2, male_loc3, male_loc4, male_loc6, male_loc8, female_loc0, female_loc2, female_loc3, female_loc4, female_loc6, female_loc8 FROM dbc_chartitles'); - - // hide unused titles - DB::Aowow()->query('UPDATE ?_titles SET cuFlags = ?d WHERE id BETWEEN 85 AND 123 AND id NOT IN (113, 120, 121, 122)', CUSTOM_EXCLUDE_FOR_LISTVIEW); - - // set expansion - DB::Aowow()->query('UPDATE ?_titles SET expansion = 2 WHERE id >= 72 AND id <> 80'); - DB::Aowow()->query('UPDATE ?_titles SET expansion = 1 WHERE id >= 42 AND id <> 46 AND expansion = 0'); - - // set category - DB::Aowow()->query('UPDATE ?_titles SET category = 1 WHERE id <= 28 OR id IN (42, 43, 44, 45, 47, 48, 62, 71, 72, 80, 82, 126, 127, 128, 157, 163, 167, 169, 177)'); - DB::Aowow()->query('UPDATE ?_titles SET category = 5 WHERE id BETWEEN 96 AND 109 OR id IN (83, 84)'); - DB::Aowow()->query('UPDATE ?_titles SET category = 2 WHERE id BETWEEN 144 AND 156 OR id IN (63, 77, 79, 113, 123, 130, 131, 132, 176)'); - DB::Aowow()->query('UPDATE ?_titles SET category = 6 WHERE id IN (46, 74, 75, 76, 124, 133, 134, 135, 137, 138, 155, 168)'); - DB::Aowow()->query('UPDATE ?_titles SET category = 4 WHERE id IN (81, 125)'); - DB::Aowow()->query('UPDATE ?_titles SET category = 3 WHERE id IN (53, 64, 120, 121, 122, 129, 139, 140, 141, 142) OR (id >= 158 AND category = 0)'); - - // update event - if ($assoc = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($titleHoliday))) - foreach ($titleHoliday as $tId => $hId) - if (!empty($assoc[$hId])) - DB::Aowow()->query('UPDATE ?_titles SET eventId = ?d WHERE id = ?d', $assoc[$hId], $tId); - - // update side - $questInfo = DB::World()->select($questQuery); - $sideUpd = DB::World()->selectCol('SELECT IF(TitleA, TitleA, TitleH) AS ARRAY_KEY, BIT_OR(IF(TitleA, 1, 2)) AS side FROM achievement_reward WHERE (TitleA <> 0 AND TitleH = 0) OR (TitleH <> 0 AND TitleA = 0) GROUP BY ARRAY_KEY HAVING side <> 3'); - foreach ($questInfo as $tId => $data) + public function generate(array $ids = []) : bool { - if ($data['eventEntry']) - DB::Aowow()->query('UPDATE ?_titles SET eventId = ?d WHERE id = ?d', $data['eventEntry'], $tId); + $questQuery = ' + SELECT + qt.RewardTitle AS ARRAY_KEY, + qt.AllowableRaces, + IFNULL(ge.eventEntry, 0) AS eventEntry + FROM + quest_template qt + LEFT JOIN + game_event_seasonal_questrelation sq ON sq.questId = qt.ID + LEFT JOIN + game_event ge ON ge.eventEntry = sq.eventEntry + WHERE + qt.RewardTitle <> 0'; - $side = Game::sideByRaceMask($data['AllowableRaces']); - if ($side == 3) - continue; + DB::Aowow()->query('REPLACE INTO ?_titles SELECT id, 0, 0, 0, 0, 0, 0, 0, bitIdx, male_loc0, male_loc2, male_loc3, male_loc4, male_loc6, male_loc8, female_loc0, female_loc2, female_loc3, female_loc4, female_loc6, female_loc8 FROM dbc_chartitles'); - if (!isset($sideUpd[$tId])) - $sideUpd[$tId] = $side; - else - $sideUpd[$tId] |= $side; + // hide unused titles + DB::Aowow()->query('UPDATE ?_titles SET cuFlags = ?d WHERE id BETWEEN 85 AND 123 AND id NOT IN (113, 120, 121, 122)', CUSTOM_EXCLUDE_FOR_LISTVIEW); + + // set expansion + DB::Aowow()->query('UPDATE ?_titles SET expansion = 2 WHERE id >= 72 AND id <> 80'); + DB::Aowow()->query('UPDATE ?_titles SET expansion = 1 WHERE id >= 42 AND id <> 46 AND expansion = 0'); + + // set category + DB::Aowow()->query('UPDATE ?_titles SET category = 1 WHERE id <= 28 OR id IN (42, 43, 44, 45, 47, 48, 62, 71, 72, 80, 82, 126, 127, 128, 157, 163, 167, 169, 177)'); + DB::Aowow()->query('UPDATE ?_titles SET category = 5 WHERE id BETWEEN 96 AND 109 OR id IN (83, 84)'); + DB::Aowow()->query('UPDATE ?_titles SET category = 2 WHERE id BETWEEN 144 AND 156 OR id IN (63, 77, 79, 113, 123, 130, 131, 132, 176)'); + DB::Aowow()->query('UPDATE ?_titles SET category = 6 WHERE id IN (46, 74, 75, 76, 124, 133, 134, 135, 137, 138, 155, 168)'); + DB::Aowow()->query('UPDATE ?_titles SET category = 4 WHERE id IN (81, 125)'); + DB::Aowow()->query('UPDATE ?_titles SET category = 3 WHERE id IN (53, 64, 120, 121, 122, 129, 139, 140, 141, 142) OR (id >= 158 AND category = 0)'); + + // update event + if ($assoc = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($this->titleHoliday))) + foreach ($this->titleHoliday as $tId => $hId) + if (!empty($assoc[$hId])) + DB::Aowow()->query('UPDATE ?_titles SET eventId = ?d WHERE id = ?d', $assoc[$hId], $tId); + + // update side + $questInfo = DB::World()->select($questQuery); + $sideUpd = DB::World()->selectCol('SELECT IF(TitleA, TitleA, TitleH) AS ARRAY_KEY, BIT_OR(IF(TitleA, 1, 2)) AS side FROM achievement_reward WHERE (TitleA <> 0 AND TitleH = 0) OR (TitleH <> 0 AND TitleA = 0) GROUP BY ARRAY_KEY HAVING side <> 3'); + foreach ($questInfo as $tId => $data) + { + if ($data['eventEntry']) + DB::Aowow()->query('UPDATE ?_titles SET eventId = ?d WHERE id = ?d', $data['eventEntry'], $tId); + + $side = Game::sideByRaceMask($data['AllowableRaces']); + if ($side == 3) + continue; + + if (!isset($sideUpd[$tId])) + $sideUpd[$tId] = $side; + else + $sideUpd[$tId] |= $side; + } + foreach ($sideUpd as $tId => $side) + if ($side != 3) + DB::Aowow()->query("UPDATE ?_titles SET side = ?d WHERE id = ?d", $side, $tId); + + // update side - sourceless titles (maintain query order) + DB::Aowow()->query('UPDATE ?_titles SET side = 2 WHERE id <= 28 OR id IN (118, 119, 116, 117, 110, 127)'); + DB::Aowow()->query('UPDATE ?_titles SET side = 1 WHERE id <= 14 OR id IN (111, 115, 112, 114, 126)'); + + return true; } - foreach ($sideUpd as $tId => $side) - if ($side != 3) - DB::Aowow()->query("UPDATE ?_titles SET side = ?d WHERE id = ?d", $side, $tId); - - // update side - sourceless titles (maintain query order) - DB::Aowow()->query('UPDATE ?_titles SET side = 2 WHERE id <= 28 OR id IN (118, 119, 116, 117, 110, 127)'); - DB::Aowow()->query('UPDATE ?_titles SET side = 1 WHERE id <= 14 OR id IN (111, 115, 112, 114, 126)'); - - return true; -} +}); ?> diff --git a/setup/tools/sqlgen/totemcategory.func.php b/setup/tools/sqlgen/totemcategory.func.php new file mode 100644 index 00000000..edb30f51 --- /dev/null +++ b/setup/tools/sqlgen/totemcategory.func.php @@ -0,0 +1,18 @@ + diff --git a/setup/tools/sqlgen/zones.func.php b/setup/tools/sqlgen/zones.func.php index f044fb6c..d51f1ec9 100644 --- a/setup/tools/sqlgen/zones.func.php +++ b/setup/tools/sqlgen/zones.func.php @@ -7,227 +7,232 @@ if (!CLI) die('not in cli mode'); -/* deps - * access_requirement -*/ - -$customData = array( - 2257 => ['cuFlags' => 0, 'category' => 0, 'type' => 1], // deeprun tram => type: transit - 3698 => ['expansion' => 1], // arenas - 3702 => ['expansion' => 1], - 3968 => ['expansion' => 1], - 4378 => ['expansion' => 2], - 4406 => ['expansion' => 2], - 2597 => ['maxPlayer' => 40], // is 5 in battlemasterlist ... dafuque? - 4710 => ['maxPlayer' => 40], - 3456 => ['parentAreaId' => 65, 'parentX' => 87.3, 'parentY' => 51.1], // has no coordinates set in map.dbc - 3849 => ['parentAreaId' => 3523, 'parentX' => 70.5, 'parentY' => 69.6], - 3847 => ['parentAreaId' => 3523, 'parentX' => 71.7, 'parentY' => 55.1], - 3848 => ['parentAreaId' => 3523, 'parentX' => 74.3, 'parentY' => 57.8], - 3845 => ['parentAreaId' => 3523, 'parentX' => 73.5, 'parentY' => 63.7] -); -$reqDBC = ['worldmaptransforms', 'worldmaparea', 'map', 'mapdifficulty', 'areatable', 'lfgdungeons', 'battlemasterlist']; - -function zones() +SqlGen::register(new class extends SetupScript { - // base query - DB::Aowow()->query(' - REPLACE INTO ?_zones - SELECT - a.id, - IFNULL(wmt.targetMapId, a.mapId), -- map - a.mapId, -- mapBak - a.areaTable, -- parentArea - IFNULL(wmt.targetMapId, -- g_zone_categories - IF(m.areaType = 1, 2, - IF(m.areaType = 2, 3, - IF(m.areaType = 4, 9, - IF(m.isBG = 1, 6, - IF(a.mapId = 571, 10, - IF(a.mapId = 530, 8, a.mapId))))))), - a.flags, - IF(areaTable <> 0 OR -- cuFlags - (wma.id IS NULL AND pa.areaId IS NULL AND (flags & 0x11000) = 0), ?d, 0), - IF(a.flags & 0x01000000, 5, -- g_zone_territories - IF(m.isBG = 1, 4, - IF(m.areaType = 4, 4, - IF(a.flags & 0x00000800, 3, - IF(a.factionGroupMask = 6, 2, - IF(a.factionGroupMask > 0, LOG2(a.factionGroupMask) - 1, 2)))))), - m.expansion, - IF(m.areaType = 0, 0, -- g_zone_instancetypes - IF(m.isBG = 1, 4, - IF(m.areaType = 4, 6, - IF(md.modeMask & 0xC, 8, - IF(md.minPl = 10 AND md.maxPL = 25, 7, - IF(m.areaType = 2, 3, - IF(m.areaType = 1 AND md.modeMask & 0x2, 5, 2))))))), - IF (md.minPl = 10 AND md.maxPl = 25, -2, - IFNULL(bm.maxPlayers, IFNULL(md.maxPl, m.maxPlayers))), - 0, -- itemLevelN - 0, -- itemLevelH - 0, -- levelReq - IFNULL(lfgIni.levelLFG, 0), -- levelReqLFG - 0, -- levelHeroic - IF(a.flags & 0x8, 1, -- levelMin - IFNULL(bm.minLevel, - IFNULL(lfgIni.levelMin, - IFNULL(lfgOpen.levelMin, 0)))), - IF(a.flags & 0x8, ?d, -- levelMax - IFNULL(bm.maxLevel, - IFNULL(lfgIni.levelMax, - IFNULL(lfgOpen.levelMax, 0)))), - "", -- attunements - "", -- heroic attunements - IFNULL(pa.areaId, 0), - IFNULL(pa.posX, 0), - IFNULL(pa.posY, 0), - IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc0, m.name_loc0), - IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc2, m.name_loc2), - IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc3, m.name_loc3), - IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc4, m.name_loc4), - IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc6, m.name_loc6), - IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc8, m.name_loc8) - FROM - dbc_areatable a - JOIN - dbc_map m ON a.mapId = m.id - LEFT JOIN ( - SELECT mapId, BIT_OR(1 << difficulty) AS modeMask, MIN(nPlayer) AS minPl, MAX(nPlayer) AS maxPl FROM dbc_mapdifficulty GROUP BY mapId - ) md ON md.mapId = a.mapId - LEFT JOIN - dbc_lfgdungeons lfgOpen ON a.mapId IN (0, 1, 530, 571) AND a.name_loc0 LIKE CONCAT("%", lfgOpen.name_loc0) AND lfgOpen.type = 4 - LEFT JOIN ( - SELECT - mapId, m.id, `left`, `right`, `top`, `bottom`, - IF((abs(((m.parentY - `right`) * 100 / (`left` - `right`)) - 50)) > abs(((m.parentX - `bottom`) * 100 / (`top` - `bottom`)) - 50), - (abs(((m.parentY - `right`) * 100 / (`left` - `right`)) - 50)), - (abs(((m.parentX - `bottom`) * 100 / (`top` - `bottom`)) - 50))) AS diff, - areaId, -- parentArea - 100 - ROUND((m.parentY - `right`) * 100 / (`left` - `right`), 1) as posX, - 100 - ROUND((m.parentX - `bottom`) * 100 / (`top` - `bottom`), 1) as posY - FROM - dbc_worldmaparea wma - JOIN - dbc_map m ON m.parentMapId = wma.mapid - WHERE - m.parentMapId IN (0, 1, 530, 571) AND areaId <> 0 AND - m.parentY BETWEEN `right` AND `left` AND - m.parentX BETWEEN bottom AND top - ORDER BY - diff ASC - ) pa ON pa.id = m.id AND m.parentMapId > -1 AND m.parentX <> 0 AND m.parentY <> 0 AND m.parentMapId = pa.mapId AND m.parentY BETWEEN pa.`right` AND pa.`left` AND m.parentX BETWEEN pa.bottom AND pa.top - LEFT JOIN ( - SELECT - mapId, - MIN(IF(targetLevelMin, targetLevelMin, levelMin)) AS levelMin, - MAX(IF(targetLevelMax, targetLevelMax, targetLevel)) AS levelMax, - MIN(IF(levelMin, levelMin, targetLevel)) AS levelLFG - FROM - dbc_lfgdungeons - WHERE - type NOT IN (4, 6) AND - groupId <> 11 - GROUP BY - mapId - ) lfgIni ON lfgIni.mapId = a.mapId - LEFT JOIN - dbc_battlemasterlist bm ON bm.mapId = a.mapId AND bm.moreMapId < 0 - LEFT JOIN - dbc_worldmaparea wma ON wma.areaId = a.id - LEFT JOIN - dbc_worldmaptransforms wmt ON - wmt.targetMapId <> wmt.sourceMapId AND - wma.mapId = wmt.sourceMapId AND - wma.left < wmt.maxY AND - wma.right > wmt.minY AND - wma.top < wmt.maxX AND - wma.bottom > wmt.minX - GROUP BY - a.id - ', CUSTOM_EXCLUDE_FOR_LISTVIEW, MAX_LEVEL); + use TrCustomData; - // get requirements from world.access_requirement - $zoneReq = DB::World()->select(' - SELECT - mapId AS ARRAY_KEY, - MIN(level_min) AS reqLevel, - MAX(IF(difficulty > 0, level_min, 0)) AS heroicLevel, - MAX(IF(difficulty = 0, item_level, 0)) AS reqItemLevelN, - MAX(IF(difficulty > 0, item_level, 0)) AS reqItemLevelH, - CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND item, item, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty = 0 AND item2 AND item2 <> item, item2, NULL) SEPARATOR " ")) AS reqItemN, - CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND item, item, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty > 0 AND item2 AND item2 <> item, item2, NULL) SEPARATOR " ")) AS reqItemH, - CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND quest_done_A, quest_done_A, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty = 0 AND quest_done_H AND quest_done_H <> quest_done_A, quest_done_H, NULL) SEPARATOR " ")) AS reqQuestN, - CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND quest_done_A, quest_done_A, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty > 0 AND quest_done_H AND quest_done_H <> quest_done_A, quest_done_H, NULL) SEPARATOR " ")) AS reqQuestH, - CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND completed_achievement, completed_achievement, NULL) SEPARATOR " ")) AS reqAchievementN, - CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND completed_achievement, completed_achievement, NULL) SEPARATOR " ")) AS reqAchievementH - FROM - access_requirement - GROUP BY - mapId - '); + protected $command = 'zones'; - foreach ($zoneReq as $mapId => $req) + protected $tblDependancyTC = ['access_requirement']; + protected $dbcSourceFiles = ['worldmaptransforms', 'worldmaparea', 'map', 'mapdifficulty', 'areatable', 'lfgdungeons', 'battlemasterlist']; + + private $customData = array( + 2257 => ['cuFlags' => 0, 'category' => 0, 'type' => 1], // deeprun tram => type: transit + 3698 => ['expansion' => 1], // arenas + 3702 => ['expansion' => 1], + 3968 => ['expansion' => 1], + 4378 => ['expansion' => 2], + 4406 => ['expansion' => 2], + 2597 => ['maxPlayer' => 40], // is 5 in battlemasterlist ... dafuq? + 4710 => ['maxPlayer' => 40], + 3456 => ['parentAreaId' => 65, 'parentX' => 87.3, 'parentY' => 51.1], // has no coordinates set in map.dbc + 3849 => ['parentAreaId' => 3523, 'parentX' => 70.5, 'parentY' => 69.6], + 3847 => ['parentAreaId' => 3523, 'parentX' => 71.7, 'parentY' => 55.1], + 3848 => ['parentAreaId' => 3523, 'parentX' => 74.3, 'parentY' => 57.8], + 3845 => ['parentAreaId' => 3523, 'parentX' => 73.5, 'parentY' => 63.7] + ); + + public function generate(array $ids = []) : bool { - $update = ['levelReq' => $req['reqLevel']]; - $aN = $aH = []; + // base query + DB::Aowow()->query(' + REPLACE INTO ?_zones + SELECT + a.id, + IFNULL(wmt.targetMapId, a.mapId), -- map + a.mapId, -- mapBak + a.areaTable, -- parentArea + IFNULL(wmt.targetMapId, -- g_zone_categories + IF(m.areaType = 1, 2, + IF(m.areaType = 2, 3, + IF(m.areaType = 4, 9, + IF(m.isBG = 1, 6, + IF(a.mapId = 571, 10, + IF(a.mapId = 530, 8, a.mapId))))))), + a.flags, + IF(areaTable <> 0 OR -- cuFlags + (wma.id IS NULL AND pa.areaId IS NULL AND (flags & 0x11000) = 0), ?d, 0), + IF(a.flags & 0x01000000, 5, -- g_zone_territories + IF(m.isBG = 1, 4, + IF(m.areaType = 4, 4, + IF(a.flags & 0x00000800, 3, + IF(a.factionGroupMask = 6, 2, + IF(a.factionGroupMask > 0, LOG2(a.factionGroupMask) - 1, 2)))))), + m.expansion, + IF(m.areaType = 0, 0, -- g_zone_instancetypes + IF(m.isBG = 1, 4, + IF(m.areaType = 4, 6, + IF(md.modeMask & 0xC, 8, + IF(md.minPl = 10 AND md.maxPL = 25, 7, + IF(m.areaType = 2, 3, + IF(m.areaType = 1 AND md.modeMask & 0x2, 5, 2))))))), + IF (md.minPl = 10 AND md.maxPl = 25, -2, + IFNULL(bm.maxPlayers, IFNULL(md.maxPl, m.maxPlayers))), + 0, -- itemLevelN + 0, -- itemLevelH + 0, -- levelReq + IFNULL(lfgIni.levelLFG, 0), -- levelReqLFG + 0, -- levelHeroic + IF(a.flags & 0x8, 1, -- levelMin + IFNULL(bm.minLevel, + IFNULL(lfgIni.levelMin, + IFNULL(lfgOpen.levelMin, 0)))), + IF(a.flags & 0x8, ?d, -- levelMax + IFNULL(bm.maxLevel, + IFNULL(lfgIni.levelMax, + IFNULL(lfgOpen.levelMax, 0)))), + "", -- attunements + "", -- heroic attunements + IFNULL(pa.areaId, 0), + IFNULL(pa.posX, 0), + IFNULL(pa.posY, 0), + IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc0, m.name_loc0), + IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc2, m.name_loc2), + IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc3, m.name_loc3), + IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc4, m.name_loc4), + IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc6, m.name_loc6), + IF(wma.id IS NULL OR m.areaType = 0 OR a.mapId IN (269, 560) OR a.areaTable, a.name_loc8, m.name_loc8) + FROM + dbc_areatable a + JOIN + dbc_map m ON a.mapId = m.id + LEFT JOIN ( + SELECT mapId, BIT_OR(1 << difficulty) AS modeMask, MIN(nPlayer) AS minPl, MAX(nPlayer) AS maxPl FROM dbc_mapdifficulty GROUP BY mapId + ) md ON md.mapId = a.mapId + LEFT JOIN + dbc_lfgdungeons lfgOpen ON a.mapId IN (0, 1, 530, 571) AND a.name_loc0 LIKE CONCAT("%", lfgOpen.name_loc0) AND lfgOpen.type = 4 + LEFT JOIN ( + SELECT + mapId, m.id, `left`, `right`, `top`, `bottom`, + IF((abs(((m.parentY - `right`) * 100 / (`left` - `right`)) - 50)) > abs(((m.parentX - `bottom`) * 100 / (`top` - `bottom`)) - 50), + (abs(((m.parentY - `right`) * 100 / (`left` - `right`)) - 50)), + (abs(((m.parentX - `bottom`) * 100 / (`top` - `bottom`)) - 50))) AS diff, + areaId, -- parentArea + 100 - ROUND((m.parentY - `right`) * 100 / (`left` - `right`), 1) as posX, + 100 - ROUND((m.parentX - `bottom`) * 100 / (`top` - `bottom`), 1) as posY + FROM + dbc_worldmaparea wma + JOIN + dbc_map m ON m.parentMapId = wma.mapid + WHERE + m.parentMapId IN (0, 1, 530, 571) AND areaId <> 0 AND + m.parentY BETWEEN `right` AND `left` AND + m.parentX BETWEEN bottom AND top + ORDER BY + diff ASC + ) pa ON pa.id = m.id AND m.parentMapId > -1 AND m.parentX <> 0 AND m.parentY <> 0 AND m.parentMapId = pa.mapId AND m.parentY BETWEEN pa.`right` AND pa.`left` AND m.parentX BETWEEN pa.bottom AND pa.top + LEFT JOIN ( + SELECT + mapId, + MIN(IF(targetLevelMin, targetLevelMin, levelMin)) AS levelMin, + MAX(IF(targetLevelMax, targetLevelMax, targetLevel)) AS levelMax, + MIN(IF(levelMin, levelMin, targetLevel)) AS levelLFG + FROM + dbc_lfgdungeons + WHERE + type NOT IN (4, 6) AND + groupId <> 11 + GROUP BY + mapId + ) lfgIni ON lfgIni.mapId = a.mapId + LEFT JOIN + dbc_battlemasterlist bm ON bm.mapId = a.mapId AND bm.moreMapId < 0 + LEFT JOIN + dbc_worldmaparea wma ON wma.areaId = a.id + LEFT JOIN + dbc_worldmaptransforms wmt ON + wmt.targetMapId <> wmt.sourceMapId AND + wma.mapId = wmt.sourceMapId AND + wma.left < wmt.maxY AND + wma.right > wmt.minY AND + wma.top < wmt.maxX AND + wma.bottom > wmt.minX + GROUP BY + a.id + ', CUSTOM_EXCLUDE_FOR_LISTVIEW, MAX_LEVEL); - if ($req['heroicLevel']) - $update['levelHeroic'] = $req['heroicLevel']; + // get requirements from world.access_requirement + $zoneReq = DB::World()->select(' + SELECT + mapId AS ARRAY_KEY, + MIN(level_min) AS reqLevel, + MAX(IF(difficulty > 0, level_min, 0)) AS heroicLevel, + MAX(IF(difficulty = 0, item_level, 0)) AS reqItemLevelN, + MAX(IF(difficulty > 0, item_level, 0)) AS reqItemLevelH, + CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND item, item, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty = 0 AND item2 AND item2 <> item, item2, NULL) SEPARATOR " ")) AS reqItemN, + CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND item, item, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty > 0 AND item2 AND item2 <> item, item2, NULL) SEPARATOR " ")) AS reqItemH, + CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND quest_done_A, quest_done_A, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty = 0 AND quest_done_H AND quest_done_H <> quest_done_A, quest_done_H, NULL) SEPARATOR " ")) AS reqQuestN, + CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND quest_done_A, quest_done_A, NULL) SEPARATOR " "), GROUP_CONCAT(IF(difficulty > 0 AND quest_done_H AND quest_done_H <> quest_done_A, quest_done_H, NULL) SEPARATOR " ")) AS reqQuestH, + CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty = 0 AND completed_achievement, completed_achievement, NULL) SEPARATOR " ")) AS reqAchievementN, + CONCAT_WS(" ", GROUP_CONCAT(IF(difficulty > 0 AND completed_achievement, completed_achievement, NULL) SEPARATOR " ")) AS reqAchievementH + FROM + access_requirement + GROUP BY + mapId + '); - if ($req['reqItemLevelN']) - $update['itemLevelReqN'] = $req['reqItemLevelN']; - - if ($req['reqItemLevelH'] && $req['reqItemLevelH'] > $req['reqItemLevelN']) - $update['itemLevelReqH'] = $req['reqItemLevelH']; - - if ($req['reqItemN'] && ($entries = explode(' ', $req['reqItemN']))) - foreach ($entries as $_) - $aN[TYPE_ITEM][] = $_; - - if ($req['reqItemH'] && ($entries = explode(' ', $req['reqItemH']))) - if ($entries = array_diff($entries, @(array)$aN[TYPE_ITEM])) - foreach ($entries as $_) - $aH[TYPE_ITEM][] = $_; - - if ($req['reqQuestN'] && ($entries = explode(' ', $req['reqQuestN']))) - foreach ($entries as $_) - $aN[TYPE_QUEST][] = $_; - - if ($req['reqQuestH'] && ($entries = explode(' ', $req['reqQuestH']))) - if ($entries = array_diff($entries, @(array)$aN[TYPE_QUEST])) - foreach ($entries as $_) - $aH[TYPE_QUEST][] = $_; - - if ($req['reqAchievementN'] && ($entries = explode(' ', $req['reqAchievementN']))) - foreach ($entries as $_) - $aN[TYPE_ACHIEVEMENT][] = $_; - - if ($req['reqAchievementH'] && ($entries = explode(' ', $req['reqAchievementH']))) - if ($entries = array_diff($entries, @(array)$aN[TYPE_ACHIEVEMENT])) - foreach ($entries as $_) - $aH[TYPE_ACHIEVEMENT][] = $_; - - if ($aN) + foreach ($zoneReq as $mapId => $req) { - foreach ($aN as $type => $entries) - $aN[$type] = $type.':'.implode(' '.$type.':', $entries); + $update = ['levelReq' => $req['reqLevel']]; + $aN = $aH = []; - $update['attunementsN'] = implode(' ', $aN); + if ($req['heroicLevel']) + $update['levelHeroic'] = $req['heroicLevel']; + + if ($req['reqItemLevelN']) + $update['itemLevelReqN'] = $req['reqItemLevelN']; + + if ($req['reqItemLevelH'] && $req['reqItemLevelH'] > $req['reqItemLevelN']) + $update['itemLevelReqH'] = $req['reqItemLevelH']; + + if ($req['reqItemN'] && ($entries = explode(' ', $req['reqItemN']))) + foreach ($entries as $_) + $aN[TYPE_ITEM][] = $_; + + if ($req['reqItemH'] && ($entries = explode(' ', $req['reqItemH']))) + if ($entries = array_diff($entries, @(array)$aN[TYPE_ITEM])) + foreach ($entries as $_) + $aH[TYPE_ITEM][] = $_; + + if ($req['reqQuestN'] && ($entries = explode(' ', $req['reqQuestN']))) + foreach ($entries as $_) + $aN[TYPE_QUEST][] = $_; + + if ($req['reqQuestH'] && ($entries = explode(' ', $req['reqQuestH']))) + if ($entries = array_diff($entries, @(array)$aN[TYPE_QUEST])) + foreach ($entries as $_) + $aH[TYPE_QUEST][] = $_; + + if ($req['reqAchievementN'] && ($entries = explode(' ', $req['reqAchievementN']))) + foreach ($entries as $_) + $aN[TYPE_ACHIEVEMENT][] = $_; + + if ($req['reqAchievementH'] && ($entries = explode(' ', $req['reqAchievementH']))) + if ($entries = array_diff($entries, @(array)$aN[TYPE_ACHIEVEMENT])) + foreach ($entries as $_) + $aH[TYPE_ACHIEVEMENT][] = $_; + + if ($aN) + { + foreach ($aN as $type => $entries) + $aN[$type] = $type.':'.implode(' '.$type.':', $entries); + + $update['attunementsN'] = implode(' ', $aN); + } + + if ($aH) + { + foreach ($aH as $type => $entries) + $aH[$type] = $type.':'.implode(' '.$type.':', $entries); + + $update['attunementsH'] = implode(' ', $aH); + } + + DB::Aowow()->query('UPDATE ?_zones SET ?a WHERE mapId = ?d', $update, $mapId); } - if ($aH) - { - foreach ($aH as $type => $entries) - $aH[$type] = $type.':'.implode(' '.$type.':', $entries); - - $update['attunementsH'] = implode(' ', $aH); - } - - DB::Aowow()->query('UPDATE ?_zones SET ?a WHERE mapId = ?d', $update, $mapId); + return true; } - - return true; -} +}); ?>