Setup/Scripts

* restructure setup to allow for self contained setup steps to self register (just the sql for now)
 * should ease adding new scripts in future
This commit is contained in:
Sarjuuk
2019-07-31 23:25:44 +02:00
parent 163e3d82b0
commit ccef11323b
51 changed files with 5345 additions and 4964 deletions

View File

@@ -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/CLISetup.class.php';
require_once 'setup/tools/setupScript.class.php';
require_once 'setup/tools/dbc.class.php'; require_once 'setup/tools/dbc.class.php';
require_once 'setup/tools/imagecreatefromblp.func.php'; require_once 'setup/tools/imagecreatefromblp.func.php';

View File

@@ -0,0 +1,76 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
trait TrDBCcopy
{
public function generate() : bool
{
if (!$this->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;
}
}
?>

View File

@@ -7,74 +7,14 @@ if (!CLI)
die('not in cli mode'); 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 class SqlGen
{ {
const MODE_NORMAL = 1; const MODE_NORMAL = 1;
const MODE_FIRSTRUN = 2; const MODE_FIRSTRUN = 2;
const MODE_UPDATE = 3; const MODE_UPDATE = 3;
private static $tables = array( // [dbcName, saveDbc, AowowDeps, TCDeps] private static $tables = [];
'achievementcategory' => ['achievement_category', false, null, null], private static $tmpStore = [];
'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']]
);
public static $cliOpts = []; public static $cliOpts = [];
private static $shortOpts = 'h'; private static $shortOpts = 'h';
@@ -84,13 +24,61 @@ class SqlGen
public static $subScripts = []; public static $subScripts = [];
public static $defaultExecTime = 30; 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'); self::$defaultExecTime = ini_get('max_execution_time');
$doScripts = null; $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) if (getopt(self::$shortOpts, self::$longOpts) || $mode == self::MODE_FIRSTRUN)
self::handleCLIOpts($doScripts); self::handleCLIOpts($doScripts);
else if ($mode != self::MODE_UPDATE) else if ($mode != self::MODE_UPDATE)
@@ -115,7 +103,50 @@ class SqlGen
self::$mode = $mode; 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 = []; $doTbls = [];
$_ = getopt(self::$shortOpts, self::$longOpts); $_ = getopt(self::$shortOpts, self::$longOpts);
@@ -130,13 +161,13 @@ class SqlGen
if (!empty($_['sync'])) if (!empty($_['sync']))
{ {
$sync = explode(',', $_['sync']); $sync = explode(',', $_['sync']);
foreach (self::$tables as $name => $info) foreach (self::$tables as $name => &$ssRef)
if (!empty($info[3]) && array_intersect($sync, $info[3])) if (array_intersect($sync, $ssRef->getDependancies(false)))
$doTbls[] = $name; $doTbls[] = $name;
// recursive dependencies // recursive dependencies
foreach (self::$tables as $name => $info) foreach (self::$tables as $name => &$ssRef)
if (!empty($info[2]) && array_intersect($doTbls, $info[2])) if (array_intersect($sync, $ssRef->getDependancies(true)))
$doTbls[] = $name; $doTbls[] = $name;
$doTbls = $doTbls ? array_unique($doTbls) : null; $doTbls = $doTbls ? array_unique($doTbls) : null;
@@ -145,17 +176,17 @@ class SqlGen
$doTbls = explode(',', $_['sql']); $doTbls = explode(',', $_['sql']);
} }
public static function printCLIHelp() public static function printCLIHelp() : void
{ {
echo "\nusage: php aowow --sql=<tableList,> [-h --help]\n\n"; echo "\nusage: php aowow --sql=<tableList,> [-h --help]\n\n";
echo "--sql : available tables:\n"; echo "--sql : available tables:\n";
foreach (self::$tables as $t => $info) foreach (self::$tables as $t => &$ssRef)
echo " * ".str_pad($t, 24).(isset($info[3]) ? ' - TC deps: '.implode(', ', $info[3]) : '').(isset($info[2]) ? ' - Aowow deps: '.implode(', ', $info[2]) : '')."\n"; 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"; 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])) if (!isset(self::$tables[$tableName]))
{ {
@@ -163,50 +194,28 @@ class SqlGen
return false; 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 if (method_exists($ssRef, 'applyCustomData'))
CLI::write('SqlGen::generate() - copying '.$tbl[0].'.dbc into aowow_'.$tableName); $ssRef->applyCustomData();
$dbc = new DBC($tbl[0], ['temporary' => CLISetup::$tmpDBC, 'tableName' => 'aowow_'.$tableName]); return true;
if ($dbc->error)
return false;
return !!$dbc->readFile();
} }
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; return self::$mode;
} }

View File

@@ -7,22 +7,21 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* dbc_achievement
* disables
*/
// Higher Learning - item rewarded through gossip
$customData = array(
1956 => ['itemExtra' => 44738]
);
$reqDBC = ['achievement_category', 'achievement', 'spellicon'];
function achievement(array $ids = [])
{ {
if ($ids) use TrCustomData;
DB::Aowow()->query('DELETE FROM ?_achievement WHERE id IN (?a)', $ids);
else 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(' DB::Aowow()->query('
REPLACE INTO REPLACE INTO
@@ -55,50 +54,51 @@ function achievement(array $ids = [])
dbc_spellicon si ON si.id = a.iconId dbc_spellicon si ON si.id = a.iconId
LEFT JOIN LEFT JOIN
?_icons i ON LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) = i.name ?_icons i ON LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) = i.name
'); { WHERE a.id IN (?a) }
} ', $ids ?: DBSIMPLE_SKIP);
// serverside achievements // 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)}', $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 $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']
); );
foreach ($serverAchievements as $sa)
if ($ids) 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, ?, ?, ?, ?, ?, ?)',
return true; $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']
// 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
); );
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;
}
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'achievementcategory';
protected $dbcSourceFiles = ['achievement_category'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'achievementcriteria';
protected $dbcSourceFiles = ['achievement_criteria'];
});
?>

View File

