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;
}
});