diff --git a/endpoints/spell/spell.php b/endpoints/spell/spell.php index bd3e7117..de96a363 100644 --- a/endpoints/spell/spell.php +++ b/endpoints/spell/spell.php @@ -1864,7 +1864,8 @@ class SpellBaseResponse extends TemplateResponse implements ICache break; case SPELL_EFFECT_SEND_TAXI: $_ = DB::Aowow()->selectRow( - 'SELECT tn1.`name_loc0` AS `start_loc0`, tn1.name_loc?d AS start_loc?d, tn2.`name_loc0` AS `end_loc0`, tn2.name_loc?d AS end_loc?d + 'SELECT tn1.`areaId` AS "startAreaId", tn1.`areaX` AS "startPosX", tn1.`areaY` AS "startPosY", tn1.`name_loc0` AS `start_loc0`, tn1.name_loc?d AS start_loc?d, + tn2.`areaId` AS "endAreaId", tn2.`areaX` AS "endPosX", tn2.`areaY` AS "endPosY", tn2.`name_loc0` AS `end_loc0`, tn2.name_loc?d AS end_loc?d FROM ?_taxipath tp JOIN ?_taxinodes tn1 ON tp.`startNodeId` = tn1.`id` JOIN ?_taxinodes tn2 ON tp.`endNodeId` = tn2.`id` @@ -1872,7 +1873,16 @@ class SpellBaseResponse extends TemplateResponse implements ICache Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, $effMV ); if ($_) - $_nameMV = $this->fmtStaffTip(''.Util::localizedString($_, 'start').''.Util::localizedString($_, 'end'), 'MiscValue: '.$effMV); + { + $start = Util::localizedString($_, 'start'); + if ($_['startAreaId']) + $start = sprintf('%s', $_['startAreaId'], $_['startPosX'] * 10, $_['startPosY'] * 10, $start); + $end = Util::localizedString($_, 'end'); + if ($_['endAreaId']) + $end = sprintf('%s', $_['endAreaId'], $_['endPosX'] * 10, $_['endPosY'] * 10, $end); + + $_nameMV = $this->fmtStaffTip(''.$start.''.$end, 'MiscValue: '.$effMV); + } break; case SPELL_EFFECT_TITAN_GRIP: $effMV = 0; // effMV is trigger spell and was handled earlier diff --git a/endpoints/zones/zones.php b/endpoints/zones/zones.php index 1909c6b1..a58b64e9 100644 --- a/endpoints/zones/zones.php +++ b/endpoints/zones/zones.php @@ -120,8 +120,8 @@ class ZonesBaseResponse extends TemplateResponse implements ICache $nodes = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, tn.* FROM ?_taxinodes tn WHERE `mapId` = ?d AND `type` <> 0 AND `typeId` <> 0', $spawnMap); $paths = DB::Aowow()->select( 'SELECT IF(tn1.`reactA` = tn1.`reactH` AND tn2.`reactA` = tn2.`reactH`, 1, 0) AS "neutral", - tp.`startNodeId` AS "startId", tn1.`posX` AS "startPosX", tn1.`posY` AS "startPosY", - tp.`endNodeId` AS "endId", tn2.`posX` AS "endPosX", tn2.`posY` AS "endPosY" + tp.`startNodeId` AS "startId", tn1.`mapX` AS "startPosX", tn1.`mapY` AS "startPosY", + tp.`endNodeId` AS "endId", tn2.`mapX` AS "endPosX", tn2.`mapY` AS "endPosY" FROM ?_taxipath tp, ?_taxinodes tn1, ?_taxinodes tn2 WHERE tn1.`Id` = tp.`endNodeId` AND tn2.`Id` = tp.`startNodeId` AND tn1.`type` <> 0 AND tn2.`type` <> 0 AND @@ -134,7 +134,7 @@ class ZonesBaseResponse extends TemplateResponse implements ICache $neutral = $n['reactH'] == $n['reactA']; $data = array( - 'coords' => [[$n['posX'], $n['posY']]], + 'coords' => [[$n['mapX'], $n['mapY']]], 'level' => 0, // floor 'name' => Util::localizedString($n, 'name'), 'type' => $n['type'], diff --git a/setup/sql/01-db_structure.sql b/setup/sql/01-db_structure.sql index f4cf0375..ffd49c59 100644 --- a/setup/sql/01-db_structure.sql +++ b/setup/sql/01-db_structure.sql @@ -2881,8 +2881,11 @@ DROP TABLE IF EXISTS `aowow_taxinodes`; CREATE TABLE `aowow_taxinodes` ( `id` smallint(5) unsigned NOT NULL, `mapId` smallint(5) unsigned NOT NULL, - `posX` float unsigned NOT NULL, - `posY` float unsigned NOT NULL, + `mapX` float unsigned NOT NULL, + `mapY` float unsigned NOT NULL, + `areaId` smallint(5) unsigned NOT NULL, + `areaX` float unsigned NOT NULL, + `areaY` float unsigned NOT NULL, `type` enum('NPC','GOBJECT') NOT NULL, `typeId` mediumint(8) unsigned NOT NULL, `reactA` tinyint(4) NOT NULL, diff --git a/setup/sql/02-db_initial_data.sql b/setup/sql/02-db_initial_data.sql index 352cdde9..72fdfa8c 100644 --- a/setup/sql/02-db_initial_data.sql +++ b/setup/sql/02-db_initial_data.sql @@ -71,7 +71,7 @@ UNLOCK TABLES; LOCK TABLES `aowow_dbversion` WRITE; /*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */; -INSERT INTO `aowow_dbversion` VALUES (1767117347,0,NULL,NULL); +INSERT INTO `aowow_dbversion` VALUES (1768324766,0,NULL,NULL); /*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */; UNLOCK TABLES; diff --git a/setup/sql/updates/1768324765_01.sql b/setup/sql/updates/1768324765_01.sql new file mode 100644 index 00000000..3b04a1df --- /dev/null +++ b/setup/sql/updates/1768324765_01.sql @@ -0,0 +1,9 @@ +ALTER TABLE `aowow_taxinodes` + CHANGE COLUMN `posX` `mapX` float unsigned NOT NULL, + CHANGE COLUMN `posY` `mapY` float unsigned NOT NULL, + ADD COLUMN `areaId` smallint(5) unsigned NOT NULL AFTER `mapY`, + ADD COLUMN `areaX` float unsigned NOT NULL AFTER `areaId`, + ADD COLUMN `areaY` float unsigned NOT NULL AFTER `areaX` +; + +UPDATE `aowow_dbversion` SET `sql` = CONCAT(IFNULL(`sql`, ''), ' taxi'); diff --git a/setup/tools/sqlgen/taxi.ss.php b/setup/tools/sqlgen/taxi.ss.php index 15652be5..36594047 100644 --- a/setup/tools/sqlgen/taxi.ss.php +++ b/setup/tools/sqlgen/taxi.ss.php @@ -17,6 +17,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript protected $dbcSourceFiles = ['taxipath', 'taxinodes', 'worldmaparea', 'worldmaptransforms', 'factiontemplate']; protected $worldDependency = ['creature', 'creature_template']; + protected $setupAfter = [['dungeonmap', 'worldmaparea'], []]; // accessed by WorldPosition::toZonePos public function generate(array $ids = []) : bool { @@ -52,96 +53,97 @@ CLISetup::registerSetup("sql", new class extends SetupScript // all sensible nodes $fNodes = DB::Aowow()->select( - 'SELECT tn.id, tn.mapId, - 100 - ROUND((tn.posY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, - 100 - ROUND((tn.posX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, - 1 AS `type`, 0 AS `typeId`, 1 AS reactA, 1 AS reactH, - tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, - tn.mapId AS origMap, tn.posX AS origPosX, tn.posY AS origPosY, - IF (tn.id NOT IN (15, 148, 225, 235) AND ( - tn.id IN (64, 250) OR ( - tn.name_loc0 NOT LIKE "%Transport%" AND tn.name_loc0 NOT LIKE "%Quest%" AND - tn.name_loc0 NOT LIKE "%Start%" AND tn.name_loc0 NOT LIKE "%End%" + 'SELECT tn.`id`, + tn.`mapId`, + 100 - ROUND((tn.`posY` - wma.`right`) * 100 / (wma.`left` - wma.`right`), 1) AS "mapX", + 100 - ROUND((tn.`posX` - wma.`bottom`) * 100 / (wma.`top` - wma.`bottom`), 1) AS "mapY", + 0 AS "areaId", + 0 AS "areaX", + 0 AS "areaY", + 1 AS `type`, 0 AS `typeId`, 1 AS "reactA", 1 AS "reactH", + tn.`name_loc0`, tn.`name_loc2`, tn.`name_loc3`, tn.`name_loc4`, tn.`name_loc6`, tn.`name_loc8`, + tn.`mapId` AS "_mapId", tn.`posX` AS "_posX", tn.`posY` AS "_posY", + IF (tn.`id` NOT IN (15, 148, 225, 235) AND ( + tn.`id` IN (64, 250) OR ( + tn.`name_loc0` NOT LIKE "%Transport%" AND tn.`name_loc0` NOT LIKE "%Quest%" AND + tn.`name_loc0` NOT LIKE "%Start%" AND tn.`name_loc0` NOT LIKE "%End%" ) - ), 0, 1) AS scripted + ), 0, 1) AS "_scripted" FROM dbc_taxinodes tn - JOIN dbc_worldmaparea wma ON ( tn.mapId = wma.mapId AND tn.posX BETWEEN wma.bottom AND wma.top AND tn.posY BETWEEN wma.right AND wma.left) - WHERE wma.areaId = 0 AND wma.mapId = tn.mapId + JOIN dbc_worldmaparea wma ON ( tn.`mapId` = wma.`mapId` AND tn.`posX` BETWEEN wma.`bottom` AND wma.`top` AND tn.`posY` BETWEEN wma.`right` AND wma.`left`) + WHERE wma.`areaId` = 0 AND wma.`mapId` = tn.`mapId` UNION - SELECT tn.id, wmt.targetMapId, - 100 - ROUND((tn.posY + wmt.offsetY - wma.right) * 100 / (wma.left - wma.right), 1) AS posX, - 100 - ROUND((tn.posX + wmt.offsetX - wma.bottom) * 100 / (wma.top - wma.bottom), 1) AS poxY, - 1 AS `type`, 0 AS `typeId`, 1 AS reactA, 1 AS reactH, - tn.name_loc0, tn.name_loc2, tn.name_loc3, tn.name_loc4, tn.name_loc6, tn.name_loc8, - tn.mapId AS origMap, tn.posX AS origPosX, tn.posY AS origPosY, + SELECT tn.`id`, + wmt.`targetMapId`, + 100 - ROUND((tn.`posY` + wmt.`offsetY` - wma.`right`) * 100 / (wma.`left` - wma.`right`), 1) AS "mapX", + 100 - ROUND((tn.`posX` + wmt.`offsetX` - wma.`bottom`) * 100 / (wma.`top` - wma.`bottom`), 1) AS "mapY", + 0 AS "areaId", + 0 AS "areaX", + 0 AS "areaY", + 1 AS `type`, 0 AS `typeId`, 1 AS "reactA", 1 AS "reactH", + tn.`name_loc0`, tn.`name_loc2`, tn.`name_loc3`, tn.`name_loc4`, tn.`name_loc6`, tn.`name_loc8`, + tn.`mapId` AS "_mapId", tn.`posX` AS "_posX", tn.`posY` AS "_posY", IF (tn.name_loc0 NOT LIKE "%Transport%" AND tn.name_loc0 NOT LIKE "%Quest%" AND tn.name_loc0 NOT LIKE "%Start%" AND tn.name_loc0 NOT LIKE "%End%", - 0, 1 ) AS scripted + 0, 1 ) AS "_scripted" FROM dbc_taxinodes tn - JOIN dbc_worldmaptransforms wmt ON ( tn.mapId = wmt.sourceMapId AND tn.posX BETWEEN wmt.minX AND wmt.maxX AND tn.posY BETWEEN wmt.minY AND wmt.maxY) - JOIN dbc_worldmaparea wma ON ( wmt.targetMapId = wma.mapId AND tn.posX + wmt.offsetX BETWEEN wma.bottom AND wma.top AND tn.posY + wmt.offsetY BETWEEN wma.right AND wma.left) - WHERE wma.areaId = 0 AND wmt.sourcemapId = tn.mapId' + JOIN dbc_worldmaptransforms wmt ON ( tn.`mapId` = wmt.`sourceMapId` AND tn.`posX` BETWEEN wmt.`minX` AND wmt.`maxX` AND tn.`posY` BETWEEN wmt.`minY` AND wmt.`maxY`) + JOIN dbc_worldmaparea wma ON ( wmt.`targetMapId` = wma.`mapId` AND tn.`posX` + wmt.`offsetX` BETWEEN wma.`bottom` AND wma.`top` AND tn.`posY` + wmt.`offsetY` BETWEEN wma.`right` AND wma.`left`) + WHERE wma.`areaId` = 0 AND wmt.`sourcemapId` = tn.`mapId`' ); // all available flightmaster - $fMaster = DB::World()->select( - 'SELECT ct.entry, ct.faction, c.map, c.position_x AS posX, c.position_y AS posY FROM creature_template ct JOIN creature c ON c.id = ct.entry WHERE ct.npcflag & ?d OR c.npcflag & ?d', + $fMaster = DB::World()->select('SELECT ct.`entry`, ct.`faction`, c.`map`, c.`position_x` AS "posX", c.`position_y` AS "posY" FROM creature_template ct JOIN creature c ON c.`id` = ct.`entry` WHERE ct.`npcflag` & ?d OR c.`npcflag` & ?d', NPC_FLAG_FLIGHT_MASTER, NPC_FLAG_FLIGHT_MASTER ); - // assign nearest flightmaster to node - foreach ($fNodes as &$n) - { - foreach ($fMaster as &$c) - { - if ($c['map'] != $n['origMap']) - continue; - - $dist = pow($c['posX'] - $n['origPosX'], 2) + pow($c['posY'] - $n['origPosY'], 2); - if ($dist > 1000) - continue; - - if (!isset($n['dist']) || $n['dist'] < $dist) - { - $n['dist'] = $dist; - $n['typeId'] = $c['entry']; - $n['faction'] = $c['faction']; - } - } - } - - unset($n); - // fetch reactions per faction $factions = DB::Aowow()->query( - 'SELECT id AS ARRAY_KEY, - IF(enemyFactionId1 = 1 OR enemyFactionId2 = 1 OR enemyFactionId3 = 1 OR enemyFactionId4 = 1 OR hostileMask & 0x3, -1, 1) AS reactA, - IF(enemyFactionId1 = 2 OR enemyFactionId2 = 2 OR enemyFactionId3 = 2 OR enemyFactionId4 = 2 OR hostileMask & 0x5, -1, 1) AS reactH + 'SELECT `id` AS ARRAY_KEY, + IF(`enemyFactionId1` = 1 OR `enemyFactionId2` = 1 OR `enemyFactionId3` = 1 OR `enemyFactionId4` = 1 OR `hostileMask` & 0x3, -1, 1) AS "reactA", + IF(`enemyFactionId1` = 2 OR `enemyFactionId2` = 2 OR `enemyFactionId3` = 2 OR `enemyFactionId4` = 2 OR `hostileMask` & 0x5, -1, 1) AS "reactH" FROM dbc_factiontemplate - WHERE id IN (?a)', - array_column($fNodes, 'faction')); + WHERE `id` IN (?a)', + array_column($fMaster, 'faction')); foreach ($fNodes as $n) { - // if (empty($n['faction'])) - // { - // CLI::write(' - ['.$n['id'].'] "'.$n['name_loc0'].'" has no NPC assigned ... skipping', CLI::LOG_WARN); - // continue; - // } - - if ($n['scripted'] || empty($n['faction'])) + // assign nearest flightmaster and its reaction to node + if ($n['_scripted']) $n['type'] = $n['typeId'] = 0; - else if (isset($factions[$n['faction']])) + else { - $n['reactA'] = $factions[$n['faction']]['reactA']; - $n['reactH'] = $factions[$n['faction']]['reactH']; + foreach ($fMaster as &$c) + { + if ($c['map'] != $n['_mapId']) + continue; + + $dist = pow($c['posX'] - $n['_posX'], 2) + pow($c['posY'] - $n['_posY'], 2); + if ($dist > 1000) + continue; + + if (!isset($n['_dist']) || $n['_dist'] < $dist) + { + $n['_dist'] = $dist; + $n['typeId'] = $c['entry']; + $n['reactA'] = $factions[$c['faction']]['reactA'] ?? null; + $n['reactH'] = $factions[$c['faction']]['reactH'] ?? null; + } + } } - unset($n['faction'], $n['origMap'], $n['origPosX'], $n['origPosY'], $n['dist'], $n['scripted']); + // calculate zone pos + if ($points = WorldPosition::toZonePos($n['_mapId'], $n['_posX'], $n['_posY'])) + { + $n['areaId'] = $points[0]['areaId']; + $n['areaX'] = $points[0]['posX']; + $n['areaY'] = $points[0]['posY']; + } + + unset($n['_mapId'], $n['_posX'], $n['_posY'], $n['_dist'], $n['_scripted']); DB::Aowow()->query('INSERT INTO ?_taxinodes VALUES (?a)', array_values($n)); } - return true; } });