@@ -7,101 +7,96 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* areatrigger_tavern
* areatrigger_scripts
* areatrigger_involvedrelation
* quest_template
* quest_template_addon
* areatrigger_teleport
*/
$customData = array(
);
$reqDBC = ['areatrigger'];
function areatrigger(/*array $ids = [] */)
{ {
DB::Aowow()->query('TRUNCATE ?_areatrigger'); protected $command = 'areatrigger';
DB::Aowow()->query('INSERT INTO ?_areatrigger SELECT id, 0, 0, NULL, orientation, NULL, NULL, NULL, NULL, NULL, NULL FROM dbc_areatrigger');
/* notes: protected $tblDependancyTC = ['areatrigger_involvedrelation', 'areatrigger_scripts', 'areatrigger_tavern', 'areatrigger_teleport', 'quest_template', 'quest_template_addon'];
* while areatrigger DO have dimensions, displaying them on a map is almost always futile, protected $dbcSourceFiles = ['areatrigger'];
* as they are either too small to be noticable or larger than the map itself (looking at you, oculus dungeon exit)
*/
// 1: Taverns public function generate(array $ids = []) : bool
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)
{ {
// todo (low): unify with spawns function DB::Aowow()->query('TRUNCATE ?_areatrigger');
$queryPost = 'SELECT dm.id, wma.areaId, IFNULL(dm.floor, 0) AS floor, ' . DB::Aowow()->query('INSERT INTO ?_areatrigger SELECT id, 0, 0, NULL, orientation, NULL, NULL, NULL, NULL, NULL, NULL FROM dbc_areatrigger');
'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']); /* notes:
if (!$points) * while areatrigger DO have dimensions, displaying them on a map is almost always futile,
$points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 0, $ad['map']); * 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); // todo (low): unify with spawns function
DB::Aowow()->query('UPDATE ?_areatrigger SET `name` = ?, `type` = ?d WHERE id = ?d', $ad['name'], AT_TYPE_TELEPORT, $id); $queryPost = 'SELECT dm.id, wma.areaId, IFNULL(dm.floor, 0) AS floor, ' .
continue; '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( // 3: Quest Objectives
'name' => $ad['name'], CLI::write(' - satisfying quest objectives');
'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); $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;
}
?> ?>

View File

@@ -7,44 +7,52 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
// roles (1:heal; 2:mleDPS; 4:rngDPS; 8:tank) SqlGen::register(new class extends SetupScript
$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()
{ {
$classes = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_chrclasses'); use TrCustomData;
// add raceMask protected $command = 'classes';
$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 protected $dbcSourceFiles = ['spell', 'charbaseinfo', 'skillraceclassinfo', 'skilllineability', 'chrclasses'];
$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 // roles (1:heal; 2:mleDPS; 4:rngDPS; 8:tank)
foreach ($classes as $id => &$data) 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); $classes = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_chrclasses');
$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);
// 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;
}
?> ?>

View File

@@ -7,156 +7,152 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* creature_template
* creature_template_locale
* creature_classlevelstats
* instance_encounters
*/
$customData = array(
);
$reqDBC = ['creaturedisplayinfo', 'creaturedisplayinfoextra'];
function creature(array $ids = [])
{ {
$baseQuery = ' protected $command = 'creature';
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';
$dummyQuery = ' protected $tblDependancyTC = ['creature_template', 'creature_template_locale', 'creature_classlevelstats', 'instance_encounters'];
UPDATE protected $dbcSourceFiles = ['creaturedisplayinfo', 'creaturedisplayinfoextra'];
?_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';
$displayInfoQuery = ' public function generate(array $ids = []) : bool
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))
{ {
$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) $lastMax = 0;
DB::Aowow()->query('REPLACE INTO ?_creature VALUES (?a)', array_values($npc)); 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;
}
?> ?>

View File

@@ -7,82 +7,87 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* 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 = [])
{ {
if (!$ids) use TrCustomData;
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); protected $command = 'currencies';
// apply names & cap protected $tblDependancyAowow = ['icons'];
$moneyNames = DB::World()->select(' protected $tblDependancyTC = ['item_template', 'item_template_locale'];
SELECT protected $dbcSourceFiles = ['itemdisplayinfo', 'currencytypes'];
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) // 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])) if (!$ids)
$strings = $moneyNames[$itemId]; DB::Aowow()->query('REPLACE INTO ?_currencies (id, category, itemId) SELECT id, category, itemId FROM dbc_currencytypes');
else
$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); if (!empty($moneyNames[$itemId]))
$strings = ['name_loc0' => 'Item #'.$itemId.' not in DB', 'iconId' => 0, 'cuFlags' => CUSTOM_EXCLUDE_FOR_LISTVIEW, 'category' => 3]; $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;
}
?> ?>

View File

@@ -7,93 +7,96 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
);
$reqDBC = ['emotes', 'emotestext', 'emotestextdata'];
function emotes(/*array $ids = [] */)
{ {
/**********/ protected $command = 'emotes';
/* Basics */
/**********/
$globStrPath = CLISetup::$srcDir.'%sInterface/FrameXML/GlobalStrings.lua'; protected $dbcSourceFiles = ['emotes', 'emotestext', 'emotestextdata'];
$allOK = true;
$locPath = [];
DB::Aowow()->query('TRUNCATE ?_emotes_aliasses'); public function generate(array $ids = []) : bool
foreach (CLISetup::$localeIds as $lId)
{ {
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) foreach (CLISetup::$expectedPaths as $xp => $locId)
continue;
if ($xp) // if in subDir add trailing slash
$xp .= '/';
$path = sprintf($globStrPath, $xp);
if (CLISetup::fileExists($path))
{ {
$locPath[$lId] = $path; if ($lId != $locId)
continue 2; 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); return $allOK;
$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;
}
}
}
return $allOK;
}
?> ?>

View File

@@ -7,46 +7,43 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* game_event
* game_event_prerequisite
*/
$customData = array(
);
$reqDBC = array(
);
function events(array $ids = [])
{ {
$eventQuery = ' protected $command = 'events';
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';
$events = DB::World()->select($eventQuery, $ids ?: DBSIMPLE_SKIP); protected $tblDependancyTC = ['game_event', 'game_event_prerequisite'];
foreach ($events as $e) public function generate(array $ids = []) : bool
DB::Aowow()->query('REPLACE INTO ?_events VALUES (?a)', array_values($e)); {
$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;
}
});
?> ?>

View File

@@ -7,126 +7,134 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
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()
{ {
$factionQuery = ' use TrCustomData;
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';
$templateQuery = ' protected $command = 'factions';
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';
$recursiveUpdateQuery = ' protected $dbcSourceFiles = ['faction', 'factiontemplate'];
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 = ' private $customData = array(
UPDATE 47 => ['qmNpcIds' => '33310'],
?_factions x 68 => ['qmNpcIds' => '33555'],
JOIN 69 => ['qmNpcIds' => '33653'],
dbc_faction f ON f.id = x.id 72 => ['qmNpcIds' => '33307'],
LEFT JOIN 76 => ['qmNpcIds' => '33553'],
dbc_factiontemplate ft ON f.id = ft.factionId 81 => ['qmNpcIds' => '33556'],
SET 922 => ['qmNpcIds' => '16528'],
cuFlags = cuFlags | ?d 930 => ['qmNpcIds' => '33657'],
WHERE 932 => ['qmNpcIds' => '19321'],
f.repIdx < 0 OR 933 => ['qmNpcIds' => '20242 23007'],
( 935 => ['qmNpcIds' => '21432'],
f.repIdx > 0 AND 941 => ['qmNpcIds' => '20241'],
(f.repFlags1 & 0x8 OR ft.id IS NULL) AND 942 => ['qmNpcIds' => '17904'],
(f.repFlags1 & 0x80) = 0 946 => ['qmNpcIds' => '17657'],
)'; 947 => ['qmNpcIds' => '17585'],
970 => ['qmNpcIds' => '18382'],
$pairs = array( 978 => ['qmNpcIds' => '20240'],
[[980], ['expansion' => 1]], 989 => ['qmNpcIds' => '21643'],
[[1097], ['expansion' => 2]], 1011 => ['qmNpcIds' => '21655'],
[[469, 891, 1037], ['side' => 1]], 1012 => ['qmNpcIds' => '23159'],
[[ 67, 892, 1052], ['side' => 2]], 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); public function generate(array $ids = []) : bool
DB::Aowow()->query($templateQuery); {
DB::Aowow()->query($excludeQuery, CUSTOM_EXCLUDE_FOR_LISTVIEW); $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) $templateQuery = '
DB::Aowow()->query($recursiveUpdateQuery, $p[0], $p[1], $p[0]); 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;
}
});
?> ?>

View File

@@ -7,32 +7,35 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
);
$reqDBC = ['factiontemplate'];
function factiontemplate()
{ {
$query = ' protected $command = 'factiontemplate';
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); 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;
}
});
?> ?>

View File

@@ -6,15 +6,22 @@ if (!defined('AOWOW_REVISION'))
if (!CLI) if (!CLI)
die('not in cli mode'); 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;
}
});
?> ?>

View File

@@ -7,53 +7,62 @@ if (!CLI)
die('not in cli mode'); 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 = ' use TrCustomData;
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); 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;
}
});
?> ?>

View File

