Maps/Spawns

* Entities (Objects, NPCs, ect) can now easily be assigned to a different map to be displayed on by clicking their pip on the map
 * Entities with already assigned area (by TrinityCore) that were unable to be matched onto the map are no longer discarded. They'll now show up in appropriate listviews.
 * Entities without already assigned area that are also unable to be matched onto the map now get an area assigned as long as the relationship areaId <=> mapId is unique (read instanced areas)
This commit is contained in:
Sarjuuk
2020-05-26 19:51:53 +02:00
parent 7db841b823
commit 62acd541b2
20 changed files with 542 additions and 72 deletions

View File

@@ -2501,6 +2501,23 @@ CREATE TABLE `aowow_spawns` (
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `aowow_spawns_override`
--
DROP TABLE IF EXISTS `aowow_spawns_override`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `aowow_spawns_override` (
`type` smallint(5) unsigned NOT NULL,
`typeGuid` mediumint(9) NOT NULL,
`areaId` mediumint(8) unsigned NOT NULL,
`floor` mediumint(8) unsigned NOT NULL,
`revision` tinyint(3) unsigned NOT NULL COMMENT 'Aowow revision, when this override was applied',
PRIMARY KEY (`type`, `typeGuid`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `aowow_spell`
--
@@ -3121,7 +3138,7 @@ UNLOCK TABLES;
LOCK TABLES `aowow_dbversion` WRITE;
/*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */;
INSERT INTO `aowow_dbversion` VALUES (1588517066,0,NULL,NULL);
INSERT INTO `aowow_dbversion` VALUES (1590506555,0,NULL,NULL);
/*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */;
UNLOCK TABLES;

View File

@@ -40,22 +40,7 @@ SqlGen::register(new class extends SetupScript
');
foreach ($addData as $id => $ad)
{
// todo (low): unify with spawns function
$queryPost = 'SELECT dm.id, wma.areaId, IFNULL(dm.floor, 0) AS floor, ' .
'100 - ROUND(IF(dm.id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)), 1) AS `posX`, ' .
'100 - ROUND(IF(dm.id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)), 1) AS `posY`, ' .
'((abs(IF(dm.id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)) - 50) / 50) * ' .
' (abs(IF(dm.id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)) - 50) / 50)) AS quality ' .
'FROM dbc_worldmaparea wma ' .
'LEFT JOIN dbc_dungeonmap dm ON dm.mapId = IF(?d AND (wma.mapId NOT IN (0, 1, 530, 571) OR wma.areaId = 4395), wma.mapId, -1) ' .
'WHERE wma.mapId = ?d AND wma.areaId <> 0 ' .
'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) ' .
'ORDER BY quality ASC';
$points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 1, $ad['map']);
if (!$points)
$points = DB::Aowow()->select($queryPost, $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], $ad['posX'], $ad['posX'], $ad['posY'], $ad['posY'], 0, $ad['map']);
$points = Game::worldPosToZonePos($ad['map'], $ad['posX'], $ad['posY']/*, 0*/);
if (!$points)
{
CLI::write(' * AT '.$id.' teleporter endpoint '.CLI::bold($ad['name']).' could not be matched to displayable area [M:'.$ad['map'].'; X:'.$ad['posY'].'; Y:'.$ad['posX'].']', CLI::LOG_WARN);

View File

@@ -19,45 +19,33 @@ SqlGen::register(new class extends SetupScript
private $querys = array(
1 => ['SELECT c.guid, 1 AS "type", c.id AS typeId, c.spawntimesecs AS respawn, c.phaseMask, c.zoneId AS areaId, c.map, IFNULL(ca.path_id, 0) AS pathId, c.position_y AS `posX`, c.position_x AS `posY` ' .
'FROM creature c LEFT JOIN creature_addon ca ON ca.guid = c.guid',
' - assembling creature spawns'],
' - assembling creature spawns', TYPE_NPC],
2 => ['SELECT c.guid, 2 AS "type", c.id AS typeId, ABS(c.spawntimesecs) AS respawn, c.phaseMask, c.zoneId AS areaId, c.map, 0 as pathId, c.position_y AS `posX`, c.position_x AS `posY` ' .
'FROM gameobject c',
' - assembling gameobject spawns'],
' - assembling 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',
' - assembling sound emitter spawns'],
' - assembling sound emitter 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',
' - assembling areatrigger spawns'],
' - assembling areatrigger 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_y AS `posX`, w.location_x AS `posY` ' .
'FROM creature c JOIN script_waypoint w ON c.id = w.entry',
' - assembling waypoints from table script_waypoint'],
' - assembling waypoints from table 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_y AS `posX`, w.position_x AS `posY` ' .
'FROM creature c JOIN waypoints w ON c.id = w.entry',
' - assembling waypoints from table waypoints'],
' - assembling waypoints from table 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_y AS `posX`, w.position_x AS `posY` ' .
'FROM creature c JOIN creature_addon ca ON ca.guid = c.guid JOIN waypoint_data w ON w.id = ca.path_id WHERE ca.path_id <> 0',
' - assembling waypoints from table waypoint_data']
' - assembling waypoints from table waypoint_data', TYPE_NPC]
);
private $queryPost =
'SELECT dm.id, wma.areaId, IFNULL(dm.floor, 0) AS floor, ' .
'100 - ROUND(IF(dm.id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)), 1) AS `posX`, ' .
'100 - ROUND(IF(dm.id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)), 1) AS `posY`, ' .
'((abs(IF(dm.id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)) - 50) / 50) * ' .
' (abs(IF(dm.id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)) - 50) / 50)) AS quality ' .
'FROM dbc_worldmaparea wma ' .
'LEFT JOIN dbc_dungeonmap dm ON dm.mapId = IF(?d AND (wma.mapId NOT IN (0, 1, 530, 571) OR wma.areaId = 4395), wma.mapId, -1) ' .
'WHERE wma.mapId = ?d AND IF(?d, wma.areaId = ?d, wma.areaId <> 0) ' .
'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) ' . // AND (dm.id IS NULL OR ?d) ' .
'ORDER BY quality ASC';
private $alphaMapCache = [];
private function alphaMapCheck(int $areaId, array &$set) : bool
@@ -141,6 +129,13 @@ SqlGen::register(new class extends SetupScript
$t = DB::Aowow()->selectRow('SELECT posX, posY, mapId FROM dbc_taxipathnode tpn WHERE tpn.pathId = ?d AND nodeIdx = 0', $t);
/*********************/
/* get override data */
/*********************/
$overrideData = DB::Aowow()->select('SELECT `type` AS ARRAY_KEY, `typeGuid` AS ARRAY_KEY2, areaId, floor FROM ?_spawns_override');
/**************/
/* perform... */
/**************/
@@ -175,18 +170,34 @@ SqlGen::register(new class extends SetupScript
$spawn['map'] = $transports[$spawn['map']]['mapId'];
}
$points = DB::Aowow()->select($this->queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 1, $spawn['map'], $spawn['areaId'], $spawn['areaId'] /*, $spawn['areaId'] ? 1 : 0*/);
if (!$points) // retry: TC counts pre-instance subareas as instance-maps .. which have no map file
$points = DB::Aowow()->select($this->queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 0, $spawn['map'], 0, 0 /*, 1*/);
if (!$points) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris))
$area = $spawn['areaId'];
$floor = -1;
if (isset($overrideData[$q[2]][$spawn['guid']]))
{
CLI::write('GUID '.$spawn['guid'].($idx < 5 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLI::LOG_WARN);
continue;
$area = $overrideData[$q[2]][$spawn['guid']]['areaId'];
$floor = $overrideData[$q[2]][$spawn['guid']]['floor'];
CLI::write('GUID '.$spawn['guid'].' was manually moved [A:'.$spawn['areaId'].' => '.$area.'; F: '.$floor.']', CLI::LOG_INFO);
}
// if areaId is set, area was determined by TC .. we're fine .. mostly
$final = $spawn['areaId'] ? $points[0] : $this->checkCoords($points);
$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)
{
$area = DB::Aowow()->selectCell('SELECT id FROM dbc_areatable WHERE mapId = ?d AND areaTable = 0', $spawn['map']);
if (!$area)
{
CLI::write('tried to default GUID '.$spawn['guid'].' to instanced area by mapId, but returned empty [M:'.$spawn['map'].']', CLI::LOG_WARN);
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('GUID '.$spawn['guid'].($idx < 5 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$area.'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLI::LOG_WARN);
continue;
}
else // if areaId is set, area was determined by TC .. we're fine .. mostly
$final = $area ? $points[0] : $this->checkCoords($points);
if ($idx < 5)
{

View File

@@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `aowow_spawns_override`;
CREATE TABLE `aowow_spawns_override` (
`type` smallint(5) unsigned NOT NULL,
`typeGuid` mediumint(9) NOT NULL,
`areaId` mediumint(8) unsigned NOT NULL,
`floor` mediumint(8) unsigned NOT NULL,
`revision` tinyint(3) unsigned NOT NULL COMMENT 'Aowow revision, when this override was applied',
PRIMARY KEY (`type`, `typeGuid`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
UPDATE aowow_dbversion SET `sql` = CONCAT(IFNULL(`sql`, ''), ' spawns');