diff --git a/includes/ajaxHandler/admin.class.php b/includes/ajaxHandler/admin.class.php
index 4870878e..8a88a375 100644
--- a/includes/ajaxHandler/admin.class.php
+++ b/includes/ajaxHandler/admin.class.php
@@ -383,7 +383,7 @@ class AjaxAdmin extends AjaxHandler
$area = $this->_get['area'];
$floor = $this->_get['floor'];
- if (!in_array($type, [Type::NPC, Type::OBJECT, Type::SOUND, Type::AREATRIGGER]))
+ if (!in_array($type, [Type::NPC, Type::OBJECT, Type::SOUND, Type::AREATRIGGER, Type::ZONE]))
return '-3';
DB::Aowow()->query('REPLACE INTO ?_spawns_override VALUES (?d, ?d, ?d, ?d, ?d)', $type, $guid, $area, $floor, AOWOW_REVISION);
diff --git a/includes/basetype.class.php b/includes/basetype.class.php
index c20a05f6..cbd51f29 100644
--- a/includes/basetype.class.php
+++ b/includes/basetype.class.php
@@ -591,14 +591,16 @@ trait spawnHelper
return;
if (User::isInGroup(U_GROUP_MODERATOR))
- if ($guids = array_filter(array_column($spawns, 'guid'), function ($x) { return $x > 0; }))
+ if ($guids = array_column(array_filter($spawns, function ($x) { return $x['guid'] > 0 || $x['type'] != Type::NPC; }), 'guid'))
$worldPos = Game::getWorldPosForGUID(self::$type, ...$guids);
foreach ($spawns as $s)
{
+ $isAccessory = $s['guid'] < 0 && $s['type'] == Type::NPC;
+
// check, if we can attach waypoints to creature
// we will get a nice clusterfuck of dots if we do this for more GUIDs, than we have colors though
- if (count($spawns) < 6 && self::$type == Type::NPC)
+ if (count($spawns) < 6 && $s['type'] == Type::NPC)
{
if ($wPoints = DB::Aowow()->select('SELECT * FROM ?_creature_waypoints WHERE creatureOrPath = ?d AND floor = ?d', $s['pathId'] ? -$s['pathId'] : $this->id, $s['floor']))
{
@@ -641,7 +643,10 @@ trait spawnHelper
if (User::isInGroup(U_GROUP_STAFF))
{
- $info[0] = $s['guid'] < 0 ? 'Vehicle Accessory' : 'GUID'.Lang::main('colon').$s['guid'];
+ if ($isAccessory)
+ $info[0] = 'Vehicle Accessory';
+ else if ($s['guid'] > 0 && ($s['type'] == Type::NPC || $s['type'] == Type::OBJECT))
+ $info[0] = 'GUID'.Lang::main('colon').$s['guid'];
if ($s['phaseMask'] > 1 && ($s['phaseMask'] & 0xFFFF) != 0xFFFF)
$info[2] = Lang::game('phases').Lang::main('colon').Util::asHex($s['phaseMask']);
@@ -658,56 +663,27 @@ trait spawnHelper
$info[4] = Lang::game('mode').Lang::main('colon').implode(', ', $_);
}
- if (self::$type == Type::AREATRIGGER)
+ if ($s['type'] == Type::AREATRIGGER)
{
- $o = Util::O2Deg($this->getField('orientation'));
- $info[5] = 'Orientation'.Lang::main('colon').$o[0].'° ('.$o[1].')';
+ // teleporter endpoint
+ if ($s['guid'] < 0)
+ {
+ $opts['type'] = 4;
+ $info[5] = 'Teleport Destination';
+ }
+ else
+ {
+ $o = Util::O2Deg($this->getField('orientation'));
+ $info[5] = 'Orientation'.Lang::main('colon').$o[0].'° ('.$o[1].')';
+ }
}
// guid < 0 are vehicle accessories. those are moved by moving the vehicle
- if (User::isInGroup(U_GROUP_MODERATOR) && $worldPos && $s['guid'] > 0 && isset($worldPos[$s['guid']]))
- {
- if ($points = Game::worldPosToZonePos($worldPos[$s['guid']]['mapId'], $worldPos[$s['guid']]['posX'], $worldPos[$s['guid']]['posY']))
- {
- $floors = [];
- foreach ($points as $p)
- {
- if ($p['multifloor'])
- $floors[$p['areaId']][] = $p['floor'];
+ if (User::isInGroup(U_GROUP_MODERATOR) && $worldPos && !$isAccessory && isset($worldPos[$s['guid']]))
+ $menu = Util::buildPosFixMenu($worldPos[$s['guid']]['mapId'], $worldPos[$s['guid']]['posX'], $worldPos[$s['guid']]['posY'], $s['type'], $s['guid'], $s['areaId'], $s['floor']);
- if (isset($menu[$p['areaId']]))
- continue;
- else if ($p['areaId'] == $s['areaId'])
- $menu[$p['areaId']] = [$p['areaId'], '$g_zones['.$p['areaId'].']', '', null, ['class' => 'checked q0']];
- else
- $menu[$p['areaId']] = [$p['areaId'], '$g_zones['.$p['areaId'].']', '$spawnposfix.bind(null, '.self::$type.', '.$s['guid'].', '.$p['areaId'].', 0)', null, null];
- }
-
- foreach ($floors as $area => $f)
- {
- $menu[$area][2] = '';
- $menu[$area][3] = [];
- if ($menu[$area][4])
- $menu[$area][4]['class'] = 'checked';
-
- foreach ($f as $n)
- {
- if ($n == $s['floor'])
- $menu[$area][3][] = [$n, '$g_zone_areas['.$area.']['.($n - 1).']', '', null, ['class' => 'checked q0']];
- else
- $menu[$area][3][] = [$n, '$g_zone_areas['.$area.']['.($n - 1).']', '$spawnposfix.bind(null, '.self::$type.', '.$s['guid'].', '.$area.', '.$n.')'];
- }
- }
-
- $menu = array_values($menu);
- }
-
- if ($menu)
- {
- $footer = '
Click to move displayed spawn point';
- array_unshift($menu, [null, "Move to..."]);
- }
- }
+ if ($menu)
+ $footer = '
Click to move pin';
}
if ($info)
diff --git a/includes/defines.php b/includes/defines.php
index f9d55770..eb6e729f 100644
--- a/includes/defines.php
+++ b/includes/defines.php
@@ -257,6 +257,13 @@ define('GUIDE_STATUS_ARCHIVED', 5);
define('DEFAULT_ICON', 'inv_misc_questionmark');
+define('MENU_IDX_ID', 0); // ID: A number or string; null makes the menu item a separator
+define('MENU_IDX_NAME', 1); // Name: A string
+define('MENU_IDX_URL', 2); // URL: A string for the URL, or a function to call when the menu item is clicked
+define('MENU_IDX_SUB', 3); // Submenu: Child menu
+define('MENU_IDX_OPT', 4); // Options: JSON array with additional options
+
+
/*
* Game
*/
diff --git a/includes/game.php b/includes/game.php
index e0bccd3e..30a57b0c 100644
--- a/includes/game.php
+++ b/includes/game.php
@@ -311,16 +311,27 @@ class Game
switch ($type)
{
case Type::NPC:
- $result = DB::World()->select('SELECT `guid` AS ARRAY_KEY, `id`, `map` AS `mapId`, `position_x` AS `posX`, `position_y` AS `posY` FROM creature WHERE `guid` IN (?a)', $guids);
+ $result = DB::World()->select('SELECT `guid` AS ARRAY_KEY, `id`, `map` AS `mapId`, `position_x` AS `posX`, `position_y` AS `posY` FROM creature WHERE `guid` IN (?a)', $guids);
break;
case Type::OBJECT:
- $result = DB::World()->select('SELECT `guid` AS ARRAY_KEY, `id`, `map` AS `mapId`, `position_x` AS `posX`, `position_y` AS `posY` FROM gameobject WHERE `guid` IN (?a)', $guids);
+ $result = DB::World()->select('SELECT `guid` AS ARRAY_KEY, `id`, `map` AS `mapId`, `position_x` AS `posX`, `position_y` AS `posY` FROM gameobject WHERE `guid` IN (?a)', $guids);
break;
case Type::SOUND:
- $result = DB::AoWoW()->select('SELECT `id` AS ARRAY_KEY, `soundId` AS `id`, `mapId`, `posX`, `posY` FROM ?_soundemitters WHERE `id` IN (?a)', $guids);
+ $result = DB::AoWoW()->select('SELECT `id` AS ARRAY_KEY, `soundId` AS `id`, `mapId`, `posX`, `posY` FROM ?_soundemitters WHERE `id` IN (?a)', $guids);
+ break;
+ case Type::ZONE:
+ $result = DB::Aowow()->select('SELECT -`id` AS ARRAY_KEY, `id`, `parentMapId` AS `mapId`, `parentX` AS `posX`, `parentY` AS `posY` FROM ?_zones WHERE -`id` IN (?a)', $guids);
break;
case Type::AREATRIGGER:
- $result = DB::AoWoW()->select('SELECT `id` AS ARRAY_KEY, `id`, `mapId`, `posX`, `posY` FROM ?_areatrigger WHERE `id` IN (?a)', $guids);
+ $result = [];
+ if ($base = array_filter($guids, function ($x) { return $x > 0; }))
+ $result = array_replace($result, DB::AoWoW()->select('SELECT `id` AS ARRAY_KEY, `id`, `mapId`, `posX`, `posY` FROM ?_areatrigger WHERE `id` IN (?a)', $base));
+ if ($endpoints = array_filter($guids, function ($x) { return $x < 0; }))
+ $result = array_replace($result, DB::World()->select(
+ 'SELECT -`ID` AS ARRAY_KEY, ID AS `id`, `target_map` AS `mapId`, `target_position_x` AS `posX`, `target_position_y` AS `posY` FROM areatrigger_teleport WHERE -`id` IN (?a) UNION
+ SELECT -`entryorguid` AS ARRAY_KEY, entryorguid AS `id`, `action_param1` AS `mapId`, `target_x` AS `posX`, `target_y` AS `posY` FROM smart_scripts WHERE -`entryorguid` IN (?a) AND `source_type` = ?d AND `action_type` = ?d',
+ $endpoints, $endpoints, SAI_SRC_TYPE_AREATRIGGER, SAI_ACTION_TELEPORT
+ ));
break;
default:
trigger_error('Game::getWorldPosForGUID - instanced with unsupported TYPE #'.$type, E_USER_WARNING);
diff --git a/includes/utilities.php b/includes/utilities.php
index d4b7bf36..62aee8dc 100644
--- a/includes/utilities.php
+++ b/includes/utilities.php
@@ -140,6 +140,7 @@ abstract class CLI
private const CHR_ESC = 27;
private const CHR_BACKSPACE = 127;
+ public const LOG_NONE = -1;
public const LOG_BLANK = 0;
public const LOG_ERROR = 1;
public const LOG_WARN = 2;
@@ -190,13 +191,13 @@ abstract class CLI
}
if ($i || $headless)
- self::write(' '.implode(' ' . self::tblDelim(' ') . ' ', $row), -1, $timestamp);
+ self::write(' '.implode(' ' . self::tblDelim(' ') . ' ', $row), CLI::LOG_NONE, $timestamp);
else
- self::write(self::tblHead(' '.implode(' ', $row)), -1, $timestamp);
+ self::write(self::tblHead(' '.implode(' ', $row)), CLI::LOG_NONE, $timestamp);
}
if (!$headless)
- self::write(self::tblHead(str_pad('', array_sum($pads) + count($pads) * 3 - 2)), -1, $timestamp);
+ self::write(self::tblHead(str_pad('', array_sum($pads) + count($pads) * 3 - 2)), CLI::LOG_NONE, $timestamp);
self::write();
}
@@ -1576,7 +1577,7 @@ abstract class Util
}
// orientation is 2*M_PI for a full circle, increasing counterclockwise
- static function O2Deg($o)
+ public static function O2Deg($o)
{
// orientation values can exceed boundaries (for whatever reason)
while ($o < 0)
@@ -1609,7 +1610,7 @@ abstract class Util
return [(int)$deg, $desc];
}
- static function mask2bits(int $bitmask, int $offset = 0) : array
+ public static function mask2bits(int $bitmask, int $offset = 0) : array
{
$bits = [];
$i = 0;
@@ -1625,6 +1626,46 @@ abstract class Util
return $bits;
}
+
+ public static function buildPosFixMenu(int $mapId, float $posX, float $posY, int $type, int $guid, int $parentArea = 0, int $parentFloor = 0) : array
+ {
+ $points = Game::worldPosToZonePos($mapId, $posX, $posY);
+ if (!$points || count($points) < 2)
+ return [];
+
+ $floors = [];
+ $menu = [[null, "Move Location to..."]];
+ foreach ($points as $p)
+ {
+ if ($p['multifloor'])
+ $floors[$p['areaId']][] = $p['floor'];
+
+ if (isset($menu[$p['areaId']]))
+ continue;
+ else if ($p['areaId'] == $parentArea)
+ $menu[$p['areaId']] = [$p['areaId'], '$g_zones['.$p['areaId'].']', '', null, ['class' => 'checked q0']];
+ else
+ $menu[$p['areaId']] = [$p['areaId'], '$g_zones['.$p['areaId'].']', '$spawnposfix.bind(null, '.$type.', '.$guid.', '.$p['areaId'].', 0)', null, null];
+ }
+
+ foreach ($floors as $area => $f)
+ {
+ $menu[$area][MENU_IDX_URL] = null;
+ $menu[$area][MENU_IDX_SUB] = [];
+ if ($menu[$area][MENU_IDX_OPT])
+ $menu[$area][MENU_IDX_OPT]['class'] = 'checked';
+
+ foreach ($f as $n)
+ {
+ if ($n == $parentFloor)
+ $menu[$area][MENU_IDX_SUB][] = [$n, '$g_zone_areas['.$area.']['.($n - 1).']', '', null, ['class' => 'checked q0']];
+ else
+ $menu[$area][MENU_IDX_SUB][] = [$n, '$g_zone_areas['.$area.']['.($n - 1).']', '$spawnposfix.bind(null, '.$type.', '.$guid.', '.$area.', '.$n.')'];
+ }
+ }
+
+ return array_values($menu);
+ }
}
diff --git a/pages/areatrigger.php b/pages/areatrigger.php
index 858ea42c..73bb9fc3 100644
--- a/pages/areatrigger.php
+++ b/pages/areatrigger.php
@@ -58,36 +58,7 @@ class AreaTriggerPage extends GenericPage
$map = null;
if ($spawns = $this->subject->getSpawns(SPAWNINFO_FULL))
{
- $ta = $this->subject->getField('teleportA');
- $tf = $this->subject->getField('teleportF');
- $tx = $this->subject->getField('teleportX');
- $ty = $this->subject->getField('teleportY');
- $to = $this->subject->getField('teleportO');
-
- // add teleport target
- if ($ta && $tx && $ty)
- {
- $o = Util::O2Deg($to);
- $endPoint = array($tx, $ty, array(
- 'type' => 4,
- 'tooltip' => array(
- 'Teleport Destination' => array(
- 'info' => ['Orientation'.Lang::main('colon').$o[0].'° ('.$o[1].')']
- )
- )
- ));
-
- if (isset($spawns[$ta][$tf]))
- $spawns[$ta][$tf]['coords'][] = $endPoint;
- else
- $spawns[$ta][$tf]['coords'] = [$endPoint];
- }
-
- $map = array(
- 'data' => ['parent' => 'mapper-generic'],
- 'mapperData' => &$spawns
- );
-
+ $map = ['data' => ['parent' => 'mapper-generic'], 'mapperData' => &$spawns];
foreach ($spawns as $areaId => &$areaData)
$map['extra'][$areaId] = ZoneList::getName($areaId);
}
diff --git a/pages/zone.php b/pages/zone.php
index 07080c3d..ed6c78ae 100644
--- a/pages/zone.php
+++ b/pages/zone.php
@@ -113,21 +113,19 @@ class ZonePage extends GenericPage
}
// Instances
- if ($_ = DB::Aowow()->selectCol('SELECT `id` FROM ?_zones WHERE `parentAreaId` = ?d AND (`cuFlags` & ?d) = 0', $this->typeId, CUSTOM_EXCLUDE_FOR_LISTVIEW))
+ if ($_ = DB::Aowow()->selectCol('SELECT `typeId` FROM ?_spawns WHERE `type`= ?d AND `areaId` = ?d ', Type::ZONE, $this->typeId))
{
$this->extendGlobalIds(Type::ZONE, ...$_);
$infobox[] = Lang::maps('Instances').Lang::main('colon')."\n[zone=".implode("], \n[zone=", $_).']';
}
// location (if instance)
- if ($pa = $this->subject->getField('parentAreaId'))
+ if ($pa = DB::Aowow()->selectRow('SELECT `areaId`, `posX`, `posY`, `floor` FROM ?_spawns WHERE `type`= ?d AND `typeId` = ?d ', Type::ZONE, $this->typeId))
{
- $paO = new ZoneList(array(['id', $pa]));
- if (!$paO->error)
- {
- $pins = str_pad($this->subject->getField('parentX') * 10, 3, '0', STR_PAD_LEFT) . str_pad($this->subject->getField('parentY') * 10, 3, '0', STR_PAD_LEFT);
- $infobox[] = Lang::zone('location').Lang::main('colon').'[lightbox=map zone='.$pa.' pins='.$pins.']'.$paO->getField('name', true).'[/lightbox]';
- }
+ $this->addMoveLocationMenu($pa['areaId'], $pa['floor']);
+
+ $pins = str_pad($pa['posX'] * 10, 3, '0', STR_PAD_LEFT) . str_pad($pa['posY'] * 10, 3, '0', STR_PAD_LEFT);
+ $infobox[] = Lang::zone('location').Lang::main('colon').'[lightbox=map zone='.$pa['areaId'].' '.($pa['floor'] > 1 ? 'floor='.--$pa['floor'] : '').' pins='.$pins.']'.ZoneList::getName($pa['areaId']).'[/lightbox]';
}
/* has to be defined in an article, i think
@@ -413,6 +411,9 @@ class ZonePage extends GenericPage
foreach ($aSpawns as $spawn)
{
+ if ($spawn['guid'] < 0) // skip teleporter endpoints
+ continue;
+
$tpl = $atSpawns->getEntry($spawn['typeId']);
if (!$tpl)
continue;
@@ -423,7 +424,7 @@ class ZonePage extends GenericPage
'name' => Util::localizedString($tpl, 'name', true, true),
'type' => Type::AREATRIGGER,
'id' => $spawn['typeId'],
- 'description' => 'Type: '.Lang::areatrigger('types', $tpl['type'])
+ 'description' => Lang::game('type').Lang::main('colon').Lang::areatrigger('types', $tpl['type'])
));
}
@@ -785,6 +786,25 @@ class ZonePage extends GenericPage
}
}
+ private function addMoveLocationMenu($parentArea, $parentFloor)
+ {
+ // hide for non-staff
+ if (!User::isInGroup(U_GROUP_EMPLOYEE))
+ return;
+
+ $worldPos = Game::getWorldPosForGUID(Type::ZONE, -$this->typeId);
+ if (!$worldPos)
+ return;
+
+ $menu = Util::buildPosFixMenu($worldPos[-$this->typeId]['mapId'], $worldPos[-$this->typeId]['posX'], $worldPos[-$this->typeId]['posY'], Type::ZONE, -$this->typeId, $parentArea, $parentFloor);
+ if (!$menu)
+ return;
+
+ $menu = [1002, 'Edit DB Entry', null, $menu];
+
+ $this->addScript([SC_JS_STRING, '$(document).ready(function () { mn_staff.push('.Util::toJSON(array_values($menu)).'); });']);
+ }
+
protected function generatePath()
{
$this->path[] = $this->subject->getField('category');
diff --git a/setup/db_structure.sql b/setup/db_structure.sql
index 7ed615c3..f084ff78 100644
--- a/setup/db_structure.sql
+++ b/setup/db_structure.sql
@@ -350,11 +350,6 @@ CREATE TABLE `aowow_areatrigger` (
`orientation` float NOT NULL,
`name` varchar(100) DEFAULT NULL,
`quest` mediumint unsigned DEFAULT NULL,
- `teleportA` smallint unsigned DEFAULT NULL,
- `teleportX` float unsigned DEFAULT NULL,
- `teleportY` float unsigned DEFAULT NULL,
- `teleportO` float DEFAULT NULL,
- `teleportF` tinyint unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `quest` (`quest`),
KEY `type` (`type`)
@@ -3131,7 +3126,7 @@ CREATE TABLE `aowow_zones` (
`levelMax` tinyint unsigned NOT NULL,
`attunementsN` text NOT NULL COMMENT 'space separated; type:typeId',
`attunementsH` text NOT NULL COMMENT 'space separated; type:typeId',
- `parentAreaId` smallint unsigned NOT NULL,
+ `parentMapId` smallint unsigned NOT NULL,
`parentX` float NOT NULL,
`parentY` float NOT NULL,
`name_loc0` varchar(120) DEFAULT NULL COMMENT 'Map Name',
@@ -3290,7 +3285,7 @@ UNLOCK TABLES;
LOCK TABLES `aowow_setup_custom_data` WRITE;
/*!40000 ALTER TABLE `aowow_setup_custom_data` DISABLE KEYS */;
-INSERT INTO `aowow_setup_custom_data` VALUES ('zones',2257,'cuFlags','0','Deeprun Tram - make visible'),('zones',2257,'category','0','Deeprun Tram - Category: Eastern Kingdoms'),('zones',2257,'type','1','Deeprun Tram - Type: Transit'),('zones',3698,'expansion','1','Nagrand Arena - Addon: BC'),('zones',3702,'expansion','1','Blades Edge Arena - Addon: BC'),('zones',3968,'expansion','1','Ruins of Lordaeron Arena - Addon: BC'),('zones',4378,'expansion','1','Dalaran Arena - Addon: WotLK'),('zones',4406,'expansion','1','Ring of Valor Arena - Addon: WotLK'),('zones',2597,'maxPlayer','40','Alterac Valey - Players: 40 [battlemasterlist.dbc: 5]'),('zones',4710,'maxPlayer','40','Isle of Conquest - Players: 40 [battlemasterlist.dbc: 5]'),('zones',3849,'parentAreaId','3523','The Mechanar - Parent: Netherstorm [not set in map.dbc]'),('zones',3849,'parentX','87.3','The Mechanar - Entrance xPos'),('zones',3849,'parentY','51.1','The Mechanar - Entrance yPos'),('zones',3847,'parentAreaId','3523','The Botanica - Parent: Netherstorm [not set in map.dbc]'),('zones',3847,'parentX','71.7','The Botanica - Entrance xPos'),('zones',3847,'parentY','55.1','The Botanica - Entrance yPos'),('zones',3848,'parentAreaId','3523','The Arcatraz - Parent: Netherstorm [not set in map.dbc]'),('zones',3848,'parentX','74.3','The Arcatraz - Entrance xPos'),('zones',3848,'parentY','57.8','The Arcatraz - Entrance yPos'),('zones',3845,'parentAreaId','3523','Tempest Keep - Parent: Netherstorm [not set in map.dbc]'),('zones',3845,'parentX','73.5','Tempest Keep - Entrance xPos'),('zones',3845,'parentY','63.7','Tempest Keep - Entrance yPos'),('zones',3456,'parentAreaId','65','Naxxramas - Parent: Netherstorm [not set in map.dbc]'),('zones',3456,'parentX','87.3','Naxxramas - Entrance xPos'),('zones',3456,'parentY','87.3','Naxxramas - Entrance yPos'),('zones',4893,'cuFlags','1073741824','The Frost Queen\'s Lair - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4894,'cuFlags','1073741824','Putricide\'s Laboratory [..] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('achievement',1956,'itemExtra','44738','Higher Learning - item rewarded through gossip'),('zones',4895,'cuFlags','1073741824','The Crimson Hall - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('titles',137,'gender','2','Matron - female'),('zones',4896,'cuFlags','1073741824','The Frozen Throne - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4897,'cuFlags','1073741824','The Sanctum of Blood - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4076,'cuFlags','1073741824','Reuse Me 7 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',207,'cuFlags','1073741824','The Great Sea - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',208,'cuFlags','1073741824','Unused Ironcladcove - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',2817,'levelMin','74','Crystalsong Forest - missing lfgDungeons entry'),('zones',1417,'cuFlags','1073741824','Sunken Temple [extra area on map 109] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',22,'cuFlags','1073741824','Programmer Isle - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',151,'cuFlags','1073741824','Designer Island - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',3948,'cuFlags','1073741824','Brian and Pat Test - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4019,'cuFlags','1073741824','Development Land - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',3605,'cuFlags','1073741824','Hyjal Past [extra area on map 560] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',3535,'cuFlags','1073741824','Hellfire Citadel [extra area on map 540] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',41,'levelMin','50','Deadwind Pass - missing lfgDungeons entry'),('zones',41,'levelMax','60','Deadwind Pass - missing lfgDungeons entry'),('zones',2257,'levelMin','1','Deeprun Tram - missing lfgDungeons entry'),('zones',2257,'levelMax','80','Deeprun Tram - missing lfgDungeons entry'),('zones',4298,'category','0','Plaguelands: The Scarlet Enclave - Parent: Eastern Kingdoms'),('zones',4298,'levelMin','55','Plaguelands: The Scarlet Enclave - missing lfgDungeons entry'),('zones',4298,'levelMax','58','Plaguelands: The Scarlet Enclave - missing lfgDungeons entry'),('zones',493,'levelMin','15','Moonglade - missing lfgDungeons entry'),('zones',493,'levelMax','60','Moonglade - missing lfgDungeons entry'),('zones',2817,'levelMax','76','Crystalsong Forest - missing lfgDungeons entry'),('zones',4742,'levelMin','77','Hrothgar\'s Landing - missing lfgDungeons entry'),('zones',4742,'levelMax','80','Hrothgar\'s Landing - missing lfgDungeons entry'),('classes',1,'roles','10','Warrior - rngDPS'),('classes',2,'roles','11','Paladin - mleDPS + Tank + Heal'),('classes',3,'roles','4','Hunter - rngDPS'),('classes',4,'roles','2','Rogue - mleDPS'),('classes',5,'roles','5','Priest - rngDPS + Heal'),('classes',6,'roles','10','Death Knight - mleDPS + Tank'),('classes',7,'roles','7','Shaman - mleDPS + rngDPS + Heal'),('classes',8,'roles','4','Mage - rngDPS'),('classes',9,'roles','4','Warlock - rngDPS'),('classes',11,'roles','15','Druid - mleDPS + Tank + Heal + rngDPS'),('currencies',103,'cap','10000','Arena Points - cap'),('currencies',104,'cap','75000','Honor Points - cap'),('currencies',1,'cuFlags','1073741824','Currency Token Test Token 1 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',2,'cuFlags','1073741824','Currency Token Test Token 2 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',4,'cuFlags','1073741824','Currency Token Test Token 3 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',22,'cuFlags','1073741824','Birmingham Test Item 3 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',141,'cuFlags','1073741824','zzzOLDDaily Quest Faction Token - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',1,'category','3','Currency Token Test Token 1 - category: unused'),('currencies',2,'category','3','Currency Token Test Token 2 - category: unused'),('currencies',4,'category','3','Currency Token Test Token 3 - category: unused'),('currencies',22,'category','3','Birmingham Test Item 3 - category: unused'),('currencies',141,'category','3','zzzOLDDaily Quest Faction Token - category: unused'),('factions',68,'qmNpcIds','33555','Undercity - set Quartermaster'),('factions',47,'qmNpcIds','33310','Ironforge - set Quartermaster'),('factions',69,'qmNpcIds','33653','Darnassus - set Quartermaster'),('factions',72,'qmNpcIds','33307','Stormwind - set Quartermaster'),('factions',76,'qmNpcIds','33553','Orgrimmar - set Quartermaster'),('factions',81,'qmNpcIds','33556','Thunder Bluff - set Quartermaster'),('factions',922,'qmNpcIds','16528','Tranquillien - set Quartermaster'),('factions',930,'qmNpcIds','33657','Exodar - set Quartermaster'),('factions',932,'qmNpcIds','19321','The Aldor - set Quartermaster'),('factions',933,'qmNpcIds','20242 23007','The Consortium - set Quartermaster'),('factions',935,'qmNpcIds','21432','The Sha\'tar - set Quartermaster'),('factions',941,'qmNpcIds','20241','The Mag\'har - set Quartermaster'),('factions',942,'qmNpcIds','17904','Cenarion Expedition - set Quartermaster'),('factions',946,'qmNpcIds','17657','Honor Hold - set Quartermaster'),('factions',947,'qmNpcIds','17585','Thrallmar - set Quartermaster'),('factions',970,'qmNpcIds','18382','Sporeggar - set Quartermaster'),('factions',978,'qmNpcIds','20240','Kurenai - set Quartermaster'),('factions',989,'qmNpcIds','21643','Keepers of Time - set Quartermaster'),('factions',1011,'qmNpcIds','21655','Lower City - set Quartermaster'),('factions',1012,'qmNpcIds','23159','Ashtongue Deathsworn - set Quartermaster'),('factions',1037,'qmNpcIds','32773 32564','Alliance Vanguard - set Quartermaster'),('factions',1038,'qmNpcIds','23428','Ogri\'la - set Quartermaster'),('factions',1052,'qmNpcIds','32774 32565','Horde Expedition - set Quartermaster'),('factions',1073,'qmNpcIds','31916 32763','The Kalu\'ak - set Quartermaster'),('factions',1090,'qmNpcIds','32287','Kirin Tor - set Quartermaster'),('factions',1091,'qmNpcIds','32533','The Wyrmrest Accord - set Quartermaster'),('factions',1094,'qmNpcIds','34881','The Silver Covenant - set Quartermaster'),('factions',1105,'qmNpcIds','31910','The Oracles - set Quartermaster'),('factions',1106,'qmNpcIds','30431','Argent Crusade - set Quartermaster'),('factions',1119,'qmNpcIds','32540','The Sons of Hodir - set Quartermaster'),('factions',1124,'qmNpcIds','34772','The Sunreavers - set Quartermaster'),('factions',1156,'qmNpcIds','37687','The Ashen Verdict - set Quartermaster'),('factions',1082,'cuFlags','1073741824','REUSE - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('factions',952,'cuFlags','1073741824','Test Faction 3 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('titles',138,'gender','1','Patron - male'),('sounds',15407,'cat','10','UR_Algalon_Summon03 - is not an item pickup'),('shapeshiftforms',1,'displayIdH','8571','Cat Form - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',15,'displayIdH','8571','Creature - Cat - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',5,'displayIdH','2289','Bear Form - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',8,'displayIdH','2289','Dire Bear Form - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',14,'displayIdH','2289','Creature - Bear - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',27,'displayIdH','21244','Flight Form, Epic - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',29,'displayIdH','20872','Flight Form - spellshapeshiftform.dbc missing displayId'),('races',1,'leader','29611','Human - King Varian Wrynn'),('races',1,'factionId','72','Human - Stormwind'),('races',1,'startAreaId','12','Human - Elwynn Forest'),('races',2,'leader','4949','Orc - Thrall'),('races',2,'factionId','76','Orc - Orgrimmar'),('races',2,'startAreaId','14','Orc - Durotar'),('races',3,'leader','2784','Dwarf - King Magni Bronzebeard'),('races',3,'factionId','47','Dwarf - Ironforge'),('races',3,'startAreaId','1','Dwarf - Dun Morogh'),('races',4,'leader','7999','Night Elf - Tyrande Whisperwind'),('races',4,'factionId','69','Night Elf - Darnassus'),('races',4,'startAreaId','141','Night Elf - Teldrassil'),('races',5,'leader','10181','Undead - Lady Sylvanas Windrunner'),('races',5,'factionId','68','Undead - Undercity'),('races',5,'startAreaId','85','Undead - Tirisfal Glades'),('races',6,'leader','3057','Tauren - Cairne Bloodhoof'),('races',6,'factionId','81','Tauren - Thunder Bluff'),('races',6,'startAreaId','215','Tauren - Mulgore'),('races',7,'leader','7937','Gnome - High Tinker Mekkatorque'),('races',7,'factionId','54','Gnome - Gnomeregan Exiles'),('races',7,'startAreaId','1','Gnome - Dun Morogh'),('races',8,'leader','10540','Troll - Vol\'jin'),('races',8,'factionId','530','Troll - Darkspear Trolls'),('races',8,'startAreaId','14','Troll - Durotar'),('races',10,'leader','16802','Blood Elf - Lor\'themar Theron'),('races',10,'factionId','911','Blood Elf - Silvermoon City'),('races',10,'startAreaId','3430','Blood Elf - Eversong Woods'),('races',11,'leader','17468','Draenei - Prophet Velen'),('races',11,'factionId','930','Draenei - Exodar'),('races',11,'startAreaId','3524','Draenei - Azuremyst Isle'),('holidays',62,'iconString','inv_misc_missilelarge_red','Fireworks Spectacular'),('holidays',141,'iconString','calendar_winterveilstart','Feast of Winter Veil'),('holidays',181,'iconString','calendar_noblegardenstart','Noblegarden'),('holidays',201,'iconString','calendar_childrensweekstart','Children\'s Week'),('holidays',283,'iconString','inv_jewelry_necklace_21','Call to Arms: Alterac Valley'),('holidays',284,'iconString','inv_misc_rune_07','Call to Arms: Warsong Gulch'),('holidays',285,'iconString','inv_jewelry_amulet_07','Call to Arms: Arathi Basin'),('holidays',301,'iconString','calendar_fishingextravaganzastart','Stranglethorn Fishing Extravaganza'),('holidays',321,'iconString','calendar_harvestfestivalstart','Harvest Festival'),('holidays',324,'iconString','calendar_hallowsendstart','Hallow\'s End'),('holidays',327,'iconString','calendar_lunarfestivalstart','Lunar Festival'),('holidays',335,'iconString','calendar_loveintheairstart','Love is in the Air'),('holidays',341,'iconString','calendar_midsummerstart','Midsummer Fire Festival'),('holidays',353,'iconString','spell_nature_eyeofthestorm','Call to Arms: Eye of the Storm'),('holidays',372,'iconString','calendar_brewfeststart','Brewfest'),('holidays',374,'iconString','calendar_darkmoonfaireelwynnstart','Darkmoon Faire'),('holidays',375,'iconString','calendar_darkmoonfairemulgorestart','Darkmoon Faire'),('holidays',376,'iconString','calendar_darkmoonfaireterokkarstart','Darkmoon Faire'),('holidays',398,'iconString','calendar_piratesdaystart','Pirates\' Day'),('holidays',400,'iconString','achievement_bg_winsoa','Call to Arms: Strand of the Ancients'),('holidays',404,'iconString','calendar_harvestfestivalstart','Pilgrim\'s Bounty'),('holidays',406,'iconString','achievement_boss_lichking','Wrath of the Lich King Launch'),('holidays',409,'iconString','calendar_dayofthedeadstart','Day of the Dead'),('holidays',420,'iconString','achievement_bg_winwsg','Call to Arms: Isle of Conquest'),('holidays',423,'iconString','calendar_loveintheairstart','Love is in the Air'),('holidays',424,'iconString','calendar_fishingextravaganzastart','Kalu\'ak Fishing Derby'),('holidays',141,'achievementCatOrId','156','Feast of Winter Veil - Category: Feast of Winter Veil'),('holidays',181,'achievementCatOrId','159','Noblegarden - Category: Noblegarden'),('holidays',201,'achievementCatOrId','163','Children\'s Week - Category: Children\'s Week'),('holidays',324,'achievementCatOrId','158','Hallow\'s End - Category: Hallow\'s End'),('holidays',327,'achievementCatOrId','160','Lunar Festival - Category: Lunar Festival'),('holidays',341,'achievementCatOrId','161','Midsummer Fire Festival - Category: Midsummer Fire Festival'),('holidays',372,'achievementCatOrId','162','Brewfest - Category: Brewfest'),('holidays',398,'achievementCatOrId','-3457','Pirates\' Day - Achievement: The Captain\'s Booty'),('holidays',404,'achievementCatOrId','14981','Pilgrim\'s Bounty - Category: Pilgrim\'s Bounty'),('holidays',409,'achievementCatOrId','-3456','Day of the Dead - Achievement: Dead Man\'s Party'),('holidays',423,'achievementCatOrId','187','Love is in the Air - Category: Love is in the Air'),('holidays',324,'bossCreature','23682','Hallow\'s End - Headless Horseman'),('holidays',327,'bossCreature','15467','Lunar Festival - Omen'),('holidays',341,'bossCreature','25740','Midsummer Fire Festival - Ahune'),('holidays',372,'bossCreature','23872','Brewfest - Coren Direbrew'),('holidays',423,'bossCreature','36296','Love is in the Air - Apothecary Hummel'),('skillline',197,'professionMask','512','Tailoring'),('skillline',186,'professionMask','256','Mining'),('skillline',165,'specializations','10656 10658 10660','Leatherworking'),('skillline',165,'recipeSubClass','1','Leatherworking'),('skillline',165,'professionMask','128','Leatherworking'),('skillline',755,'recipeSubClass','10','Jewelcrafting'),('skillline',755,'professionMask','64','Jewelcrafting'),('skillline',129,'recipeSubClass','7','First Aid'),('skillline',129,'professionMask','32','First Aid'),('skillline',202,'specializations','20219 20222','Engineering'),('skillline',202,'recipeSubClass','3','Engineering'),('skillline',202,'professionMask','16','Engineering'),('skillline',333,'recipeSubClass','8','Enchanting'),('skillline',333,'professionMask','8','Enchanting'),('skillline',185,'recipeSubClass','5','Cooking'),('skillline',185,'professionMask','4','Cooking'),('skillline',164,'specializations','9788 9787 17041 17040 17039','Blacksmithing'),('skillline',164,'recipeSubClass','4','Blacksmithing'),('skillline',164,'professionMask','2','Blacksmithing'),('skillline',171,'specializations','28677 28675 28672','Alchemy'),('skillline',171,'recipeSubClass','6','Alchemy'),('skillline',171,'professionMask','1','Alchemy'),('skillline',393,'professionMask','0','Skinning'),('skillline',197,'recipeSubClass','2','Tailoring'),('skillline',197,'specializations','26798 26801 26797','Tailoring'),('skillline',356,'professionMask','1024','Fishing'),('skillline',356,'recipeSubClass','9','Fishing'),('skillline',182,'professionMask','2048','Herbalism'),('skillline',773,'professionMask','4096','Inscription'),('skillline',773,'recipeSubClass','11','Inscription'),('skillline',785,'name_loc0','Pet - Wasp','Pet - Wasp'),('skillline',781,'name_loc2','Familier - diablosaure exotique','Pet - Exotic Devlisaur'),('skillline',758,'name_loc6','Mascota: Evento - Control remoto','Pet - Event - Remote Control'),('skillline',758,'name_loc3','Tier - Ereignis Ferngesteuert','Pet - Event - Remote Control'),('skillline',758,'categoryId','7','Pet - Event - Remote Control - bring in line with other pets'),('skillline',788,'categoryId','7','Pet - Exotic Spirit Beast - bring in line with other pets'),('item',33147,'class','9','Formula: Enchant Cloak - Subtlety - Class: Recipes'),('item',33147,'subClass','8','Formula: Enchant Cloak - Subtlety - Subclass: Enchanting'),('currencies',1,'description_loc0','Text that describes this item can be found here.',''),('currencies',1,'description_loc2','Un texte qui décrit l\'objet figure ici.',''),('currencies',1,'description_loc3','Text, der den Gegenstand beschreibt, wird hier angezeigt.',''),('currencies',1,'description_loc6','Aquí puede encontrarse el texto que describe a este objeto.',''),('currencies',1,'description_loc8','Здесь находится описание предмета.',''),('currencies',61,'description_loc0','Tiffany Cartier\'s shop in Dalaran will gladly accept these tokens for unique jewelcrafting recipes.',''),('currencies',61,'description_loc2','La boutique de Tiffany Kartier, à Dalaran, accepte avec joie ces marques contre des dessins de joaillerie uniques.',''),('currencies',61,'description_loc3','Tiffany Cartiers Geschäft in Dalaran wird diese Symbole im Tausch gegen einzigartige Juweliersrezepte dankend annehmen.',''),('currencies',61,'description_loc4','达拉然的蒂凡妮·卡蒂亚会欣然接受这些代币,并用稀有的珠宝加工图鉴来交换。',''),('currencies',61,'description_loc6','La tienda de Tiffany Cartier en Dalaran cambiará gustosamente estos talismanes por recetas de joyería.',''),('currencies',61,'description_loc8','В магазине Тиффани Картье, что в Даларане, вам с радостью обменяют эти знаки на уникальные ювелирные эскизы.',''),('currencies',81,'description_loc0','Visit special cooking vendors in Dalaran and the capital cities to to purchase unusual cooking recipes, spices, and even a fine hat!',''),('currencies',81,'description_loc2','Rendez visite aux marchands de fournitures de cuisine à Dalaran et dans les autres capitales pour acheter des recettes de cuisine spéciales, des épices, et même une superbe toque !',''),('currencies',81,'description_loc3','Besucht besondere Kochhändler in Dalaran und den Hauptstädten, um ungewöhnliche Kochrezepte, Gewürze und sogar eine großartige Mütze zu kaufen!',''),('currencies',81,'description_loc4','造访达拉然以及各个主城的特殊烹饪供应商,购买罕见的烹饪配方、香料以及大厨的帽子!',''),('currencies',81,'description_loc6','Visita a los vendedores de cocina especiales de Dalaran y de las capitales para comprar recetas de cocina poco frecuentes, especias, ¡e incluso un bonito gorro!',''),('currencies',81,'description_loc8','Посетите торговцев кулинарными товарами в Даларане и других столицах, чтобы приобрести особые кулинарные рецепты, специи и даже головной убор!',''),('currencies',241,'description_loc0','Awarded for valiant acts in the Crusader\'s Coliseum.',''),('currencies',241,'description_loc2','Obtenu en récompense d’actes de bravoure au colisée des Croisés.',''),('currencies',241,'description_loc3','Werden für hehre Taten im Kolosseum der Kreuzfahrer verliehen.',''),('currencies',241,'description_loc4','表彰你在十字军演武场中展示的武勇。',''),('currencies',241,'description_loc6','Otorgado por las hazañas en el Coliseo de los Cruzados.',''),('currencies',241,'description_loc8','За храбрость, проявленную на турнирах Колизея Авангарда.',''),('currencies',181,'description_loc0','If you can read this, you\'ve found a bug. REPORT IT!',''),('currencies',181,'description_loc2','Si vous lisez ceci, c\'est un bug. SIGNALEZ-LE !',''),('currencies',181,'description_loc3','Wenn Ihr das hier lesen könnt, habt Ihr einen Bug gefunden. MELDET IHN!',''),('currencies',181,'description_loc6','Si puedes leer esto, has encontrado un error. ¡Informa!',''),('currencies',181,'description_loc8','Если вы видите это сообщение, это значит, что вы обнаружили ошибку. Сообщите о ней!',''),('currencies',103,'description_loc0','Used to purchase powerful PvP armor and weapons.',''),('currencies',103,'description_loc2','Utilisés pour acheter des armures et armes de JcJ puissantes.',''),('currencies',103,'description_loc3','Können für den Erwerb von mächtigen PVP-Waffen und -Rüstungen verwendet werden.',''),('currencies',103,'description_loc4','竞技场点数是通过在竞技场战斗中获胜而赢得的。你可以消费这些点数来购买强大的奖励品!',''),('currencies',103,'description_loc6','Se utilizan para comprar armas y armaduras de JcJ poderosas.',''),('currencies',103,'description_loc8','За эти очки можно покупать мощное оружие и доспехи для PvP-сражений.',''),('currencies',104,'description_loc0','Used to purchase less-powerful PvP armor and weapons.',''),('currencies',104,'description_loc2','Utilisés pour acheter des armures et armes de JcJ moyennement puissantes.',''),('currencies',104,'description_loc3','Können für den Erwerb von weniger mächtigen PVP-Waffen und -Rüstungen verwendet werden.',''),('currencies',104,'description_loc4','荣誉是通过在PvP战斗中 杀死敌对阵营的成员获得的。你可以使用荣誉点数购买特殊的物品。',''),('currencies',104,'description_loc6','Se utilizan para comprar armas y armaduras de JcJ menos poderosas.',''),('currencies',104,'description_loc8','За эти очки можно покупать не очень мощное оружие и доспехи для PvP-сражений.',''),('currencies',221,'description_loc0','Used to purchase less-powerful armor and weapons.',''),('currencies',221,'description_loc2','Utilisés pour acheter des armures et armes de JcJ moyennement puissantes.',''),('currencies',221,'description_loc3','Können für den Erwerb von weniger mächtigen Waffen und Rüstungen verwendet werden.',''),('currencies',221,'description_loc6','Se utilizan para comprar armas y armaduras menos poderosas.',''),('currencies',221,'description_loc8','За эти очки можно покупать не очень мощное оружие и доспехи.',''),('currencies',341,'description_loc0','Used to purchase powerful PvE armor and weapons.',''),('currencies',341,'description_loc2','Utilisés pour acheter des armures et armes de JcE puissantes.',''),('currencies',341,'description_loc3','Können für den Erwerb von mächtigen PVE-Waffen und -Rüstungen verwendet werden.',''),('currencies',341,'description_loc6','Se utilizan para comprar armas y armaduras de JcE poderosas.',''),('currencies',341,'description_loc8','За эти очки можно покупать мощное оружие и доспехи для PvE-сражений.',''),('spell',9787,'reqSpellId',9787,'Weaponsmith - requires itself'),('spell',9788,'reqSpellId',9788,'Armorsmith - requires itself'),('spell',10656,'reqSpellId',10656,'Dragonscale Leatherworking - requires itself'),('spell',10658,'reqSpellId',10658,'Elemental Leatherworking - requires itself'),('spell',10660,'reqSpellId',10660,'Tribal Leatherworking - requires itself'),('spell',17039,'reqSpellId',17039,'Master Swordsmith - requires itself'),('spell',17040,'reqSpellId',17040,'Master Hammersmith - requires itself'),('spell',17041,'reqSpellId',17041,'Master Axesmith - requires itself'),('spell',20219,'reqSpellId',20219,'Gnomish Engineer - requires itself'),('spell',20222,'reqSpellId',20222,'Goblin Engineer - requires itself'),('spell',26797,'reqSpellId',26797,'Spellfire Tailoring - requires itself'),('spell',26798,'reqSpellId',26798,'Mooncloth Tailoring - requires itself'),('spell',26801,'reqSpellId',26801,'Shadoweave Tailoring - requires itself'),('spell',379,'cuFLags',1073741824,'Earth Shield - hide'),('spell',17567,'cuFLags',1073741824,'Summon Blood Parrot - hide'),('spell',19483,'cuFLags',1073741824,'Immolation - hide'),('spell',20154,'cuFLags',1073741824,'Seal of Righteousness - hide'),('spell',21169,'cuFLags',1073741824,'Reincarnation - hide'),('spell',22845,'cuFLags',1073741824,'Frenzied Regeneration - hide'),('spell',23885,'cuFLags',1073741824,'Bloodthirst - hide'),('spell',27813,'cuFLags',1073741824,'Blessed Recovery - hide'),('spell',27817,'cuFLags',1073741824,'Blessed Recovery - hide'),('spell',27818,'cuFLags',1073741824,'Blessed Recovery - hide'),('spell',29442,'cuFLags',1073741824,'Magic Absorption - hide'),('spell',29841,'cuFLags',1073741824,'Second Wind - hide'),('spell',29842,'cuFLags',1073741824,'Second Wind - hide'),('spell',29886,'cuFLags',1073741824,'Create Soulwell - hide'),('spell',30708,'cuFLags',1073741824,'Totem of Wrath - hide'),('spell',30874,'cuFLags',1073741824,'Gift of the Water Spirit - hide'),('spell',31643,'cuFLags',1073741824,'Blazing Speed - hide'),('spell',32841,'cuFLags',1073741824,'Mass Resurrection - hide'),('spell',34919,'cuFLags',1073741824,'Vampiric Touch - hide'),('spell',44450,'cuFLags',1073741824,'Burnout - hide'),('spell',47633,'cuFLags',1073741824,'Death Coil - hide'),('spell',48954,'cuFLags',1073741824,'Swift Zhevra - hide'),('spell',49575,'cuFLags',1073741824,'Death Grip - hide'),('spell',50536,'cuFLags',1073741824,'Unholy Blight - hide'),('spell',52374,'cuFLags',1073741824,'Blood Strike - hide'),('spell',56816,'cuFLags',1073741824,'Rune Strike - hide'),('spell',58427,'cuFLags',1073741824,'Overkill - hide'),('spell',58889,'cuFLags',1073741824,'Create Soulwell - hide'),('spell',64380,'cuFLags',1073741824,'Shattering Throw - hide'),('spell',66122,'cuFLags',1073741824,'Magic Rooster - hide'),('spell',66123,'cuFLags',1073741824,'Magic Rooster - hide'),('spell',66124,'cuFLags',1073741824,'Magic Rooster - hide'),('spell',66175,'cuFLags',1073741824,'Macabre Marionette - hide'),('spell',54910,'cuFLags',1073741824,'Glyph of the Red Lynx - hide unused glyph'),('spell',57231,'cuFLags',1073741824,'Death Knight Glyph 25 - hide unused glyph'),('spell',58166,'cuFLags',1073741824,'Glyph of the Forest Lynx - hide unused glyph'),('spell',58239,'cuFLags',1073741824,'Glyph of the Penguin - hide unused glyph'),('spell',58240,'cuFLags',1073741824,'Glyph of the Bear Cub - hide unused glyph'),('spell',58261,'cuFLags',1073741824,'Glyph of the Arctic Wolf - hide unused glyph'),('spell',58262,'cuFLags',1073741824,'Glyph of the Black Wolf - hide unused glyph'),('spell',60460,'cuFLags',1073741824,'Glyph of Raise Dead - hide unused glyph'),('spell',54910,'skillLine1',0,'Glyph of the Red Lynx - hide unused glyph'),('spell',57231,'skillLine1',0,'Death Knight Glyph 25 - hide unused glyph'),('spell',58166,'skillLine1',0,'Glyph of the Forest Lynx - hide unused glyph'),('spell',58239,'skillLine1',0,'Glyph of the Penguin - hide unused glyph'),('spell',58240,'skillLine1',0,'Glyph of the Bear Cub - hide unused glyph'),('spell',58261,'skillLine1',0,'Glyph of the Arctic Wolf - hide unused glyph'),('spell',58262,'skillLine1',0,'Glyph of the Black Wolf - hide unused glyph'),('spell',60460,'skillLine1',0,'Glyph of Raise Dead - hide unused glyph'),('spell',54910,'iconIdAlt',0,'Glyph of the Red Lynx - hide unused glyph'),('spell',57231,'iconIdAlt',0,'Death Knight Glyph 25 - hide unused glyph'),('spell',58166,'iconIdAlt',0,'Glyph of the Forest Lynx - hide unused glyph'),('spell',58239,'iconIdAlt',0,'Glyph of the Penguin - hide unused glyph'),('spell',58240,'iconIdAlt',0,'Glyph of the Bear Cub - hide unused glyph'),('spell',58261,'iconIdAlt',0,'Glyph of the Arctic Wolf - hide unused glyph'),('spell',58262,'iconIdAlt',0,'Glyph of the Black Wolf - hide unused glyph'),('spell',60460,'iconIdAlt',0,'Glyph of Raise Dead - hide unused glyph'),('quests',9572,'zoneOrSort','3562','Weaken the Ramparts - category Hellfire Citadel -> Hellfire Ramparts'),('quests',9575,'zoneOrSort','3562','Weaken the Ramparts - category Hellfire Citadel -> Hellfire Ramparts'),('quests',11354,'zoneOrSort','3562','Wanted: Nazan\'s Riding Crop - category Hellfire Citadel -> Hellfire Ramparts'),('quests',9589,'zoneOrSort','3713','The Blood is Life - category Hellfire Citadel -> Blood Furnace'),('quests',9590,'zoneOrSort','3713','The Blood is Life - category Hellfire Citadel -> Blood Furnace'),('quests',9607,'zoneOrSort','3713','Heart of Rage - category Hellfire Citadel -> Blood Furnace'),('quests',9608,'zoneOrSort','3713','Heart of Rage - category Hellfire Citadel -> Blood Furnace'),('quests',11362,'zoneOrSort','3713','Wanted: Keli\'dan\'s Feathered Stave - category Hellfire Citadel -> Blood Furnace'),('quests',9492,'zoneOrSort','3714','Turning the Tide - category Hellfire Citadel -> Shattered Halls'),('quests',9493,'zoneOrSort','3714','Pride of the Fel Horde - category Hellfire Citadel -> Shattered Halls'),('quests',9494,'zoneOrSort','3714','Fel Embers - category Hellfire Citadel -> Shattered Halls'),('quests',9495,'zoneOrSort','3714','The Will of the Warchief - category Hellfire Citadel -> Shattered Halls'),('quests',9496,'zoneOrSort','3714','Pride of the Fel Horde - category Hellfire Citadel -> Shattered Halls'),('quests',9497,'zoneOrSort','3714','Emblem of the Fel Horde - category Hellfire Citadel -> Shattered Halls'),('quests',9524,'zoneOrSort','3714','Imprisoned in the Citadel - category Hellfire Citadel -> Shattered Halls'),('quests',9525,'zoneOrSort','3714','Imprisoned in the Citadel - category Hellfire Citadel -> Shattered Halls'),('quests',11363,'zoneOrSort','3714','Wanted: Bladefist\'s Seal - category Hellfire Citadel -> Shattered Halls'),('quests',11364,'zoneOrSort','3714','Wanted: Shattered Hand Centurions - category Hellfire Citadel -> Shattered Halls');
+INSERT INTO `aowow_setup_custom_data` VALUES ('zones',2257,'cuFlags','0','Deeprun Tram - make visible'),('zones',2257,'category','0','Deeprun Tram - Category: Eastern Kingdoms'),('zones',2257,'type','1','Deeprun Tram - Type: Transit'),('zones',3698,'expansion','1','Nagrand Arena - Addon: BC'),('zones',3702,'expansion','1','Blades Edge Arena - Addon: BC'),('zones',3968,'expansion','1','Ruins of Lordaeron Arena - Addon: BC'),('zones',4378,'expansion','1','Dalaran Arena - Addon: WotLK'),('zones',4406,'expansion','1','Ring of Valor Arena - Addon: WotLK'),('zones',2597,'maxPlayer','40','Alterac Valey - Players: 40 [battlemasterlist.dbc: 5]'),('zones',4710,'maxPlayer','40','Isle of Conquest - Players: 40 [battlemasterlist.dbc: 5]'),('zones',4893,'cuFlags','1073741824','The Frost Queen\'s Lair - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4894,'cuFlags','1073741824','Putricide\'s Laboratory [..] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('achievement',1956,'itemExtra','44738','Higher Learning - item rewarded through gossip'),('zones',4895,'cuFlags','1073741824','The Crimson Hall - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('titles',137,'gender','2','Matron - female'),('zones',4896,'cuFlags','1073741824','The Frozen Throne - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4897,'cuFlags','1073741824','The Sanctum of Blood - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4076,'cuFlags','1073741824','Reuse Me 7 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',207,'cuFlags','1073741824','The Great Sea - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',208,'cuFlags','1073741824','Unused Ironcladcove - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',2817,'levelMin','74','Crystalsong Forest - missing lfgDungeons entry'),('zones',1417,'cuFlags','1073741824','Sunken Temple [extra area on map 109] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',22,'cuFlags','1073741824','Programmer Isle - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',151,'cuFlags','1073741824','Designer Island - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',3948,'cuFlags','1073741824','Brian and Pat Test - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',4019,'cuFlags','1073741824','Development Land - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',3605,'cuFlags','1073741824','Hyjal Past [extra area on map 560] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',3535,'cuFlags','1073741824','Hellfire Citadel [extra area on map 540] - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('zones',41,'levelMin','50','Deadwind Pass - missing lfgDungeons entry'),('zones',41,'levelMax','60','Deadwind Pass - missing lfgDungeons entry'),('zones',2257,'levelMin','1','Deeprun Tram - missing lfgDungeons entry'),('zones',2257,'levelMax','80','Deeprun Tram - missing lfgDungeons entry'),('zones',4298,'category','0','Plaguelands: The Scarlet Enclave - Parent: Eastern Kingdoms'),('zones',4298,'levelMin','55','Plaguelands: The Scarlet Enclave - missing lfgDungeons entry'),('zones',4298,'levelMax','58','Plaguelands: The Scarlet Enclave - missing lfgDungeons entry'),('zones',493,'levelMin','15','Moonglade - missing lfgDungeons entry'),('zones',493,'levelMax','60','Moonglade - missing lfgDungeons entry'),('zones',2817,'levelMax','76','Crystalsong Forest - missing lfgDungeons entry'),('zones',4742,'levelMin','77','Hrothgar\'s Landing - missing lfgDungeons entry'),('zones',4742,'levelMax','80','Hrothgar\'s Landing - missing lfgDungeons entry'),('classes',1,'roles','10','Warrior - rngDPS'),('classes',2,'roles','11','Paladin - mleDPS + Tank + Heal'),('classes',3,'roles','4','Hunter - rngDPS'),('classes',4,'roles','2','Rogue - mleDPS'),('classes',5,'roles','5','Priest - rngDPS + Heal'),('classes',6,'roles','10','Death Knight - mleDPS + Tank'),('classes',7,'roles','7','Shaman - mleDPS + rngDPS + Heal'),('classes',8,'roles','4','Mage - rngDPS'),('classes',9,'roles','4','Warlock - rngDPS'),('classes',11,'roles','15','Druid - mleDPS + Tank + Heal + rngDPS'),('currencies',103,'cap','10000','Arena Points - cap'),('currencies',104,'cap','75000','Honor Points - cap'),('currencies',1,'cuFlags','1073741824','Currency Token Test Token 1 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',2,'cuFlags','1073741824','Currency Token Test Token 2 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',4,'cuFlags','1073741824','Currency Token Test Token 3 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',22,'cuFlags','1073741824','Birmingham Test Item 3 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',141,'cuFlags','1073741824','zzzOLDDaily Quest Faction Token - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('currencies',1,'category','3','Currency Token Test Token 1 - category: unused'),('currencies',2,'category','3','Currency Token Test Token 2 - category: unused'),('currencies',4,'category','3','Currency Token Test Token 3 - category: unused'),('currencies',22,'category','3','Birmingham Test Item 3 - category: unused'),('currencies',141,'category','3','zzzOLDDaily Quest Faction Token - category: unused'),('factions',68,'qmNpcIds','33555','Undercity - set Quartermaster'),('factions',47,'qmNpcIds','33310','Ironforge - set Quartermaster'),('factions',69,'qmNpcIds','33653','Darnassus - set Quartermaster'),('factions',72,'qmNpcIds','33307','Stormwind - set Quartermaster'),('factions',76,'qmNpcIds','33553','Orgrimmar - set Quartermaster'),('factions',81,'qmNpcIds','33556','Thunder Bluff - set Quartermaster'),('factions',922,'qmNpcIds','16528','Tranquillien - set Quartermaster'),('factions',930,'qmNpcIds','33657','Exodar - set Quartermaster'),('factions',932,'qmNpcIds','19321','The Aldor - set Quartermaster'),('factions',933,'qmNpcIds','20242 23007','The Consortium - set Quartermaster'),('factions',935,'qmNpcIds','21432','The Sha\'tar - set Quartermaster'),('factions',941,'qmNpcIds','20241','The Mag\'har - set Quartermaster'),('factions',942,'qmNpcIds','17904','Cenarion Expedition - set Quartermaster'),('factions',946,'qmNpcIds','17657','Honor Hold - set Quartermaster'),('factions',947,'qmNpcIds','17585','Thrallmar - set Quartermaster'),('factions',970,'qmNpcIds','18382','Sporeggar - set Quartermaster'),('factions',978,'qmNpcIds','20240','Kurenai - set Quartermaster'),('factions',989,'qmNpcIds','21643','Keepers of Time - set Quartermaster'),('factions',1011,'qmNpcIds','21655','Lower City - set Quartermaster'),('factions',1012,'qmNpcIds','23159','Ashtongue Deathsworn - set Quartermaster'),('factions',1037,'qmNpcIds','32773 32564','Alliance Vanguard - set Quartermaster'),('factions',1038,'qmNpcIds','23428','Ogri\'la - set Quartermaster'),('factions',1052,'qmNpcIds','32774 32565','Horde Expedition - set Quartermaster'),('factions',1073,'qmNpcIds','31916 32763','The Kalu\'ak - set Quartermaster'),('factions',1090,'qmNpcIds','32287','Kirin Tor - set Quartermaster'),('factions',1091,'qmNpcIds','32533','The Wyrmrest Accord - set Quartermaster'),('factions',1094,'qmNpcIds','34881','The Silver Covenant - set Quartermaster'),('factions',1105,'qmNpcIds','31910','The Oracles - set Quartermaster'),('factions',1106,'qmNpcIds','30431','Argent Crusade - set Quartermaster'),('factions',1119,'qmNpcIds','32540','The Sons of Hodir - set Quartermaster'),('factions',1124,'qmNpcIds','34772','The Sunreavers - set Quartermaster'),('factions',1156,'qmNpcIds','37687','The Ashen Verdict - set Quartermaster'),('factions',1082,'cuFlags','1073741824','REUSE - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('factions',952,'cuFlags','1073741824','Test Faction 3 - set: CUSTOM_EXCLUDE_FOR_LISTVIEW'),('titles',138,'gender','1','Patron - male'),('sounds',15407,'cat','10','UR_Algalon_Summon03 - is not an item pickup'),('shapeshiftforms',1,'displayIdH','8571','Cat Form - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',15,'displayIdH','8571','Creature - Cat - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',5,'displayIdH','2289','Bear Form - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',8,'displayIdH','2289','Dire Bear Form - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',14,'displayIdH','2289','Creature - Bear - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',27,'displayIdH','21244','Flight Form, Epic - spellshapeshiftform.dbc missing displayId'),('shapeshiftforms',29,'displayIdH','20872','Flight Form - spellshapeshiftform.dbc missing displayId'),('races',1,'leader','29611','Human - King Varian Wrynn'),('races',1,'factionId','72','Human - Stormwind'),('races',1,'startAreaId','12','Human - Elwynn Forest'),('races',2,'leader','4949','Orc - Thrall'),('races',2,'factionId','76','Orc - Orgrimmar'),('races',2,'startAreaId','14','Orc - Durotar'),('races',3,'leader','2784','Dwarf - King Magni Bronzebeard'),('races',3,'factionId','47','Dwarf - Ironforge'),('races',3,'startAreaId','1','Dwarf - Dun Morogh'),('races',4,'leader','7999','Night Elf - Tyrande Whisperwind'),('races',4,'factionId','69','Night Elf - Darnassus'),('races',4,'startAreaId','141','Night Elf - Teldrassil'),('races',5,'leader','10181','Undead - Lady Sylvanas Windrunner'),('races',5,'factionId','68','Undead - Undercity'),('races',5,'startAreaId','85','Undead - Tirisfal Glades'),('races',6,'leader','3057','Tauren - Cairne Bloodhoof'),('races',6,'factionId','81','Tauren - Thunder Bluff'),('races',6,'startAreaId','215','Tauren - Mulgore'),('races',7,'leader','7937','Gnome - High Tinker Mekkatorque'),('races',7,'factionId','54','Gnome - Gnomeregan Exiles'),('races',7,'startAreaId','1','Gnome - Dun Morogh'),('races',8,'leader','10540','Troll - Vol\'jin'),('races',8,'factionId','530','Troll - Darkspear Trolls'),('races',8,'startAreaId','14','Troll - Durotar'),('races',10,'leader','16802','Blood Elf - Lor\'themar Theron'),('races',10,'factionId','911','Blood Elf - Silvermoon City'),('races',10,'startAreaId','3430','Blood Elf - Eversong Woods'),('races',11,'leader','17468','Draenei - Prophet Velen'),('races',11,'factionId','930','Draenei - Exodar'),('races',11,'startAreaId','3524','Draenei - Azuremyst Isle'),('holidays',62,'iconString','inv_misc_missilelarge_red','Fireworks Spectacular'),('holidays',141,'iconString','calendar_winterveilstart','Feast of Winter Veil'),('holidays',181,'iconString','calendar_noblegardenstart','Noblegarden'),('holidays',201,'iconString','calendar_childrensweekstart','Children\'s Week'),('holidays',283,'iconString','inv_jewelry_necklace_21','Call to Arms: Alterac Valley'),('holidays',284,'iconString','inv_misc_rune_07','Call to Arms: Warsong Gulch'),('holidays',285,'iconString','inv_jewelry_amulet_07','Call to Arms: Arathi Basin'),('holidays',301,'iconString','calendar_fishingextravaganzastart','Stranglethorn Fishing Extravaganza'),('holidays',321,'iconString','calendar_harvestfestivalstart','Harvest Festival'),('holidays',324,'iconString','calendar_hallowsendstart','Hallow\'s End'),('holidays',327,'iconString','calendar_lunarfestivalstart','Lunar Festival'),('holidays',335,'iconString','calendar_loveintheairstart','Love is in the Air'),('holidays',341,'iconString','calendar_midsummerstart','Midsummer Fire Festival'),('holidays',353,'iconString','spell_nature_eyeofthestorm','Call to Arms: Eye of the Storm'),('holidays',372,'iconString','calendar_brewfeststart','Brewfest'),('holidays',374,'iconString','calendar_darkmoonfaireelwynnstart','Darkmoon Faire'),('holidays',375,'iconString','calendar_darkmoonfairemulgorestart','Darkmoon Faire'),('holidays',376,'iconString','calendar_darkmoonfaireterokkarstart','Darkmoon Faire'),('holidays',398,'iconString','calendar_piratesdaystart','Pirates\' Day'),('holidays',400,'iconString','achievement_bg_winsoa','Call to Arms: Strand of the Ancients'),('holidays',404,'iconString','calendar_harvestfestivalstart','Pilgrim\'s Bounty'),('holidays',406,'iconString','achievement_boss_lichking','Wrath of the Lich King Launch'),('holidays',409,'iconString','calendar_dayofthedeadstart','Day of the Dead'),('holidays',420,'iconString','achievement_bg_winwsg','Call to Arms: Isle of Conquest'),('holidays',423,'iconString','calendar_loveintheairstart','Love is in the Air'),('holidays',424,'iconString','calendar_fishingextravaganzastart','Kalu\'ak Fishing Derby'),('holidays',141,'achievementCatOrId','156','Feast of Winter Veil - Category: Feast of Winter Veil'),('holidays',181,'achievementCatOrId','159','Noblegarden - Category: Noblegarden'),('holidays',201,'achievementCatOrId','163','Children\'s Week - Category: Children\'s Week'),('holidays',324,'achievementCatOrId','158','Hallow\'s End - Category: Hallow\'s End'),('holidays',327,'achievementCatOrId','160','Lunar Festival - Category: Lunar Festival'),('holidays',341,'achievementCatOrId','161','Midsummer Fire Festival - Category: Midsummer Fire Festival'),('holidays',372,'achievementCatOrId','162','Brewfest - Category: Brewfest'),('holidays',398,'achievementCatOrId','-3457','Pirates\' Day - Achievement: The Captain\'s Booty'),('holidays',404,'achievementCatOrId','14981','Pilgrim\'s Bounty - Category: Pilgrim\'s Bounty'),('holidays',409,'achievementCatOrId','-3456','Day of the Dead - Achievement: Dead Man\'s Party'),('holidays',423,'achievementCatOrId','187','Love is in the Air - Category: Love is in the Air'),('holidays',324,'bossCreature','23682','Hallow\'s End - Headless Horseman'),('holidays',327,'bossCreature','15467','Lunar Festival - Omen'),('holidays',341,'bossCreature','25740','Midsummer Fire Festival - Ahune'),('holidays',372,'bossCreature','23872','Brewfest - Coren Direbrew'),('holidays',423,'bossCreature','36296','Love is in the Air - Apothecary Hummel'),('skillline',197,'professionMask','512','Tailoring'),('skillline',186,'professionMask','256','Mining'),('skillline',165,'specializations','10656 10658 10660','Leatherworking'),('skillline',165,'recipeSubClass','1','Leatherworking'),('skillline',165,'professionMask','128','Leatherworking'),('skillline',755,'recipeSubClass','10','Jewelcrafting'),('skillline',755,'professionMask','64','Jewelcrafting'),('skillline',129,'recipeSubClass','7','First Aid'),('skillline',129,'professionMask','32','First Aid'),('skillline',202,'specializations','20219 20222','Engineering'),('skillline',202,'recipeSubClass','3','Engineering'),('skillline',202,'professionMask','16','Engineering'),('skillline',333,'recipeSubClass','8','Enchanting'),('skillline',333,'professionMask','8','Enchanting'),('skillline',185,'recipeSubClass','5','Cooking'),('skillline',185,'professionMask','4','Cooking'),('skillline',164,'specializations','9788 9787 17041 17040 17039','Blacksmithing'),('skillline',164,'recipeSubClass','4','Blacksmithing'),('skillline',164,'professionMask','2','Blacksmithing'),('skillline',171,'specializations','28677 28675 28672','Alchemy'),('skillline',171,'recipeSubClass','6','Alchemy'),('skillline',171,'professionMask','1','Alchemy'),('skillline',393,'professionMask','0','Skinning'),('skillline',197,'recipeSubClass','2','Tailoring'),('skillline',197,'specializations','26798 26801 26797','Tailoring'),('skillline',356,'professionMask','1024','Fishing'),('skillline',356,'recipeSubClass','9','Fishing'),('skillline',182,'professionMask','2048','Herbalism'),('skillline',773,'professionMask','4096','Inscription'),('skillline',773,'recipeSubClass','11','Inscription'),('skillline',785,'name_loc0','Pet - Wasp','Pet - Wasp'),('skillline',781,'name_loc2','Familier - diablosaure exotique','Pet - Exotic Devlisaur'),('skillline',758,'name_loc6','Mascota: Evento - Control remoto','Pet - Event - Remote Control'),('skillline',758,'name_loc3','Tier - Ereignis Ferngesteuert','Pet - Event - Remote Control'),('skillline',758,'categoryId','7','Pet - Event - Remote Control - bring in line with other pets'),('skillline',788,'categoryId','7','Pet - Exotic Spirit Beast - bring in line with other pets'),('item',33147,'class','9','Formula: Enchant Cloak - Subtlety - Class: Recipes'),('item',33147,'subClass','8','Formula: Enchant Cloak - Subtlety - Subclass: Enchanting'),('currencies',1,'description_loc0','Text that describes this item can be found here.',''),('currencies',1,'description_loc2','Un texte qui décrit l\'objet figure ici.',''),('currencies',1,'description_loc3','Text, der den Gegenstand beschreibt, wird hier angezeigt.',''),('currencies',1,'description_loc6','Aquí puede encontrarse el texto que describe a este objeto.',''),('currencies',1,'description_loc8','Здесь находится описание предмета.',''),('currencies',61,'description_loc0','Tiffany Cartier\'s shop in Dalaran will gladly accept these tokens for unique jewelcrafting recipes.',''),('currencies',61,'description_loc2','La boutique de Tiffany Kartier, à Dalaran, accepte avec joie ces marques contre des dessins de joaillerie uniques.',''),('currencies',61,'description_loc3','Tiffany Cartiers Geschäft in Dalaran wird diese Symbole im Tausch gegen einzigartige Juweliersrezepte dankend annehmen.',''),('currencies',61,'description_loc4','达拉然的蒂凡妮·卡蒂亚会欣然接受这些代币,并用稀有的珠宝加工图鉴来交换。',''),('currencies',61,'description_loc6','La tienda de Tiffany Cartier en Dalaran cambiará gustosamente estos talismanes por recetas de joyería.',''),('currencies',61,'description_loc8','В магазине Тиффани Картье, что в Даларане, вам с радостью обменяют эти знаки на уникальные ювелирные эскизы.',''),('currencies',81,'description_loc0','Visit special cooking vendors in Dalaran and the capital cities to to purchase unusual cooking recipes, spices, and even a fine hat!',''),('currencies',81,'description_loc2','Rendez visite aux marchands de fournitures de cuisine à Dalaran et dans les autres capitales pour acheter des recettes de cuisine spéciales, des épices, et même une superbe toque !',''),('currencies',81,'description_loc3','Besucht besondere Kochhändler in Dalaran und den Hauptstädten, um ungewöhnliche Kochrezepte, Gewürze und sogar eine großartige Mütze zu kaufen!',''),('currencies',81,'description_loc4','造访达拉然以及各个主城的特殊烹饪供应商,购买罕见的烹饪配方、香料以及大厨的帽子!',''),('currencies',81,'description_loc6','Visita a los vendedores de cocina especiales de Dalaran y de las capitales para comprar recetas de cocina poco frecuentes, especias, ¡e incluso un bonito gorro!',''),('currencies',81,'description_loc8','Посетите торговцев кулинарными товарами в Даларане и других столицах, чтобы приобрести особые кулинарные рецепты, специи и даже головной убор!',''),('currencies',241,'description_loc0','Awarded for valiant acts in the Crusader\'s Coliseum.',''),('currencies',241,'description_loc2','Obtenu en récompense d’actes de bravoure au colisée des Croisés.',''),('currencies',241,'description_loc3','Werden für hehre Taten im Kolosseum der Kreuzfahrer verliehen.',''),('currencies',241,'description_loc4','表彰你在十字军演武场中展示的武勇。',''),('currencies',241,'description_loc6','Otorgado por las hazañas en el Coliseo de los Cruzados.',''),('currencies',241,'description_loc8','За храбрость, проявленную на турнирах Колизея Авангарда.',''),('currencies',181,'description_loc0','If you can read this, you\'ve found a bug. REPORT IT!',''),('currencies',181,'description_loc2','Si vous lisez ceci, c\'est un bug. SIGNALEZ-LE !',''),('currencies',181,'description_loc3','Wenn Ihr das hier lesen könnt, habt Ihr einen Bug gefunden. MELDET IHN!',''),('currencies',181,'description_loc6','Si puedes leer esto, has encontrado un error. ¡Informa!',''),('currencies',181,'description_loc8','Если вы видите это сообщение, это значит, что вы обнаружили ошибку. Сообщите о ней!',''),('currencies',103,'description_loc0','Used to purchase powerful PvP armor and weapons.',''),('currencies',103,'description_loc2','Utilisés pour acheter des armures et armes de JcJ puissantes.',''),('currencies',103,'description_loc3','Können für den Erwerb von mächtigen PVP-Waffen und -Rüstungen verwendet werden.',''),('currencies',103,'description_loc4','竞技场点数是通过在竞技场战斗中获胜而赢得的。你可以消费这些点数来购买强大的奖励品!',''),('currencies',103,'description_loc6','Se utilizan para comprar armas y armaduras de JcJ poderosas.',''),('currencies',103,'description_loc8','За эти очки можно покупать мощное оружие и доспехи для PvP-сражений.',''),('currencies',104,'description_loc0','Used to purchase less-powerful PvP armor and weapons.',''),('currencies',104,'description_loc2','Utilisés pour acheter des armures et armes de JcJ moyennement puissantes.',''),('currencies',104,'description_loc3','Können für den Erwerb von weniger mächtigen PVP-Waffen und -Rüstungen verwendet werden.',''),('currencies',104,'description_loc4','荣誉是通过在PvP战斗中 杀死敌对阵营的成员获得的。你可以使用荣誉点数购买特殊的物品。',''),('currencies',104,'description_loc6','Se utilizan para comprar armas y armaduras de JcJ menos poderosas.',''),('currencies',104,'description_loc8','За эти очки можно покупать не очень мощное оружие и доспехи для PvP-сражений.',''),('currencies',221,'description_loc0','Used to purchase less-powerful armor and weapons.',''),('currencies',221,'description_loc2','Utilisés pour acheter des armures et armes de JcJ moyennement puissantes.',''),('currencies',221,'description_loc3','Können für den Erwerb von weniger mächtigen Waffen und Rüstungen verwendet werden.',''),('currencies',221,'description_loc6','Se utilizan para comprar armas y armaduras menos poderosas.',''),('currencies',221,'description_loc8','За эти очки можно покупать не очень мощное оружие и доспехи.',''),('currencies',341,'description_loc0','Used to purchase powerful PvE armor and weapons.',''),('currencies',341,'description_loc2','Utilisés pour acheter des armures et armes de JcE puissantes.',''),('currencies',341,'description_loc3','Können für den Erwerb von mächtigen PVE-Waffen und -Rüstungen verwendet werden.',''),('currencies',341,'description_loc6','Se utilizan para comprar armas y armaduras de JcE poderosas.',''),('currencies',341,'description_loc8','За эти очки можно покупать мощное оружие и доспехи для PvE-сражений.',''),('spell',9787,'reqSpellId',9787,'Weaponsmith - requires itself'),('spell',9788,'reqSpellId',9788,'Armorsmith - requires itself'),('spell',10656,'reqSpellId',10656,'Dragonscale Leatherworking - requires itself'),('spell',10658,'reqSpellId',10658,'Elemental Leatherworking - requires itself'),('spell',10660,'reqSpellId',10660,'Tribal Leatherworking - requires itself'),('spell',17039,'reqSpellId',17039,'Master Swordsmith - requires itself'),('spell',17040,'reqSpellId',17040,'Master Hammersmith - requires itself'),('spell',17041,'reqSpellId',17041,'Master Axesmith - requires itself'),('spell',20219,'reqSpellId',20219,'Gnomish Engineer - requires itself'),('spell',20222,'reqSpellId',20222,'Goblin Engineer - requires itself'),('spell',26797,'reqSpellId',26797,'Spellfire Tailoring - requires itself'),('spell',26798,'reqSpellId',26798,'Mooncloth Tailoring - requires itself'),('spell',26801,'reqSpellId',26801,'Shadoweave Tailoring - requires itself'),('spell',379,'cuFLags',1073741824,'Earth Shield - hide'),('spell',17567,'cuFLags',1073741824,'Summon Blood Parrot - hide'),('spell',19483,'cuFLags',1073741824,'Immolation - hide'),('spell',20154,'cuFLags',1073741824,'Seal of Righteousness - hide'),('spell',21169,'cuFLags',1073741824,'Reincarnation - hide'),('spell',22845,'cuFLags',1073741824,'Frenzied Regeneration - hide'),('spell',23885,'cuFLags',1073741824,'Bloodthirst - hide'),('spell',27813,'cuFLags',1073741824,'Blessed Recovery - hide'),('spell',27817,'cuFLags',1073741824,'Blessed Recovery - hide'),('spell',27818,'cuFLags',1073741824,'Blessed Recovery - hide'),('spell',29442,'cuFLags',1073741824,'Magic Absorption - hide'),('spell',29841,'cuFLags',1073741824,'Second Wind - hide'),('spell',29842,'cuFLags',1073741824,'Second Wind - hide'),('spell',29886,'cuFLags',1073741824,'Create Soulwell - hide'),('spell',30708,'cuFLags',1073741824,'Totem of Wrath - hide'),('spell',30874,'cuFLags',1073741824,'Gift of the Water Spirit - hide'),('spell',31643,'cuFLags',1073741824,'Blazing Speed - hide'),('spell',32841,'cuFLags',1073741824,'Mass Resurrection - hide'),('spell',34919,'cuFLags',1073741824,'Vampiric Touch - hide'),('spell',44450,'cuFLags',1073741824,'Burnout - hide'),('spell',47633,'cuFLags',1073741824,'Death Coil - hide'),('spell',48954,'cuFLags',1073741824,'Swift Zhevra - hide'),('spell',49575,'cuFLags',1073741824,'Death Grip - hide'),('spell',50536,'cuFLags',1073741824,'Unholy Blight - hide'),('spell',52374,'cuFLags',1073741824,'Blood Strike - hide'),('spell',56816,'cuFLags',1073741824,'Rune Strike - hide'),('spell',58427,'cuFLags',1073741824,'Overkill - hide'),('spell',58889,'cuFLags',1073741824,'Create Soulwell - hide'),('spell',64380,'cuFLags',1073741824,'Shattering Throw - hide'),('spell',66122,'cuFLags',1073741824,'Magic Rooster - hide'),('spell',66123,'cuFLags',1073741824,'Magic Rooster - hide'),('spell',66124,'cuFLags',1073741824,'Magic Rooster - hide'),('spell',66175,'cuFLags',1073741824,'Macabre Marionette - hide'),('spell',54910,'cuFLags',1073741824,'Glyph of the Red Lynx - hide unused glyph'),('spell',57231,'cuFLags',1073741824,'Death Knight Glyph 25 - hide unused glyph'),('spell',58166,'cuFLags',1073741824,'Glyph of the Forest Lynx - hide unused glyph'),('spell',58239,'cuFLags',1073741824,'Glyph of the Penguin - hide unused glyph'),('spell',58240,'cuFLags',1073741824,'Glyph of the Bear Cub - hide unused glyph'),('spell',58261,'cuFLags',1073741824,'Glyph of the Arctic Wolf - hide unused glyph'),('spell',58262,'cuFLags',1073741824,'Glyph of the Black Wolf - hide unused glyph'),('spell',60460,'cuFLags',1073741824,'Glyph of Raise Dead - hide unused glyph'),('spell',54910,'skillLine1',0,'Glyph of the Red Lynx - hide unused glyph'),('spell',57231,'skillLine1',0,'Death Knight Glyph 25 - hide unused glyph'),('spell',58166,'skillLine1',0,'Glyph of the Forest Lynx - hide unused glyph'),('spell',58239,'skillLine1',0,'Glyph of the Penguin - hide unused glyph'),('spell',58240,'skillLine1',0,'Glyph of the Bear Cub - hide unused glyph'),('spell',58261,'skillLine1',0,'Glyph of the Arctic Wolf - hide unused glyph'),('spell',58262,'skillLine1',0,'Glyph of the Black Wolf - hide unused glyph'),('spell',60460,'skillLine1',0,'Glyph of Raise Dead - hide unused glyph'),('spell',54910,'iconIdAlt',0,'Glyph of the Red Lynx - hide unused glyph'),('spell',57231,'iconIdAlt',0,'Death Knight Glyph 25 - hide unused glyph'),('spell',58166,'iconIdAlt',0,'Glyph of the Forest Lynx - hide unused glyph'),('spell',58239,'iconIdAlt',0,'Glyph of the Penguin - hide unused glyph'),('spell',58240,'iconIdAlt',0,'Glyph of the Bear Cub - hide unused glyph'),('spell',58261,'iconIdAlt',0,'Glyph of the Arctic Wolf - hide unused glyph'),('spell',58262,'iconIdAlt',0,'Glyph of the Black Wolf - hide unused glyph'),('spell',60460,'iconIdAlt',0,'Glyph of Raise Dead - hide unused glyph'),('quests',9572,'zoneOrSort','3562','Weaken the Ramparts - category Hellfire Citadel -> Hellfire Ramparts'),('quests',9575,'zoneOrSort','3562','Weaken the Ramparts - category Hellfire Citadel -> Hellfire Ramparts'),('quests',11354,'zoneOrSort','3562','Wanted: Nazan\'s Riding Crop - category Hellfire Citadel -> Hellfire Ramparts'),('quests',9589,'zoneOrSort','3713','The Blood is Life - category Hellfire Citadel -> Blood Furnace'),('quests',9590,'zoneOrSort','3713','The Blood is Life - category Hellfire Citadel -> Blood Furnace'),('quests',9607,'zoneOrSort','3713','Heart of Rage - category Hellfire Citadel -> Blood Furnace'),('quests',9608,'zoneOrSort','3713','Heart of Rage - category Hellfire Citadel -> Blood Furnace'),('quests',11362,'zoneOrSort','3713','Wanted: Keli\'dan\'s Feathered Stave - category Hellfire Citadel -> Blood Furnace'),('quests',9492,'zoneOrSort','3714','Turning the Tide - category Hellfire Citadel -> Shattered Halls'),('quests',9493,'zoneOrSort','3714','Pride of the Fel Horde - category Hellfire Citadel -> Shattered Halls'),('quests',9494,'zoneOrSort','3714','Fel Embers - category Hellfire Citadel -> Shattered Halls'),('quests',9495,'zoneOrSort','3714','The Will of the Warchief - category Hellfire Citadel -> Shattered Halls'),('quests',9496,'zoneOrSort','3714','Pride of the Fel Horde - category Hellfire Citadel -> Shattered Halls'),('quests',9497,'zoneOrSort','3714','Emblem of the Fel Horde - category Hellfire Citadel -> Shattered Halls'),('quests',9524,'zoneOrSort','3714','Imprisoned in the Citadel - category Hellfire Citadel -> Shattered Halls'),('quests',9525,'zoneOrSort','3714','Imprisoned in the Citadel - category Hellfire Citadel -> Shattered Halls'),('quests',11363,'zoneOrSort','3714','Wanted: Bladefist\'s Seal - category Hellfire Citadel -> Shattered Halls'),('quests',11364,'zoneOrSort','3714','Wanted: Shattered Hand Centurions - category Hellfire Citadel -> Shattered Halls');
/*!40000 ALTER TABLE `aowow_setup_custom_data` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
diff --git a/setup/tools/sqlgen/areatrigger.ss.php b/setup/tools/sqlgen/areatrigger.ss.php
index 76b837fe..6f25914d 100644
--- a/setup/tools/sqlgen/areatrigger.ss.php
+++ b/setup/tools/sqlgen/areatrigger.ss.php
@@ -15,12 +15,11 @@ CLISetup::registerSetup('sql', new class extends SetupScript
protected $dbcSourceFiles = ['areatrigger'];
protected $worldDependency = ['areatrigger_involvedrelation', 'areatrigger_scripts', 'areatrigger_tavern', 'areatrigger_teleport', 'quest_template', 'quest_template_addon'];
- protected $setupAfter = [['dungeonmap', 'worldmaparea'], []];
public function generate(array $ids = []) : bool
{
DB::Aowow()->query('TRUNCATE ?_areatrigger');
- DB::Aowow()->query('INSERT INTO ?_areatrigger SELECT `id`, 0, 0, `mapId`, `posX`, `posY`, `orientation`, NULL, NULL, NULL, NULL, NULL, NULL, NULL FROM dbc_areatrigger');
+ DB::Aowow()->query('INSERT INTO ?_areatrigger SELECT `id`, 0, 0, `mapId`, `posX`, `posY`, `orientation`, NULL, NULL FROM dbc_areatrigger');
/* notes:
* while areatrigger DO have dimensions, displaying them on a map is almost always futile,
@@ -34,40 +33,18 @@ CLISetup::registerSetup('sql', new class extends SetupScript
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('[areatrigger] - calculation teleporter coordinates');
+
+ // 2: Teleporter
+ CLI::write('[areatrigger] - teleporter type and name');
$addData = DB::World()->select(
- 'SELECT ID AS ARRAY_KEY, Name AS `name`, target_map AS `map`, target_position_x AS `posX`, target_position_y AS `posY`, target_orientation AS `orientation`
- FROM areatrigger_teleport
- UNION
- SELECT entryorguid AS ARRAY_KEY, "TBD" AS `name`, action_param1 AS `map`, target_x AS `posX`, target_y AS `posY`, target_o AS `orientation`
- FROM smart_scripts
- WHERE source_type = 2 AND action_type = 62'
+ 'SELECT `ID` AS ARRAY_KEY, `Name` AS `name` FROM areatrigger_teleport UNION
+ SELECT `entryorguid` AS ARRAY_KEY, "SAI Teleport" AS `name` FROM smart_scripts WHERE `source_type` = ?d AND `action_type` = ?d',
+ SAI_SRC_TYPE_AREATRIGGER, SAI_ACTION_TELEPORT
);
-
foreach ($addData as $id => $ad)
- {
- $points = Game::worldPosToZonePos($ad['map'], $ad['posX'], $ad['posY']);
- if (!$points)
- {
- CLI::write('[areatrigger] '.str_pad('['.$id.']', 8).' 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;
- }
+ DB::Aowow()->query('UPDATE ?_areatrigger SET `name` = ?, `type` = ?d WHERE `id` = ?d', $ad['name'], AT_TYPE_TELEPORT, $id);
- $update = array(
- 'name' => $ad['name'],
- 'type' => AT_TYPE_TELEPORT,
- 'teleportA' => $points[0]['areaId'],
- 'teleportX' => $points[0]['posX'],
- 'teleportY' => $points[0]['posY'],
- 'teleportO' => $ad['orientation'],
- 'teleportF' => $points[0]['floor']
- );
-
- DB::Aowow()->query('UPDATE ?_areatrigger SET ?a WHERE `id` = ?d', $update, $id);
- }
// 3: Quest Objectives
CLI::write('[areatrigger] - satisfying quest objectives');
@@ -81,6 +58,7 @@ CLISetup::registerSetup('sql', new class extends SetupScript
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('[areatrigger] - assigning scripts');
diff --git a/setup/tools/sqlgen/spawns.ss.php b/setup/tools/sqlgen/spawns.ss.php
index dbb06786..2dea47bd 100644
--- a/setup/tools/sqlgen/spawns.ss.php
+++ b/setup/tools/sqlgen/spawns.ss.php
@@ -12,59 +12,82 @@ if (!CLI)
CLISetup::registerSetup("sql", new class extends SetupScript
{
protected $info = array(
- 'spawns' => [[], CLISetup::ARGV_PARAM, 'Compiles spawns/waypoints for type: GObject, NPC, Sound & Areatrigger from dbc and world db.']
- );
+ 'spawns' => [[ ], CLISetup::ARGV_PARAM, 'Compiles map points from dbc and world db.' ],
+ 'creatures' => [['1'], CLISetup::ARGV_OPTIONAL, '...just the creature positions.' ],
+ 'objects' => [['2'], CLISetup::ARGV_OPTIONAL, '...just the gameobject positions.' ],
+ 'soundemitter' => [['3'], CLISetup::ARGV_OPTIONAL, '...just the soundemitter positions.' ],
+ 'areatrigger' => [['4'], CLISetup::ARGV_OPTIONAL, '...just the areatrigger and teleporter positions.'],
+ 'instances' => [['5'], CLISetup::ARGV_OPTIONAL, '...just the instance portal positions.' ],
+ 'waypoints' => [['6'], CLISetup::ARGV_OPTIONAL, '...just the creature waypoints.' ]
+ );
protected $dbcSourceFiles = ['worldmaparea', 'map', 'taxipathnode', 'soundemitters', 'areatrigger', 'areatable'];
- protected $worldDependency = ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data'];
+ protected $worldDependency = ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data', 'smart_scripts', 'areatrigger_teleport'];
protected $setupAfter = [['dungeonmap', 'worldmaparea', 'zones'], ['img-maps']];
- 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_x` AS `posX`, c.`position_y` AS `posY` ' .
- 'FROM creature c LEFT JOIN creature_addon ca ON ca.guid = c.guid',
- '`creature` spawns', Type::NPC],
+ private $transports = [];
+ private $overrideData = [];
- 2 => ['SELECT c.`guid`, 2 AS `type`, c.`id` AS `typeId`, c.`spawntimesecs` AS `respawn`, c.`phaseMask`, c.`zoneId` AS `areaId`, c.`map`, 0 AS `pathId`, c.`position_x` AS `posX`, c.`position_y` AS `posY` ' .
- 'FROM gameobject c',
- '`gameobject` spawns', Type::OBJECT],
-
- 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',
- 'SoundEmitters.dbc spawns', Type::SOUND],
-
- 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',
- 'AreaTrigger.dbc spawns', Type::AREATRIGGER],
-
- 5 => ['SELECT c.`guid`, w.`entry` AS `npcOrPath`, w.`pointId` AS `point`, c.`zoneId` AS `areaId`, c.`map`, w.`waittime` AS `wait`, w.`location_x` AS `posX`, w.`location_y` AS `posY` ' .
- 'FROM creature c JOIN script_waypoint w ON c.`id` = w.`entry`',
- '`script_waypoint`', Type::NPC],
-
- 6 => ['SELECT c.`guid`, w.`entry` AS `npcOrPath`, w.`pointId` AS `point`, c.`zoneId` AS `areaId`, c.`map`, 0 AS `wait`, w.`position_x` AS `posX`, w.`position_y` AS `posY` ' .
- 'FROM creature c JOIN waypoints w ON c.`id` = w.`entry`',
- '`waypoints`', Type::NPC],
-
- 7 => ['SELECT c.`guid`, -w.`id` AS `npcOrPath`, w.`point`, c.`zoneId` AS `areaId`, c.`map`, w.`delay` AS `wait`, w.`position_x` AS `posX`, w.`position_y` 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',
- '`waypoint_data`', Type::NPC]
+ private $steps = array(
+ 0x01 => ['creature', Type::NPC, false, '`creature` spawns', ],
+ 0x02 => ['gameobject', Type::OBJECT, false, '`gameobject` spawns', ],
+ 0x04 => ['soundemitter', Type::SOUND, false, 'SoundEmitters.dbc positions', ],
+ 0x08 => ['areatrigger', Type::AREATRIGGER, false, 'AreaTrigger.dbc positions and teleporter endpoints' ],
+ 0x10 => ['instances', Type::ZONE, false, 'Map.dbc instance portals positions' ],
+ 0x20 => ['waypoints', Type::NPC, true, 'NPC waypoints from `script_waypoint`, `waypoints` & `waypoint_data`'],
);
+
public function generate(array $ids = []) : bool
{
- /*********************/
- /* truncate old data */
- /*********************/
+ /*****************************/
+ /* find out what to generate */
+ /*****************************/
- DB::Aowow()->query('TRUNCATE TABLE ?_spawns');
- DB::Aowow()->query('TRUNCATE TABLE ?_creature_waypoints');
+ $opts = array_slice(array_keys($this->info), 1);
+ $getOpt = CLISetup::getOpt(...$opts);
+ $todoMask = 0x0;
+
+ if ($getOpt['creatures'])
+ $todoMask |= 0x01;
+ if ($getOpt['objects'])
+ $todoMask |= 0x02;
+ if ($getOpt['soundemitter'])
+ $todoMask |= 0x04;
+ if ($getOpt['areatrigger'])
+ $todoMask |= 0x08;
+ if ($getOpt['instances'])
+ $todoMask |= 0x10;
+ if ($getOpt['waypoints'])
+ $todoMask |= 0x20;
+
+ if ($todoMask)
+ foreach ($this->steps as $idx => $_)
+ if (!($todoMask & $idx))
+ unset($this->steps[$idx]);
+
+
+ /*********************************/
+ /* selectively truncate old data */
+ /*********************************/
+
+ if (!$todoMask || ($todoMask & 0x1F) == 0x1F)
+ DB::Aowow()->query('TRUNCATE TABLE ?_spawns');
+ else
+ foreach ($this->steps as $idx => [, $type, $isWP, ])
+ if (($idx & $todoMask) && !$isWP)
+ DB::Aowow()->query('DELETE FROM ?_spawns WHERE `type` = ?d', $type);
+
+ if (!$todoMask || ($todoMask & 0x20))
+ 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` = ?d AND `data6` <> 0', OBJECT_MO_TRANSPORT);
- foreach ($transports as &$t)
+ $this->transports = DB::World()->selectCol('SELECT `data0` AS `pathId`, `data6` AS ARRAY_KEY FROM gameobject_template WHERE `type` = ?d AND `data6` <> 0', OBJECT_MO_TRANSPORT);
+ foreach ($this->transports as &$t)
$t = DB::Aowow()->selectRow('SELECT `posX`, `posY`, `mapId` FROM dbc_taxipathnode tpn WHERE tpn.`pathId` = ?d AND `nodeIdx` = 0', $t);
@@ -72,109 +95,57 @@ CLISetup::registerSetup("sql", new class extends SetupScript
/* get override data */
/*********************/
- $overrideData = DB::Aowow()->select('SELECT `type` AS ARRAY_KEY, `typeGuid` AS ARRAY_KEY2, `areaId`, `floor` FROM ?_spawns_override');
+ $this->overrideData = DB::Aowow()->select('SELECT `type` AS ARRAY_KEY, `typeGuid` AS ARRAY_KEY2, `areaId`, `floor` FROM ?_spawns_override');
/**************/
/* perform... */
/**************/
- foreach ($this->querys as $idx => $q)
+ foreach (array_values($this->steps) as $i => [$generator, $type, $isWP, $comment])
{
- $time = new Timer(500);
- $sum = 0;
+ $time = new Timer(500);
+ $sum = 0;
+ $lastOverride = 0;
+ $nSteps = count($this->steps);
+ $queryResult = $this->$generator();
+ $queryTotal = count($queryResult);
+ $queryTotalLen = strlen($queryTotal);
- if ($idx == 3 || $idx == 4)
- $queryResult = DB::Aowow()->select($q[0]);
- else
- $queryResult = DB::World()->select($q[0]);
+ CLI::write(' - '.$generator);
- $qryTotal = count($queryResult);
- $qtLen = strlen($qryTotal);
- $doneGUID = 0;
foreach ($queryResult as $spawn)
{
+ $notice = '';
$sum++;
if ($time->update())
- CLI::write(' * '.$idx.'/'.count($this->querys).': '. CLI::bold($q[1]).' - '.sprintf('%'.$qtLen.'d / %d (%4.1f%%)', $sum, $qryTotal, round(100 * $sum / $qryTotal, 1)), CLI::LOG_BLANK, true, true);
+ CLI::write(' * '.($i + 1).'/'.$nSteps.': '. CLI::bold($comment).' - '.sprintf('%'.$queryTotalLen.'d / %d (%4.1f%%)', $sum, $queryTotal, round(100 * $sum / $queryTotal, 1)), CLI::LOG_BLANK, true, true);
- // npc/object is on a transport -> apply offsets to path of transport
- // note, that transport DO spawn outside of displayable area maps .. another todo i guess..
- if (isset($transports[$spawn['map']]))
+ $point = $this->transformPoint($spawn, $type, $notice);
+
+ if (!$notice && !$lastOverride)
{
- $spawn['posX'] += $transports[$spawn['map']]['posX'];
- $spawn['posY'] += $transports[$spawn['map']]['posY'];
- $spawn['map'] = $transports[$spawn['map']]['mapId'];
+ CLI::write($notice, CLI::LOG_INFO);
+ $time->reset();
+ $lastOverride = $spawn['guid']; // don't spam this for waypoints
}
- $area = $spawn['areaId'];
- $floor = -1;
- if (isset($overrideData[$q[2]][$spawn['guid']]))
+ if (!$point)
{
- $area = $overrideData[$q[2]][$spawn['guid']]['areaId'];
- $floor = $overrideData[$q[2]][$spawn['guid']]['floor'];
- if ($doneGUID != $spawn['guid'])
- {
- CLI::write('[spawns] '.str_pad('['.$spawn['guid'].']', 9).' manually moved to [A:'.$spawn['areaId'].' => '.$area.'; F: '.$floor.']', CLI::LOG_INFO);
- $time->reset();
- $doneGUID = $spawn['guid']; // do not spam on waypoints
- }
- }
-
- $points = Game::worldPosToZonePos($spawn['map'], $spawn['posX'], $spawn['posY'], $area, $floor);
-
- // cannot be placed, but we know the instanced map and can thus at least assign a zone
- if (!$points && !in_array($spawn['map'], [0, 1, 530, 571]) && $idx < 5)
- {
- // use server calculated areaId if possible
- $area = $area ?: DB::Aowow()->selectCell('SELECT `id` FROM ?_zones WHERE `mapId` = ?d AND `parentArea` = 0 AND (`cuFlags` & ?d) = 0', $spawn['map'], CUSTOM_EXCLUDE_FOR_LISTVIEW);
- if (!$area)
- {
- CLI::write('[spawns] '.str_pad('['.$spawn['guid'].']', 9).' could not be defaulted to instanced area by mapId [M:'.$spawn['map'].']', CLI::LOG_WARN);
- $time->reset();
- continue;
- }
- $final = ['areaId' => $area, 'posX' => 0, 'posY' => 0, 'floor' => 0];
- }
- else if (!$points) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris))
- {
- CLI::write('[spawns] '.str_pad('['.$spawn['guid'].']', 9).' '.($idx < 5 ? '' : 'with path/point ['.$spawn['npcOrPath'].'; '.$spawn['point'].'] ').'could not be matched to displayable area [A:'.$area.'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLI::LOG_WARN);
+ CLI::write('[points] '.str_pad('['.$spawn['guid'].']', 9).' '.(isset($spawn['point']) ? 'with path/point ['.$spawn['npcOrPath'].'; '.$spawn['point'].'] ' : '').'could not be matched to displayable area [A:'.($spawn['areaId'] ?? 0).'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLI::LOG_WARN);
$time->reset();
continue;
}
- else // if areaId is set, area was determined by TC .. we're fine .. mostly
- $final = $area ? $points[0] : Game::checkCoords($points);
- if ($idx < 5)
+ $set = array_merge($spawn, $point);
+ if (!$isWP) // REPLACE: because there is bogus data where one path may be assigned to multiple npcs
{
- $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']
- );
-
+ unset($set['map']);
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']
- );
-
- // REPLACE: because there is bogus data where one path may be assigned to multiple npcs
+ unset($set['map'], $set['guid']);
DB::Aowow()->query('REPLACE INTO ?_creature_waypoints (?#) VALUES (?a)', array_keys($set), array_values($set));
}
}
@@ -185,44 +156,47 @@ CLISetup::registerSetup("sql", new class extends SetupScript
/* spawn vehicle accessories */
/*****************************/
- // get vehicle template accessories
- $accessories = DB::World()->select(
- 'SELECT vta.`accessory_entry` AS `typeId`, c.`guid`, vta.`entry`, COUNT(1) AS `nSeats` FROM vehicle_template_accessory vta LEFT JOIN creature c ON c.`id` = vta.`entry` GROUP BY `accessory_entry`, c.`guid` UNION
- SELECT va.`accessory_entry` AS `typeId`, va.`guid`, 0 AS `entry`, COUNT(1) AS `nSeats` FROM vehicle_accessory va GROUP BY `accessory_entry`, va.`guid`'
- );
-
- // accessories may also be vehicles (e.g. "Kor'kron Infiltrator" is seated on "Kor'kron Suppression Turret" is seated on "Kor'kron Troop Transport")
- // so we will retry finding a spawned vehicle if none were found on the previous pass and a change occured
- $vGuid = 0; // not really used, but we need some kind of index
- $n = 0;
- $matches = -1;
- while ($matches)
+ if ($todoMask & 0x01) // only when creature is set
{
- $matches = 0;
- foreach ($accessories as $idx => $data)
+ // get vehicle template accessories
+ $accessories = DB::World()->select(
+ 'SELECT vta.`accessory_entry` AS `typeId`, c.`guid`, vta.`entry`, COUNT(1) AS `nSeats` FROM vehicle_template_accessory vta LEFT JOIN creature c ON c.`id` = vta.`entry` GROUP BY `accessory_entry`, c.`guid` UNION
+ SELECT va.`accessory_entry` AS `typeId`, va.`guid`, 0 AS `entry`, COUNT(1) AS `nSeats` FROM vehicle_accessory va GROUP BY `accessory_entry`, va.`guid`'
+ );
+
+ // accessories may also be vehicles (e.g. "Kor'kron Infiltrator" is seated on "Kor'kron Suppression Turret" is seated on "Kor'kron Troop Transport")
+ // so we will retry finding a spawned vehicle if none were found on the previous pass and a change occured
+ $vGuid = 0; // not really used, but we need some kind of index
+ $n = 0;
+ $matches = -1;
+ while ($matches)
{
- $vehicles = [];
- if ($data['guid']) // vehicle already spawned
- $vehicles = DB::Aowow()->select('SELECT s.`areaId`, s.`posX`, s.`posY`, s.`floor` FROM ?_spawns s WHERE s.`guid` = ?d AND s.`type` = ?d', $data['guid'], Type::NPC);
- else if ($data['entry']) // vehicle on unspawned vehicle action
- $vehicles = DB::Aowow()->select('SELECT s.`areaId`, s.`posX`, s.`posY`, s.`floor` FROM ?_spawns s WHERE s.`typeId` = ?d AND s.`type` = ?d', $data['entry'], Type::NPC);
-
- if ($vehicles)
+ $matches = 0;
+ foreach ($accessories as $idx => $data)
{
- $matches++;
- foreach ($vehicles as $v) // if there is more than one vehicle, its probably due to overlapping zones
- for ($i = 0; $i < $data['nSeats']; $i++)
- DB::Aowow()->query('INSERT INTO ?_spawns (`guid`, `type`, `typeId`, `respawn`, `spawnMask`, `phaseMask`, `areaId`, `floor`, `posX`, `posY`, `pathId`) VALUES (?d, ?d, ?d, 0, 0, 1, ?d, ?d, ?f, ?f, 0)',
- --$vGuid, Type::NPC, $data['typeId'], $v['areaId'], $v['floor'], $v['posX'], $v['posY']);
+ $vehicles = [];
+ if ($data['guid']) // vehicle already spawned
+ $vehicles = DB::Aowow()->select('SELECT s.`areaId`, s.`posX`, s.`posY`, s.`floor` FROM ?_spawns s WHERE s.`guid` = ?d AND s.`type` = ?d', $data['guid'], Type::NPC);
+ else if ($data['entry']) // vehicle on unspawned vehicle action
+ $vehicles = DB::Aowow()->select('SELECT s.`areaId`, s.`posX`, s.`posY`, s.`floor` FROM ?_spawns s WHERE s.`typeId` = ?d AND s.`type` = ?d', $data['entry'], Type::NPC);
- unset($accessories[$idx]);
+ if ($vehicles)
+ {
+ $matches++;
+ foreach ($vehicles as $v) // if there is more than one vehicle, its probably due to overlapping zones
+ for ($i = 0; $i < $data['nSeats']; $i++)
+ DB::Aowow()->query('INSERT INTO ?_spawns (`guid`, `type`, `typeId`, `respawn`, `spawnMask`, `phaseMask`, `areaId`, `floor`, `posX`, `posY`, `pathId`) VALUES (?d, ?d, ?d, 0, 0, 1, ?d, ?d, ?f, ?f, 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', CLI::LOG_BLANK, true, true);
}
- if ($matches)
- CLI::write(' * assigned '.$matches.' accessories on '.++$n.'. pass on vehicle accessories', CLI::LOG_BLANK, true, true);
+ if ($accessories)
+ CLI::write('[spawns] - '.count($accessories).' accessories could not be fitted onto a spawned vehicle.', CLI::LOG_WARN);
}
- if ($accessories)
- CLI::write('[spawns] - '.count($accessories).' accessories could not be fitted onto a spawned vehicle.', CLI::LOG_WARN);
/********************************/
@@ -233,6 +207,131 @@ CLISetup::registerSetup("sql", new class extends SetupScript
return true;
}
+
+ private function creature() : array
+ {
+ // [guid, type, typeId, map, posX, posY [, respawn, spawnMask, phaseMask, areaId, floor, pathId]]
+ return DB::World()->select(
+ 'SELECT c.`guid`, ?d AS `type`, c.`id` AS `typeId`, c.`map`, c.`position_x` AS `posX`, c.`position_y` AS `posY`, c.`spawntimesecs` AS `respawn`, c.`spawnMask`, c.`phaseMask`, c.`zoneId` AS `areaId`, IFNULL(ca.`path_id`, 0) AS `pathId`
+ FROM creature c
+ LEFT JOIN creature_addon ca ON ca.guid = c.guid',
+ Type::NPC
+ );
+ }
+
+ private function gameobject() : array
+ {
+ // [guid, type, typeId, map, posX, posY [, respawn, spawnMask, phaseMask, areaId, floor, pathId]]
+ return DB::World()->select(
+ 'SELECT `guid`, ?d AS `type`, `id` AS `typeId`, `map`, `position_x` AS `posX`, `position_y` AS `posY`, `spawntimesecs` AS `respawn`, `spawnMask`, `phaseMask`, `zoneId` AS `areaId`
+ FROM gameobject',
+ Type::OBJECT
+ );
+ }
+
+ private function soundemitter() : array
+ {
+ // [guid, type, typeId, map, posX, posY [, respawn, spawnMask, phaseMask, areaId, floor, pathId]]
+ return DB::Aowow()->select(
+ 'SELECT `id` AS `guid`, ?d AS `type`, `soundId` AS `typeId`, `mapId` AS `map`, `posX`, `posY`
+ FROM dbc_soundemitters',
+ Type::SOUND
+ );
+ }
+
+ private function areatrigger() : array
+ {
+ // [guid, type, typeId, map, posX, posY [, respawn, spawnMask, phaseMask, areaId, floor, pathId]]
+ $base = DB::Aowow()->select(
+ 'SELECT `id` AS `guid`, ?d AS `type`, `id` AS `typeId`, `mapId` AS `map`, `posX`, `posY`
+ FROM dbc_areatrigger',
+ Type::AREATRIGGER
+ );
+
+ $addData = DB::World()->select(
+ 'SELECT -`ID` AS `guid`, ?d AS `type`, ID AS `typeId`, `target_map` AS `map`, `target_position_x` AS `posX`, `target_position_y` AS `posY`
+ FROM areatrigger_teleport UNION
+ SELECT -`entryorguid` AS `guid`, ?d AS `type`, entryorguid AS `typeId`, `action_param1` AS `map`, `target_x` AS `posX`, `target_y` AS `posY`
+ FROM smart_scripts
+ WHERE `source_type` = ?d AND `action_type` = ?d',
+ Type::AREATRIGGER, Type::AREATRIGGER, SAI_SRC_TYPE_AREATRIGGER, SAI_ACTION_TELEPORT
+ );
+
+ return array_merge($base, $addData);
+ }
+
+ private function instances() : array
+ {
+ // maps with set graveyard
+ return DB::Aowow()->select(
+ 'SELECT -`id` AS `guid`, ?d AS `type`, `id` AS `typeId`, `parentMapId` AS `map`, `parentX` AS `posX`, `parentY` AS `posY`
+ FROM ?_zones
+ WHERE `parentX` <> 0 AND `parentY` <> 0 AND `parentArea` = 0 AND (`cuFlags` & ?d) = 0',
+ Type::ZONE, CUSTOM_EXCLUDE_FOR_LISTVIEW
+ );
+ }
+
+ private function waypoints() : array
+ {
+ return DB::World()->select(
+ 'SELECT c.`guid`, w.`entry` AS `creatureOrPath`, w.`pointId` AS `point`, c.`zoneId` AS `areaId`, c.`map`, w.`waittime` AS `wait`, w.`location_x` AS `posX`, w.`location_y` AS `posY`
+ FROM creature c
+ JOIN script_waypoint w ON c.`id` = w.`entry` UNION
+ SELECT c.`guid`, w.`entry` AS `creatureOrPath`, w.`pointId` AS `point`, c.`zoneId` AS `areaId`, c.`map`, 0 AS `wait`, w.`position_x` AS `posX`, w.`position_y` AS `posY`
+ FROM creature c
+ JOIN waypoints w ON c.`id` = w.`entry` UNION
+ SELECT c.`guid`, -w.`id` AS `creatureOrPath`, w.`point`, c.`zoneId` AS `areaId`, c.`map`, w.`delay` AS `wait`, w.`position_x` AS `posX`, w.`position_y` 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'
+ );
+ }
+
+
+ private function transformPoint(array $point, int $type, ?string $notice = '') : array
+ {
+ // npc/object is on a transport -> apply offsets to path of transport
+ // note, that transport DO spawn outside of displayable area maps .. another todo i guess..
+ if (isset($this->transports[$point['map']]))
+ {
+ $point['posX'] += $this->transports[$point['map']]['posX'];
+ $point['posY'] += $this->transports[$point['map']]['posY'];
+ $point['map'] = $this->transports[$point['map']]['mapId'];
+ }
+
+ $area = $point['areaId'] ?? 0;
+ $floor = -1;
+ if (isset($this->overrideData[$type][$point['guid']]))
+ {
+ $area = $this->overrideData[$type][$point['guid']]['areaId'];
+ $floor = $this->overrideData[$type][$point['guid']]['floor'];
+ $notice = '[points] '.str_pad('['.$point['guid'].']', 9).' manually moved to [A:'.($point['areaId'] ?? 0).' => '.$area.'; F: '.$floor.']';
+ }
+
+ if ($points = Game::worldPosToZonePos($point['map'], $point['posX'], $point['posY'], $area, $floor))
+ {
+ if ($area) // if areaId is set, area was determined by TC .. we're fine .. mostly
+ return ['areaId' => $area, 'posX' => $points[0]['posX'], 'posY' => $points[0]['posY'], 'floor' => $points[0]['floor']];
+
+ $point = Game::checkCoords($points); // try to determine best found point by alphamap
+ return ['areaId' => $point['areaId'], 'posX' => $point['posX'], 'posY' => $point['posY'], 'floor' => $point['floor']];
+ }
+
+ // cannot be placed on a map, try to reuse TC assigned areaId
+ if ($area)
+ {
+ $selfOrParent = DB::Aowow()->selectCell('SELECT IF(`parentArea`, `parentArea`, `id`) FROM ?_zones WHERE `id` = ?d', $area);
+ return ['areaId' => $selfOrParent, 'posX' => 0, 'posY' => 0, 'floor' => 0];
+ }
+
+ // we know the instanced map; try to assign a zone this way
+ if (!in_array($point['map'], [0, 1, 530, 571]))
+ if ($area = DB::Aowow()->selectCell('SELECT `id` FROM ?_zones WHERE `mapId` = ?d AND `parentArea` = 0 AND (`cuFlags` & ?d) = 0', $point['map'], CUSTOM_EXCLUDE_FOR_LISTVIEW))
+ return ['areaId' => $area, 'posX' => 0, 'posY' => 0, 'floor' => 0];
+
+ return [];
+ }
});
?>
diff --git a/setup/tools/sqlgen/zones.ss.php b/setup/tools/sqlgen/zones.ss.php
index 010b1d59..2bd1635d 100644
--- a/setup/tools/sqlgen/zones.ss.php
+++ b/setup/tools/sqlgen/zones.ss.php
@@ -20,8 +20,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript
'zones' => [[], CLISetup::ARGV_PARAM, 'Compiles supplemental data for type: Zone from dbc and world db.']
);
- protected $dbcSourceFiles = ['worldmaptransforms', 'worldmaparea', 'map', 'mapdifficulty', 'areatable', 'lfgdungeons', 'battlemasterlist'];
- protected $worldDependency = ['access_requirement'];
+ protected $dbcSourceFiles = ['worldmaptransforms', 'worldmaparea', 'map', 'mapdifficulty', 'areatable', 'lfgdungeons', 'battlemasterlist', 'areatrigger'];
+ protected $worldDependency = ['access_requirement', 'areatrigger_teleport'];
protected $setupAfter = [['dungeonmap', 'worldmaparea'], []];
public function generate(array $ids = []) : bool
@@ -49,9 +49,9 @@ CLISetup::registerSetup("sql", new class extends SetupScript
IF(a.flags & 0x8, ?d, IFNULL(bm.maxLevel, IFNULL(lfgIni.levelMax, IFNULL(lfgOpen.levelMax, 0)))) AS `levelMax`,
"" AS `attunementsN`,
"" AS `attunementsH`,
- m.parentMapId, -- IFNULL(pa.areaId, 0),
- m.parentX, -- IFNULL(pa.posX, 0),
- m.parentY, -- IFNULL(pa.posY, 0),
+ GREATEST(m.parentMapId, 0),
+ m.parentX,
+ m.parentY,
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),
@@ -77,26 +77,18 @@ CLISetup::registerSetup("sql", new class extends SetupScript
CUSTOM_EXCLUDE_FOR_LISTVIEW, MAX_LEVEL
);
- foreach ($baseData as &$bd)
- {
- // usually parent = -1 means no parent but some maps have this touple set to 0
- if (!$bd['parentMapId'] && !$bd['parentX'] && !$bd['parentY'])
- continue;
-
- if ($gPos = Game::worldPosToZonePos($bd['parentMapId'], $bd['parentY'], $bd['parentX']))
- {
- $pos = Game::checkCoords($gPos);
- $bd['parentMapId'] = $pos['areaId'] ?? $gPos[0]['areaId'];
- $bd['parentX'] = $pos['posX'] ?? $gPos[0]['posX'];
- $bd['parentY'] = $pos['posY'] ?? $gPos[0]['posY'];
- continue;
- }
-
- $bd['parentMapId'] = 0;
- }
-
DB::Aowow()->query('INSERT INTO ?_zones VALUES (?a)', $baseData);
+
+ // set missing graveyards from areatrigger data (auto-resurrect map or just plain errors)
+ // grouped because naxxramas _just has_ to be special with 4 entrances...
+ if ($missingMaps = DB::Aowow()->selectCol('SELECT `id` FROM dbc_map WHERE `parentX` = 0 AND `parentY` = 0 AND `parentMapId` > -1 AND `areaType` NOT IN (0, 3, 4)'))
+ if ($triggerIds = DB::World()->selectCol('SELECT `target_map`, `id` AS ARRAY_KEY FROM areatrigger_teleport WHERE `target_map` IN (?a) GROUP BY `target_map`', $missingMaps))
+ if ($positions = DB::Aowow()->select('SELECT `id` AS `ARRAY_KEY`, `mapId` AS "parentMapId", `posX` AS "parentX", `posY` AS "parentY" FROM dbc_areatrigger WHERE `id` IN (?a)', array_keys($triggerIds)))
+ foreach ($positions as $atId => $parentPos)
+ DB::Aowow()->query('UPDATE ?_zones SET ?a WHERE `mapId` = ?d', $parentPos, $triggerIds[$atId]);
+
+
// get requirements from world.access_requirement
$zoneReq = DB::World()->select(
'SELECT mapId AS ARRAY_KEY,
diff --git a/setup/updates/1719445945_01.sql b/setup/updates/1719445945_01.sql
new file mode 100644
index 00000000..67b34418
--- /dev/null
+++ b/setup/updates/1719445945_01.sql
@@ -0,0 +1,25 @@
+DROP TABLE IF EXISTS `aowow_areatrigger`;
+CREATE TABLE `aowow_areatrigger` (
+ `id` int unsigned NOT NULL,
+ `cuFlags` int unsigned NOT NULL DEFAULT 0 COMMENT 'see defines.php for flags',
+ `type` smallint unsigned NOT NULL,
+ `mapId` smallint unsigned NOT NULL COMMENT 'world pos. from dbc',
+ `posX` float NOT NULL COMMENT 'world pos. from dbc',
+ `posY` float NOT NULL COMMENT 'world pos. from dbc',
+ `orientation` float NOT NULL,
+ `name` varchar(100) DEFAULT NULL,
+ `quest` mediumint unsigned DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `quest` (`quest`),
+ KEY `type` (`type`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+
+ALTER TABLE `aowow_zones`
+ CHANGE COLUMN `parentAreaId` `parentMapId` smallint unsigned NOT NULL;
+
+DELETE FROM aowow_setup_custom_data WHERE
+ `command` = 'zones' AND
+ `entry` IN (3456, 3845, 3847, 3848, 3849) AND
+ `field` IN ('parentAreaId', 'parentX', 'parentY');
+
+UPDATE `aowow_dbversion` SET `sql` = CONCAT(IFNULL(`sql`, ''), ' areatrigger zones spawns');