@@ -7,32 +7,35 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
);
$reqDBC = ['spellicon', 'itemdisplayinfo', 'creaturefamily'];
function icons()
{ {
DB::Aowow()->query('TRUNCATE ?_icons'); protected $command = 'icons';
DB::Aowow()->query('ALTER TABLE ?_icons AUTO_INCREMENT = 1');
$baseQuery = ' protected $dbcSourceFiles = ['spellicon', 'itemdisplayinfo', 'creaturefamily'];
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); 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;
}
});
?> ?>

View File

@@ -7,16 +7,6 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps:
* ?_items finalized
* ?_spell finalized
* dbc_spellitemenchantment
*/
$customData = array(
);
$reqDBC = ['spellitemenchantment'];
class ItemStatSetup extends ItemList class ItemStatSetup extends ItemList
{ {
private $statCols = []; 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'); protected $tblDependancyAowow = ['items', 'spell'];
$enchStats = enchantment_stats(); protected $dbcSourceFiles = ['spellitemenchantment'];
CLI::write(' '.count($enchStats).' enchantments parsed');
CLI::write(' - applying stats for items');
while (true) private function enchantment_stats() : array
{ {
$items = new ItemStatSetup($offset, SqlGen::$stepSize, $ids, $enchStats); $statCols = DB::Aowow()->selectCol('SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_NAME` LIKE "%item_stats"');
if ($items->error) $enchants = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_spellitemenchantment');
break; $spells = [];
$spellStats = [];
$max = max($items->getFoundIDs()); foreach ($enchants as $eId => $e)
$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++)
{ {
// trigger: onEquip + valid SpellId for ($i = 1; $i <=3; $i++)
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])
{ {
case 6: // TYPE_TOTEM +AmountX as DPS (Rockbiter) // trigger: onEquip + valid SpellId
$result[$eId]['dps'] = $val; // we do not use dps as itemMod, so apply it directly if ($e['object'.$i] > 0 && $e['type'.$i] == 3)
$obj = null; $spells[] = $e['object'.$i];
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; if ($spells)
break; $spellStats = (new SpellList(array(['id', $spells], CFG_SQL_LIMIT_NONE)))->getStatGain();
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 $result = [];
case 8: // TYPE_PRISMATIC_SOCKET Extra Sockets AmountX as socketCount (ignore) foreach ($enchants as $eId => $e)
$result[$eId]['nsockets'] = $val; // there is no itemmod for sockets, so apply it directly {
default: // TYPE_NONE dnd stuff; skip assignment below // parse stats
$obj = null; $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) $updateCols = ['type' => TYPE_ENCHANTMENT, 'typeId' => $eId];
if ($str = Game::$itemMods[$obj]) // check if we use these mods foreach ($result[$eId] as $k => $v)
Util::arraySumByKey($result[$eId], [$str => $val]); {
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]; return $result;
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; 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;
}
});
?> ?>

View File

@@ -7,31 +7,35 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
);
$reqDBC = ['spellitemenchantment'];
function itemenchantment()
{ {
$baseQuery = ' protected $command = 'itemenchantment';
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';
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'); public function generate(array $ids = []) : bool
foreach ($cuProcs as $id => $vals) {
DB::Aowow()->query('UPDATE ?_itemenchantment SET ?a WHERE id = ?d', $vals, $id); $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($baseQuery);
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; $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;
}
});
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'itemenchantmentcondition';
protected $dbcSourceFiles = ['spellitemenchantmentcondition'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'itemextendedcost';
protected $dbcSourceFiles = ['itemextendedcost'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'itemlimitcategory';
protected $dbcSourceFiles = ['itemlimitcategory'];
});
?>

View File

@@ -7,21 +7,24 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
);
$reqDBC = ['itemrandomsuffix', 'itemrandomproperties'];
function itemrandomenchant()
{ {
$query = ' protected $command = 'itemrandomenchant';
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); 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;
}
});
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'itemrandomproppoints';
protected $dbcSourceFiles = ['itemrandomproperties'];
});
?>

View File

@@ -7,252 +7,254 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* 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 = [])
{ {
$baseQuery = ' use TrCustomData;
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';
$lastMax = 0; protected $command = 'items';
while ($items = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$stepSize))
{
$newMax = max(array_column($items, 'entry'));
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) private $skill2cat = array(
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(
773 => 11, // inscription 773 => 11, // inscription
356 => 9, // fishing 356 => 9, // fishing
186 => 12, // mining 186 => 12, // mining
185 => 5, // cooking 185 => 5, // cooking
171 => 6 // alchemy 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 public function generate(array $ids = []) : bool
DB::Aowow()->query(' {
UPDATE $baseQuery = '
?_items i SELECT
JOIN it.entry,
dbc_durabilityquality dq ON dq.id = ((i.quality + 1) * 2) class, class as classBak,
JOIN subclass, subclass AS subClassBak,
dbc_durabilitycosts dc ON dc.id = i.itemLevel SoundOverrideSubclass,
SET IFNULL(sg.id, 0) AS subSubClass,
i.repairPrice = (durability* dq.mod * IF(i.classBak = 2, it.name, IFNULL(itl2.Name, ""), IFNULL(itl3.Name, ""), IFNULL(itl4.Name, ""), IFNULL(itl6.Name, ""), IFNULL(itl8.Name, ""),
CASE i.subClassBak 0 AS iconId,
WHEN 0 THEN w0 WHEN 1 THEN w1 WHEN 2 THEN w2 WHEN 3 THEN w3 WHEN 4 THEN w4 displayid,
WHEN 5 THEN w5 WHEN 6 THEN w6 WHEN 7 THEN w7 WHEN 8 THEN w8 WHEN 10 THEN w10 0 AS spellVisualId,
WHEN 11 THEN w11 WHEN 12 THEN w12 WHEN 13 THEN w13 WHEN 14 THEN w14 WHEN 15 THEN w15 Quality,
WHEN 16 THEN w16 WHEN 17 THEN w17 WHEN 18 THEN w18 WHEN 19 THEN w19 WHEN 20 THEN w20 Flags, FlagsExtra,
END, BuyCount, BuyPrice, SellPrice,
CASE i.subClassBak 0 AS repairPrice,
WHEN 1 THEN a1 WHEN 2 THEN a2 WHEN 3 THEN a3 WHEN 4 THEN a4 WHEN 6 THEN a6 InventoryType AS slot, InventoryType AS slotBak,
END AllowableClass, AllowableRace,
)) ItemLevel,
WHERE RequiredLevel,
durability > 0 AND ((classBak = 4 AND subClassBak IN (1, 2, 3, 4, 6)) OR (classBak = 2 AND subClassBak <> 9))'); 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;
}
});
?> ?>

View File

@@ -8,39 +8,35 @@ if (!CLI)
/* /*
note: the virtual set-ids wont match the ones of wowhead 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 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: SqlGen::register(new class extends SetupScript
* item_template
* game_event
*/
$customData = array(
221 => ['item1' => 7948, 'item2' => 7949, 'item3' => 7950, 'item4' => 7951, 'item5' => 7952, 'item6' => 7953]
);
$reqDBC = ['itemset'];
function itemset()
{ {
$setToHoliday = array ( use TrCustomData;
761 => 141, // Winterveil
762 => 372, // Brewfest protected $command = 'itemset';
785 => 341, // Midsummer
812 => 181, // Noblegarden 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 private $setToHoliday = array (
if ($pairs = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($setToHoliday))) 761 => 141, // Winterveil
foreach ($setToHoliday as &$hId) 762 => 372, // Brewfest
$hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0; 785 => 341, // Midsummer
812 => 181, // Noblegarden
);
// tags where refId == virtualId // tags where refId == virtualId
// in pve sets are not recycled beyond the contentGroup // in pve sets are not recycled beyond the contentGroup
$tagsById = array( private $tagsById = array(
// "Dungeon Set 1" // "Dungeon Set 1"
1 => [181, 182, 183, 184, 185, 186, 187, 188, 189], 1 => [181, 182, 183, 184, 185, 186, 187, 188, 189],
// "Dungeon Set 2" // "Dungeon Set 2"
@@ -88,7 +84,7 @@ function itemset()
); );
// well .. fuck // well .. fuck
$tagsByNamePart = array( private $tagsByNamePart = array(
17 => ['gladiator'], // "Arena Season 1 Set", 17 => ['gladiator'], // "Arena Season 1 Set",
19 => ['merciless'], // "Arena Season 2 Set", 19 => ['merciless'], // "Arena Season 2 Set",
20 => ['vengeful'], // "Arena Season 3 Set", 20 => ['vengeful'], // "Arena Season 3 Set",
@@ -99,272 +95,279 @@ function itemset()
30 => ['wrathful'] // "Arena Season 8 Set", 30 => ['wrathful'] // "Arena Season 8 Set",
); );
DB::Aowow()->query('TRUNCATE TABLE ?_itemset'); public function generate(array $ids = []) : bool
$vIdx = 0;
$virtualId = 0;
$sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset');
foreach ($sets as $setId => $setData)
{ {
$spells = $items = $mods = $descText = $name = $gains = []; // find events associated with holidayIds
$max = $reqLvl = $min = $quality = $heroic = $nPieces = []; if ($pairs = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($this->setToHoliday)))
$classMask = $type = 0; foreach ($this->setToHoliday as &$hId)
$hasRing = false; $hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0;
$holiday = isset($setToHoliday[$setId]) ? $setToHoliday[$setId] : 0; DB::Aowow()->query('TRUNCATE TABLE ?_itemset');
$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);
/****************************************/ $vIdx = 0;
/* determine type and reuse from pieces */ $virtualId = 0;
/****************************************/ $sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset');
foreach ($sets as $setId => $setData)
// make the first vId always same as setId
$firstPiece = reset($pieces);
$tmp = [$firstPiece['Quality'].$firstPiece['ItemLevel'] => $setId];
// walk through all items associated with the set
foreach ($pieces as $itemId => $piece)
{ {
$classMask |= ($piece['AllowableClass'] & CLASS_MASK_ALL); $spells = $items = $mods = $descText = $name = $gains = [];
$key = $piece['Quality'].str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT); $max = $reqLvl = $min = $quality = $heroic = $nPieces = [];
$classMask = $type = 0;
$hasRing = false;
if (!isset($tmp[$key])) $holiday = $this->setToHoliday[$setId] ?? 0;
$tmp[$key] = --$vIdx; $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) // make the first vId always same as setId
if ($piece['class'] != ITEM_CLASS_ARMOR || $piece['subclass'] == 0) $firstPiece = reset($pieces);
$canReuse = false; $tmp = [$firstPiece['Quality'].$firstPiece['ItemLevel'] => $setId];
/* gather relevant stats for use */ // walk through all items associated with the set
foreach ($pieces as $itemId => $piece)
if (!isset($quality[$vId]) || $piece['Quality'] > $quality[$vId])
$quality[$vId] = $piece['Quality'];
if ($piece['Flags'] & ITEM_FLAG_HEROIC)
$heroic[$vId] = true;
if (!isset($reqLvl[$vId]) || $piece['RequiredLevel'] > $reqLvl[$vId])
$reqLvl[$vId] = $piece['RequiredLevel'];
if (!isset($min[$vId]) || $piece['ItemLevel'] < $min[$vId])
$min[$vId] = $piece['ItemLevel'];
if (!isset($max[$vId]) || $piece['ItemLevel'] > $max[$vId])
$max[$vId] = $piece['ItemLevel'];
if (!isset($items[$vId][$piece['slot']]) || !$canReuse)
{ {
if (!isset($nPieces[$vId])) $classMask |= ($piece['AllowableClass'] & CLASS_MASK_ALL);
$nPieces[$vId] = 1; $key = $piece['Quality'].str_pad($piece['ItemLevel'], 3, 0, STR_PAD_LEFT);
else
$nPieces[$vId]++;
}
if (isset($items[$vId][$piece['slot']])) if (!isset($tmp[$key]))
{ $tmp[$key] = --$vIdx;
// not reusable -> insert anyway on unique keys
if (!$canReuse) $vId = $tmp[$key];
$items[$vId][$piece['slot'].$itemId] = $itemId;
else // 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 (!isset($nPieces[$vId]))
$nPieces[$vId] = 1;
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;
else else
$temp[$slot] = $item; $nPieces[$vId]++;
} }
}
$items = [$temp]; if (isset($items[$vId][$piece['slot']]))
$heroic = [reset($heroic)]; {
$nPieces = [count($temp)]; // not reusable -> insert anyway on unique keys
$quality = [reset($quality)]; if (!$canReuse)
$reqLvl = [reset($reqLvl)]; $items[$vId][$piece['slot'].$itemId] = $itemId;
$max = $max ? [max($max)] : [0]; else
$min = $min ? [min($min)] : [0]; {
} 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) if ($items[$vId][$piece['slot']] > $itemId)
$subsets = array_pad($subsets, 10, 0); $items[$vId][$piece['slot']] = $itemId;
}
}
else
$items[$vId][$piece['slot']] = $itemId;
/********************/ /* check for type */
/* calc statbonuses */
/********************/
for ($i = 1; $i < 9; $i++) // skip cloaks, they mess with armor classes
if ($setData['spellId'.$i] > 0 && $setData['itemCount'.$i] > 0) if ($piece['slot'] == 16)
$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. <!--rtg19-->14&nbsp;<small>(<!--rtg%19-->0.30%&nbsp;@&nbsp;L<!--lvl-->80)</small>
$descText[$loc] = preg_replace('/<!--rtg\d+-->(\d+)&nbsp.*?<\/small>/i', '\1', $descText[$loc]);
}
/****************************/
/* finalaize data and write */
/****************************/
foreach ($items as $vId => $vSet)
{
$note = 0;
foreach ($tagsById as $tag => $sets)
{
if (!in_array($setId, $sets))
continue; 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. <!--rtg19-->14&nbsp;<small>(<!--rtg%19-->0.30%&nbsp;@&nbsp;L<!--lvl-->80)</small>
$descText[$loc] = preg_replace('/<!--rtg\d+-->(\d+)&nbsp.*?<\/small>/i', '\1', $descText[$loc]);
}
/****************************/
/* finalaize data and write */
/****************************/
foreach ($items as $vId => $vSet)
{
$note = 0;
foreach ($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; if (isset($pieces[reset($vSet)]) && stripos($pieces[reset($vSet)]['name'], $str) === 0)
break 2; {
$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;
}
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'lock';
protected $dbcSourceFiles = ['lock'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'mailtemplate';
protected $dbcSourceFiles = ['mailtemplate'];
});
?>

View File

@@ -7,124 +7,121 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* gameobject_template
* gameobject_template_locale
* gameobject_questitem
*/
$customData = array(
);
$reqDBC = ['lock'];
function objects(array $ids = [])
{ {
$baseQuery = ' protected $command = 'objects';
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';
$updateQuery = ' protected $tblDependancyTC = ['gameobject_template', 'gameobject_template_locale', 'gameobject_questitem'];
UPDATE protected $dbcSourceFiles = ['lock'];
?_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 = 0; public function generate(array $ids = []) : bool
while ($objects = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$stepSize))
{ {
$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) CLI::write(' * sets '.($lastMax + 1).' - '.$newMax);
DB::Aowow()->query('REPLACE INTO ?_objects VALUES (?a)', array_values($o));
$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;
}
?> ?>

View File

@@ -7,121 +7,120 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* creature_template
* creature
*/
$customData = array(
);
$reqDBC = ['talent', 'spell', 'skilllineability', 'creaturefamily'];
function pet(array $ids = [])
{ {
$baseQuery = ' protected $command = 'pet';
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';
$spawnQuery = ' protected $tblDependancyAowow = ['icons'];
SELECT protected $tblDependancyTC = ['creature_template', 'creature'];
ct.family AS ARRAY_KEY, protected $dbcSourceFiles = ['talent', 'spell', 'skilllineability', 'creaturefamily'];
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 = ' public function generate(array $ids = []) : bool
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']])) $baseQuery = '
$res[$set['id']] = []; 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;
}
?> ?>

View File

@@ -7,266 +7,260 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* quest_template
* quest_template_addon
* quest_template_locale
* game_event
* game_event_seasonal_questrelation
* disables
*/
$customData = array(
);
$reqDBC = ['questxp', 'questfactionreward'];
function quests(array $ids = [])
{ {
$baseQuery = ' protected $command = 'quests';
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';
$xpQuery = ' protected $tblDependancyTC = ['quest_template', 'quest_template_addon', 'quest_template_locale', 'game_event', 'game_event_seasonal_questrelation', 'disables'];
UPDATE protected $dbcSourceFiles = ['questxp', 'questfactionreward'];
?_quests q,
dbc_questxp xp
SET
rewardXP = (CASE rewardXP
WHEN 0 THEN xp.Field1 WHEN 1 THEN xp.Field2 WHEN 2 THEN xp.Field3 WHEN 3 THEN xp.Field4 WHEN 4 THEN xp.Field5
WHEN 5 THEN xp.Field6 WHEN 6 THEN xp.Field7 WHEN 7 THEN xp.Field8 WHEN 8 THEN xp.Field9 WHEN 9 THEN xp.Field10
ELSE 0
END)
WHERE
xp.id = q.level { AND
q.id IN(?a)
}';
$repQuery = ' public function generate(array $ids = []) : bool
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))
{ {
$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;
}
?> ?>

View File

@@ -7,51 +7,42 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* 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 = [] */)
{ {
$query['creature'] = ' protected $command = 'quests_startend';
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'] = ' protected $tblDependancyTC = ['creature_queststarter', 'creature_questender', 'game_event_creature_quest', 'gameobject_queststarter', 'gameobject_questender', 'game_event_gameobject_quest', 'item_template'];
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'; public function generate(array $ids = []) : bool
// 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); $query['creature'] = '
foreach ($data as $d) SELECT 1 AS type, id AS typeId, quest AS questId, 1 AS method, 0 AS eventId FROM creature_queststarter UNION
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)); 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;
}
?> ?>

View File

@@ -7,45 +7,53 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
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()
{ {
/**********/ use TrCustomData;
/* Basics */
/**********/
$baseQuery = ' protected $command = 'races';
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); protected $dbcSourceFiles = ['chrraces', 'charbaseinfo'];
// add classMask private $customData = array(
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'); 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 public function generate(array $ids = []) : bool
DB::Aowow()->query('UPDATE ?_races SET cuFlags = ?d WHERE flags & ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW, 0x1); {
/**********/
/* 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;
}
});
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'scalingstatdistribution';
protected $dbcSourceFiles = ['scalingstatdistribution'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'scalingstatvalues';
protected $dbcSourceFiles = ['scalingstatvalues'];
});
?>

View File

@@ -7,22 +7,40 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
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()
{ {
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;
}
});
?> ?>

View File

@@ -6,71 +6,81 @@ if (!defined('AOWOW_REVISION'))
if (!CLI) if (!CLI)
die('not in cli mode'); 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 = ' use TrCustomData;
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';
DB::Aowow()->query($baseQuery); protected $command = 'skillline';
// categorization protected $tblDependancyAowow = ['icons'];
DB::Aowow()->query('UPDATE ?_skillline SET typeCat = -5 WHERE id = 777 OR (categoryId = 9 AND id NOT IN (356, 129, 185, 142, 155))'); protected $dbcSourceFiles = ['skillline', 'spell', 'skilllineability'];
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 private $customData = array(
DB::Aowow()->query('UPDATE ?_skillline SET name_loc8 = REPLACE(name_loc8, " - ", ": ") WHERE categoryId = 7 OR id IN (758, 788)'); 393 => ['professionMask' => 0x0000], // Skinning
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]); 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 public function generate(array $ids = []) : bool
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(' $baseQuery = '
UPDATE REPLACE INTO
?_skillline sl, ?_skillline
dbc_spell s, SELECT
dbc_skilllineability sla, 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, ""
?_icons ic, FROM
dbc_spellicon si dbc_skillline';
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; 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;
}
});
?> ?>

View File

@@ -7,421 +7,427 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
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 = [] */)
{ {
/* use TrCustomData;
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
*/
// WMOAreaTable.dbc/id => AreaTable.dbc/id protected $command = 'sounds';
$worldStateZoneSoundFix = array(
18153 => 2119, protected $dbcSourceFiles = array(
18154 => 2119, // base emotes race
47321 => 4273, // The Spark of Imagination 'soundentries', 'emotestextsound', 'vocaluisounds',
43600 => 4273, // The Celestial Planetarium // creatures
47478 => 4273 // The Prison of Yogg-Saron '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)
);
/***********/ public function generate(array $ids = []) : bool
/* 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))
{ {
$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, CLI::write(' * sets '.($lastMax + 1).' - '.$newMax);
because of different cases, path being attached to file and other shenanigans
build a usable path and create full index to compensate $lastMax = $newMax;
25.6k raw files => expect ~21k filtered files
*/
$fileSets = []; $groupSets = [];
$hasDupes = false; foreach ($sounds as $s)
for ($i = 1; $i < 11; $i++)
{ {
$nicePath = CLI::nicePath($s['soundFile'.$i], $s['path']); /* attention!
if ($s['soundFile'.$i] && array_key_exists($nicePath, $soundIndex))
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]; $nicePath = CLI::nicePath($s['soundFile'.$i], $s['path']);
$hasDupes = true; 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; continue;
} }
else if ($fileSets)
DB::Aowow()->query('INSERT INTO ?_sounds_files VALUES (?a)', array_values($fileSets));
// convert to something web friendly => ogg unset($s['path']);
if (stristr($s['soundFile'.$i], '.wav'))
{
$soundIndex[$nicePath] = ++$soundFileIdx;
$fileSets[] = array( $groupSets[] = array_values($s);
$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) DB::Aowow()->query('REPLACE INTO ?_sounds VALUES (?a)', array_values($groupSets));
{
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));
} /******************/
/* 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('TRUNCATE ?_emotes_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 ?_emotes_sounds SELECT emotesTextId, raceId, gender + 1, soundId FROM dbc_emotestextsound');
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
/***************/ /*******************/
/* Emote Sound */ /* Creature Sounds */
/***************/ /*******************/
CLI::write(' - linking to emotes'); CLI::write(' - linking to creatures');
DB::Aowow()->query('TRUNCATE ?_emotes_sounds'); // currently ommitting:
DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_sounds SELECT emotesTextId, raceId, gender + 1, soundId FROM dbc_emotestextsound'); // * 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: // issues: (probably because of 335-data)
// * footsteps (matrix of: creature + terrain + humidity) // * animate is probably wrong
// * fidget2 through 5 // * missile and impactarea not in js
// * customattack2 through 3 // * ready, castertargeting, casterstate and targetstate not in dbc
// 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('TRUNCATE ?_spell_sounds');
DB::Aowow()->query(' DB::Aowow()->query('
INSERT INTO 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`) ?_spell_sounds (`id`, `precast`, `cast`, `impact`, `state`, `statedone`, `channel`, `missile`, `animation`, `casterimpact`, `targetimpact`, `missiletargeting`, `instantarea`, `impactarea`, `persistentarea`)
SELECT SELECT
cdi.id, sv.id,
IFNULL(ns.greetSoundId, 0), IFNULL(svk1.soundId, 0),
IFNULL(ns.byeSoundId, 0), IFNULL(svk2.soundId, 0),
IFNULL(ns.angrySoundId, 0), IFNULL(svk3.soundId, 0),
IF(csdA.exertion, csdA.exertion, IFNULL(csdB.exertion, 0)), IFNULL(svk4.soundId, 0),
IF(csdA.exertionCritical, csdA.exertionCritical, IFNULL(csdB.exertionCritical, 0)), IFNULL(svk5.soundId, 0),
IF(csdA.injury, csdA.injury, IFNULL(csdB.injury, 0)), IFNULL(svk6.soundId, 0),
IF(csdA.injuryCritical, csdA.injuryCritical, IFNULL(csdB.injuryCritical, 0)), missileSoundId,
IF(csdA.death, csdA.death, IFNULL(csdB.death, 0)), animationSoundId,
IF(csdA.stun, csdA.stun, IFNULL(csdB.stun, 0)), IFNULL(svk7.soundId, 0),
IF(csdA.stand, csdA.stand, IFNULL(csdB.stand, 0)), IFNULL(svk8.soundId, 0),
IF(csdA.aggro, csdA.aggro, IFNULL(csdB.aggro, 0)), IFNULL(svk9.soundId, 0),
IF(csdA.wingFlap, csdA.wingFlap, IFNULL(csdB.wingFlap, 0)), IFNULL(svk10.soundId, 0),
IF(csdA.wingGlide, csdA.wingGlide, IFNULL(csdB.wingGlide, 0)), IFNULL(svk11.soundId, 0),
IF(csdA.alert, csdA.alert, IFNULL(csdB.alert, 0)), IFNULL(svk12.soundId, 0)
IF(csdA.fidget, csdA.fidget, IFNULL(csdB.fidget, 0)), FROM
IF(csdA.customAttack, csdA.customAttack, IFNULL(csdB.customAttack, 0)), dbc_spellvisual sv
IF(csdA.loop, csdA.loop, IFNULL(csdB.loop, 0)), LEFT JOIN
IF(csdA.jumpStart, csdA.jumpStart, IFNULL(csdB.jumpStart, 0)), dbc_spellvisualkit svk1 ON svk1.id = sv.precastKitId
IF(csdA.jumpEnd, csdA.jumpEnd, IFNULL(csdB.jumpEnd, 0)), LEFT JOIN
IF(csdA.petAttack, csdA.petAttack, IFNULL(csdB.petAttack, 0)), dbc_spellvisualkit svk2 ON svk2.id = sv.castKitId
IF(csdA.petOrder, csdA.petOrder, IFNULL(csdB.petOrder, 0)), LEFT JOIN
IF(csdA.petDismiss, csdA.petDismiss, IFNULL(csdB.petDismiss, 0)), dbc_spellvisualkit svk3 ON svk3.id = sv.impactKitId
IF(csdA.birth, csdA.birth, IFNULL(csdB.birth, 0)), LEFT JOIN
IF(csdA.spellcast, csdA.spellcast, IFNULL(csdB.spellcast, 0)), dbc_spellvisualkit svk4 ON svk4.id = sv.stateKitId
IF(csdA.submerge, csdA.submerge, IFNULL(csdB.submerge, 0)), LEFT JOIN
IF(csdA.submerged, csdA.submerged, IFNULL(csdB.submerged, 0)) dbc_spellvisualkit svk5 ON svk5.id = sv.statedoneKitId
FROM LEFT JOIN
dbc_creaturedisplayinfo cdi dbc_spellvisualkit svk6 ON svk6.id = sv.channelKitId
LEFT JOIN LEFT JOIN
dbc_creaturemodeldata cmd ON cmd.id = cdi.modelId dbc_spellvisualkit svk7 ON svk7.id = sv.casterImpactKitId
LEFT JOIN LEFT JOIN
dbc_creaturesounddata csdA ON cdi.creatureSoundId = csdA.id dbc_spellvisualkit svk8 ON svk8.id = sv.targetImpactKitId
LEFT JOIN LEFT JOIN
dbc_creaturesounddata csdB ON cmd.creatureSoundId = csdB.id dbc_spellvisualkit svk9 ON svk9.id = sv.missileTargetingKitId
LEFT JOIN LEFT JOIN
dbc_npcsounds ns ON cdi.npcSoundId = ns.id 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) // omiting data from WMOAreaTable, as its at the moment impossible to link to actual zones
// * animate is probably wrong
// * missile and impactarea not in js
// * ready, castertargeting, casterstate and targetstate not in dbc
DB::Aowow()->query('TRUNCATE ?_spell_sounds'); DB::Aowow()->query('TRUNCATE ?_zones_sounds');
DB::Aowow()->query(' DB::Aowow()->query('
INSERT INTO INSERT INTO
?_spell_sounds (`id`, `precast`, `cast`, `impact`, `state`, `statedone`, `channel`, `missile`, `animation`, `casterimpact`, `targetimpact`, `missiletargeting`, `instantarea`, `impactarea`, `persistentarea`) ?_zones_sounds (id, ambienceDay, ambienceNight, musicDay, musicNight, intro, worldStateId, worldStateValue)
SELECT SELECT
sv.id, a.id,
IFNULL(svk1.soundId, 0), IFNULL(sa1.soundIdDay, 0),
IFNULL(svk2.soundId, 0), IFNULL(sa1.soundIdNight, 0),
IFNULL(svk3.soundId, 0), IFNULL(zm1.soundIdDay, 0),
IFNULL(svk4.soundId, 0), IFNULL(zm1.soundIdNight, 0),
IFNULL(svk5.soundId, 0), IFNULL(zimt1.soundId, 0),
IFNULL(svk6.soundId, 0), 0,
missileSoundId, 0
animationSoundId, FROM
IFNULL(svk7.soundId, 0), dbc_areatable a
IFNULL(svk8.soundId, 0), LEFT JOIN
IFNULL(svk9.soundId, 0), dbc_soundambience sa1 ON sa1.id = a.soundAmbience
IFNULL(svk10.soundId, 0), LEFT JOIN
IFNULL(svk11.soundId, 0), dbc_zonemusic zm1 ON zm1.id = a.zoneMusic
IFNULL(svk12.soundId, 0) LEFT JOIN
FROM dbc_zoneintromusictable zimt1 ON zimt1.id = a.zoneIntroMusic
dbc_spellvisual sv WHERE
LEFT JOIN a.soundAmbience > 0 OR a.zoneMusic > 0 OR a.zoneIntroMusic
dbc_spellvisualkit svk1 ON svk1.id = sv.precastKitId UNION
LEFT JOIN SELECT
dbc_spellvisualkit svk2 ON svk2.id = sv.castKitId IF(wszs.areaId, wszs.areaId, wszs.wmoAreaId),
LEFT JOIN IFNULL(sa2.soundIdDay, 0),
dbc_spellvisualkit svk3 ON svk3.id = sv.impactKitId IFNULL(sa2.soundIdNight, 0),
LEFT JOIN IFNULL(zm2.soundIdDay, 0),
dbc_spellvisualkit svk4 ON svk4.id = sv.stateKitId IFNULL(zm2.soundIdNight, 0),
LEFT JOIN IFNULL(zimt2.soundId, 0),
dbc_spellvisualkit svk5 ON svk5.id = sv.statedoneKitId wszs.stateId,
LEFT JOIN wszs.value
dbc_spellvisualkit svk6 ON svk6.id = sv.channelKitId FROM
LEFT JOIN dbc_worldstatezonesounds wszs
dbc_spellvisualkit svk7 ON svk7.id = sv.casterImpactKitId LEFT JOIN
LEFT JOIN dbc_soundambience sa2 ON sa2.id = wszs.soundAmbienceId
dbc_spellvisualkit svk8 ON svk8.id = sv.targetImpactKitId LEFT JOIN
LEFT JOIN dbc_zonemusic zm2 ON zm2.id = wszs.zoneMusicId
dbc_spellvisualkit svk9 ON svk9.id = sv.missileTargetingKitId LEFT JOIN
LEFT JOIN dbc_zoneintromusictable zimt2 ON zimt2.id = wszs.zoneIntroMusicId
dbc_spellvisualkit svk10 ON svk10.id = sv.instantAreaKitId WHERE
LEFT JOIN wszs.zoneMusicId > 0 AND (wszs.areaId OR wszs.wmoAreaId IN (?a))
dbc_spellvisualkit svk11 ON svk11.id = sv.impactAreaKitId ', array_keys($worldStateZoneSoundFix));
LEFT JOIN
dbc_spellvisualkit svk12 ON svk12.id = sv.persistentAreaKitId // 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('TRUNCATE ?_items_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 $fields = ['hit', 'crit'];
foreach ($worldStateZoneSoundFix as $old => $new) foreach ($fields as $f)
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++)
{ {
DB::Aowow()->query(' for ($i = 1; $i <= 10; $i++)
INSERT INTO {
?_items_sounds DB::Aowow()->query('
SELECT INSERT INTO
?#, ?_items_sounds
(1 << wis.subClass) SELECT
FROM ?#,
dbc_weaponimpactsounds wis (1 << wis.subClass)
WHERE FROM
?# > 0 dbc_weaponimpactsounds wis
ON DUPLICATE KEY UPDATE WHERE
subClassMask = subClassMask | (1 << wis.subClass) ?# > 0
', $f.$i, $f.$i); 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;
}
?> ?>

File diff suppressed because it is too large Load Diff

View File

@@ -7,28 +7,60 @@ if (!CLI)
die('not in cli mode'); 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: SqlGen::register(new class extends SetupScript
* 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
{ {
$alphaMapCache = []; protected $command = 'spawns'; // and waypoints
$alphaMapCheck = function ($areaId, array &$set) use (&$alphaMapCache)
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'; $file = 'setup/generated/alphaMaps/'.$areaId.'.png';
if (!file_exists($file)) // file does not exist (probably instanced area) if (!file_exists($file)) // file does not exist (probably instanced area)
@@ -41,28 +73,28 @@ function spawns() // and waypoints
return true; return true;
} }
if (empty($alphaMapCache[$areaId])) if (empty($this->alphaMapCache[$areaId]))
$alphaMapCache[$areaId] = imagecreatefrompng($file); $this->alphaMapCache[$areaId] = imagecreatefrompng($file);
// alphaMaps are 1000 x 1000, adapt points [black => valid point] // 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; $set = null;
return true; return true;
}; }
$checkCoords = function ($points) use($alphaMapCheck) private function checkCoords(array $points) : array
{ {
$result = []; $result = [];
$capitals = array( // capitals take precedence over their surroundings $capitals = array( // capitals take precedence over their surroundings
1497, 1637, 1638, 3487, // Undercity, Ogrimmar, Thunder Bluff, Silvermoon City 1497, 1637, 1638, 3487, // Undercity, Ogrimmar, Thunder Bluff, Silvermoon City
1519, 1537, 1657, 3557, // Stormwind City, Ironforge, Darnassus, The Exodar 1519, 1537, 1657, 3557, // Stormwind City, Ironforge, Darnassus, The Exodar
3703, 4395 // Shattrath City, Dalaran 3703, 4395 // Shattrath City, Dalaran
); );
foreach ($points as $res) foreach ($points as $res)
{ {
if ($alphaMapCheck($res['areaId'], $res)) if ($this->alphaMapCheck($res['areaId'], $res))
{ {
if (!$res) if (!$res)
continue; continue;
@@ -74,9 +106,9 @@ function spawns() // and waypoints
if (empty($result) || $result[0] > $q) if (empty($result) || $result[0] > $q)
$result = [$q, $res]; $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; 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]; $result = [1.0, $res];
} }
@@ -88,198 +120,161 @@ function spawns() // and waypoints
} }
return $result[1]; 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` ' . public function generate(array $ids = []) : bool
'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)
{ {
CLI::write($q[1]); /*********************/
/* truncate old data */
/*********************/
$n = 0; DB::Aowow()->query('TRUNCATE TABLE ?_spawns');
$sum = 0; 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($q[1]);
CLI::write(' * sets '.($sum + 1).' - '.($sum += SqlGen::$stepSize));
if ($n++ > SqlGen::$stepSize) $n = 0;
$n = 0; $sum = 0;
// npc/object is on a transport -> apply offsets to path of transport if ($idx == 3 || $idx == 4)
// note, that the coordinates are mixed up .. again $queryResult = DB::Aowow()->select($q[0]);
// 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));
}
else else
{ $queryResult = DB::World()->select($q[0]);
$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)); 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 // get vehicle template accessories
$accessories = DB::World()->select(' $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 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'); 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") // 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 // 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 $vGuid = 0; // not really used, but we need some kind of index
$n = 0; $n = 0;
$matches = -1; $matches = -1;
while ($matches) while ($matches)
{
$matches = 0;
foreach ($accessories as $idx => $data)
{ {
$vehicles = []; $matches = 0;
if ($data['guid']) // vehicle already spawned foreach ($accessories as $idx => $data)
$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++; $vehicles = [];
foreach ($vehicles as $v) // if there is more than one vehicle, its probably due to overlapping zones if ($data['guid']) // vehicle already spawned
for ($i = 0; $i < $data['nSeats']; $i++) $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);
DB::Aowow()->query(' else if ($data['entry']) // vehicle on unspawned vehicle action
REPLACE INTO ?_spawns (`guid`, `type`, `typeId`, `respawn`, `spawnMask`, `phaseMask`, `areaId`, `floor`, `posX`, `posY`, `pathId`) VALUES $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);
(?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 ($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) if ($accessories)
CLI::write(' * assigned '.$matches.' accessories on '.++$n.'. pass on vehicle 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;
}
?> ?>

File diff suppressed because it is too large Load Diff

View File

@@ -7,26 +7,26 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps: SqlGen::register(new class extends SetupScript
* spelldifficulty_dbc
*/
$customData = array(
);
$reqDBC = ['spelldifficulty'];
function spelldifficulty(array $ids = [])
{ {
// has no unique keys.. protected $command = 'spelldifficulty';
DB::Aowow()->query('TRUNCATE TABLE ?_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'); public function generate(array $ids = []) : bool
foreach ($rows as $r) {
DB::Aowow()->query('INSERT INTO ?_spelldifficulty VALUES (?a)', array_values($r)); // 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;
}
});
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'spellfocusobject';
protected $dbcSourceFiles = ['spellfocusobject'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'spelloverride';
protected $dbcSourceFiles = ['overridespelldata'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'spellrange';
protected $dbcSourceFiles = ['spellrange'];
});
?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'spellvariables';
protected $dbcSourceFiles = ['spelldescriptionvariables'];
});
?>

View File

@@ -7,35 +7,38 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
$customData = array( SqlGen::register(new class extends SetupScript
);
$reqDBC = ['talent', 'talenttab'];
function talents()
{ {
// class: 0 => hunter pets protected $command = 'talents';
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; 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;
}
});
?> ?>

View File

@@ -7,170 +7,169 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps SqlGen::register(new class extends SetupScript
* creature_template
* creature
*/
$customData = array(
);
$reqDBC = ['taxipath', 'taxinodes', 'worldmaparea', 'worldmaptransforms', 'factiontemplate'];
function taxi() // path & nodes
{ {
/*********/ protected $command = 'taxi'; // path & nodes
/* 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'); 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) public function generate(array $ids = []) : bool
$paths = DB::Aowow()->select('SELECT id AS ARRAY_KEY, tp.* FROM ?_taxipath tp');
foreach ($paths as $i => $p)
{ {
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); if ($_['startNodeId'] == $p['endNodeId'] AND $_['endNodeId'] == $p['startNodeId'])
unset($paths[$j]); {
unset($paths[$i]); DB::Aowow()->query('DELETE FROM ?_taxipath WHERE id = ?d', $j);
break; unset($paths[$j]);
unset($paths[$i]);
break;
}
} }
} }
}
/*********/ /*********/
/* nodes */ /* nodes */
/*********/ /*********/
// all sensible nodes // all sensible nodes
$fNodes = DB::Aowow()->select( $fNodes = DB::Aowow()->select(
'SELECT 'SELECT
tn.id, tn.id,
tn.mapId, tn.mapId,
100 - ROUND((tn.posY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, 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, 100 - ROUND((tn.posX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY,
1 AS type, 1 AS type,
0 AS typeId, 0 AS typeId,
1 AS reactA, 1 AS reactA,
1 AS reactH, 1 AS reactH,
tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8,
tn.mapId AS origMap, tn.mapId AS origMap,
tn.posX AS origPosX, tn.posX AS origPosX,
tn.posY AS origPosY, tn.posY AS origPosY,
IF (tn.id NOT IN (15, 148, 225, 235) AND IF (tn.id NOT IN (15, 148, 225, 235) AND
(
tn.id IN (64, 250) OR
( (
tn.name_loc0 NOT LIKE "%Transport%" AND tn.id IN (64, 250) OR
tn.name_loc0 NOT LIKE "%Quest%" AND (
tn.name_loc0 NOT LIKE "%Start%" AND tn.name_loc0 NOT LIKE "%Transport%" AND
tn.name_loc0 NOT LIKE "%End%" tn.name_loc0 NOT LIKE "%Quest%" AND
) tn.name_loc0 NOT LIKE "%Start%" AND
), 0, 1) AS scripted tn.name_loc0 NOT LIKE "%End%"
FROM )
dbc_taxinodes tn ), 0, 1) AS scripted
JOIN FROM
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) dbc_taxinodes tn
WHERE JOIN
wma.areaId = 0 AND 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)
wma.mapId = tn.mapId WHERE
UNION wma.areaId = 0 AND
SELECT wma.mapId = tn.mapId
tn.id, UNION
wmt.targetMapId, SELECT
100 - ROUND((tn.posY + wmt.offsetY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, tn.id,
100 - ROUND((tn.posX + wmt.offsetX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, wmt.targetMapId,
1 AS type, 100 - ROUND((tn.posY + wmt.offsetY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX,
0 AS typeId, 100 - ROUND((tn.posX + wmt.offsetX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY,
1 AS reactA, 1 AS type,
1 AS reactH, 0 AS typeId,
tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, 1 AS reactA,
tn.mapId AS origMap, 1 AS reactH,
tn.posX AS origPosX, tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8,
tn.posY AS origPosY, tn.mapId AS origMap,
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%", tn.posX AS origPosX,
0, tn.posY AS origPosY,
1 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%",
) AS scripted 0,
FROM 1
dbc_taxinodes tn ) AS scripted
JOIN FROM
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) dbc_taxinodes tn
JOIN 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) 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)
WHERE JOIN
wma.areaId = 0 AND 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)
wmt.sourcemapId = tn.mapId' WHERE
); wma.areaId = 0 AND
wmt.sourcemapId = tn.mapId'
);
// all available flightmaster // all available flightmaster
$fMaster = DB::World()->select( $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', '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 NPC_FLAG_FLIGHT_MASTER, NPC_FLAG_FLIGHT_MASTER
); );
// assign nearest flightmaster to node // assign nearest flightmaster to node
foreach ($fNodes as &$n) foreach ($fNodes as &$n)
{
foreach ($fMaster as &$c)
{ {
if ($c['map'] != $n['origMap']) foreach ($fMaster as &$c)
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; if ($c['map'] != $n['origMap'])
$n['typeId'] = $c['entry']; continue;
$n['faction'] = $c['faction'];
$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 // fetch reactions per faction
$factions = DB::Aowow()->query(' $factions = DB::Aowow()->query('
SELECT SELECT
id AS ARRAY_KEY, 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 = 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 IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 1) AS reactH
FROM FROM
dbc_factiontemplate dbc_factiontemplate
WHERE WHERE
id IN (?a)', id IN (?a)',
array_column($fNodes, 'faction') array_column($fNodes, 'faction')
); );
foreach ($fNodes as $n) 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']]))
{ {
$n['reactA'] = $factions[$n['faction']]['reactA']; // if (empty($n['faction']))
$n['reactH'] = $factions[$n['faction']]['reactH']; // {
// 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;
}
?> ?>

View File

@@ -6,22 +6,22 @@ if (!defined('AOWOW_REVISION'))
if (!CLI) if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps:
* quest_template
* game_event_seasonal_questrelation
* game_event
* achievement_reward
*/
$customData = array( SqlGen::register(new class extends SetupScript
137 => ['gender' => 2],
138 => ['gender' => 1],
);
$reqDBC = ['chartitles'];
function titles()
{ {
$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, 137 => 201,
138 => 201, 138 => 201,
124 => 324, 124 => 324,
@@ -35,69 +35,72 @@ function titles()
168 => 404 168 => 404
); );
$questQuery = ' public function generate(array $ids = []) : bool
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)
{ {
if ($data['eventEntry']) $questQuery = '
DB::Aowow()->query('UPDATE ?_titles SET eventId = ?d WHERE id = ?d', $data['eventEntry'], $tId); 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']); 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 ($side == 3)
continue;
if (!isset($sideUpd[$tId])) // hide unused titles
$sideUpd[$tId] = $side; 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);
else
$sideUpd[$tId] |= $side; // 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;
}
?> ?>

View File

@@ -0,0 +1,18 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
SqlGen::register(new class extends SetupScript
{
use TrDBCcopy;
protected $command = 'totemcategory';
protected $dbcSourceFiles = ['totemcategory'];
});
?>

View File

@@ -7,227 +7,232 @@ if (!CLI)
die('not in cli mode'); die('not in cli mode');
/* deps SqlGen::register(new class extends SetupScript
* 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()
{ {
// base query use TrCustomData;
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);
// get requirements from world.access_requirement protected $command = 'zones';
$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
');
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']]; // base query
$aN = $aH = []; 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']) // get requirements from world.access_requirement
$update['levelHeroic'] = $req['heroicLevel']; $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']) foreach ($zoneReq as $mapId => $req)
$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) $update = ['levelReq' => $req['reqLevel']];
$aN[$type] = $type.':'.implode(' '.$type.':', $entries); $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) return true;
{
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;
}
?> ?>