NPC/MapModes

* try to improve map mode detection for NPCs again...
This commit is contained in:
Sarjuuk
2025-01-27 10:25:44 +01:00
parent 9da1e1575f
commit 40c2c63d1b
8 changed files with 37 additions and 39 deletions

View File

@@ -1004,7 +1004,7 @@ $lang = array(
'react' => "Reaktion", 'react' => "Reaktion",
'worth' => "Wert", 'worth' => "Wert",
'unkPosition' => "Der Aufenthaltsort dieses NPCs ist nicht bekannt.", 'unkPosition' => "Der Aufenthaltsort dieses NPCs ist nicht bekannt.",
'difficultyPH' => "Dieser NPC ist ein Platzhalter für einen anderen Modus von", 'difficultyPH' => 'Dieser NPC ist ein Platzhalter für einen anderen Modus von <a href="?npc=%1$d">%2$s</a>.',
'seat' => "Sitz", 'seat' => "Sitz",
'accessory' => "Zusätze", 'accessory' => "Zusätze",
'accessoryFor' => "Dieser NPC ist Zusatz für Fahrzeug", 'accessoryFor' => "Dieser NPC ist Zusatz für Fahrzeug",

View File

@@ -1005,7 +1005,7 @@ $lang = array(
'react' => "React", 'react' => "React",
'worth' => "Worth", 'worth' => "Worth",
'unkPosition' => "The location of this NPC is unknown.", 'unkPosition' => "The location of this NPC is unknown.",
'difficultyPH' => "This NPC is a placeholder for a different mode of", 'difficultyPH' => 'This NPC is a placeholder for a different mode of <a href="?npc=%1$d">%2$s</a>.',
'seat' => "Seat", 'seat' => "Seat",
'accessory' => "Accessories", 'accessory' => "Accessories",
'accessoryFor' => "This NPC is an accessory for vehicle", 'accessoryFor' => "This NPC is an accessory for vehicle",

View File

@@ -1004,7 +1004,7 @@ $lang = array(
'react' => "Reacción", 'react' => "Reacción",
'worth' => "Valor", 'worth' => "Valor",
'unkPosition' => "No se conoce la ubicación de este PNJ.", 'unkPosition' => "No se conoce la ubicación de este PNJ.",
'difficultyPH' => "Este PNJ es un marcador de posición para un modo diferente de", 'difficultyPH' => 'Este PNJ es un marcador de posición para un modo diferente de <a href="?npc=%1$d">%2$s</a>.',
'seat' => "Asiento", 'seat' => "Asiento",
'accessory' => "Accesorio", 'accessory' => "Accesorio",
'accessoryFor' => "Esta criatura es una accesorio para vehículo", 'accessoryFor' => "Esta criatura es una accesorio para vehículo",

View File

@@ -1004,7 +1004,7 @@ $lang = array(
'react' => "Réaction", 'react' => "Réaction",
'worth' => "Vaut", 'worth' => "Vaut",
'unkPosition' => "L'emplacement de ce PNJ est inconnu.", 'unkPosition' => "L'emplacement de ce PNJ est inconnu.",
'difficultyPH' => "Ce PNJ est un espace réservé pour un autre mode de difficulté.", 'difficultyPH' => 'Ce PNJ est un espace réservé pour un autre mode de difficulté <a href="?npc=%1$d">%2$s</a>.',
'seat' => "Siège", 'seat' => "Siège",
'accessory' => "Passager", 'accessory' => "Passager",
'accessoryFor' => "Ce PNJ est un passager pour un véhicule.", 'accessoryFor' => "Ce PNJ est un passager pour un véhicule.",

View File

@@ -1004,7 +1004,7 @@ $lang = array(
'react' => "Реакция", 'react' => "Реакция",
'worth' => "Деньги", 'worth' => "Деньги",
'unkPosition' => "Местоположение этого НИП неизвестно.", 'unkPosition' => "Местоположение этого НИП неизвестно.",
'difficultyPH' => "[Этот НИП является прототипом для другого режима]", 'difficultyPH' => '[Этот НИП является прототипом для другого режима <a href="?npc=%1$d">%2$s</a>.]',
'seat' => "[Seat]", 'seat' => "[Seat]",
'accessory' => "[Accessory]", 'accessory' => "[Accessory]",
'accessoryFor' => "[This creature is an accessory for vehicle]", 'accessoryFor' => "[This creature is an accessory for vehicle]",

View File

@@ -1004,7 +1004,7 @@ $lang = array(
'react' => "反应", 'react' => "反应",
'worth' => "价值", 'worth' => "价值",
'unkPosition' => "这个NPC的位置未知。", 'unkPosition' => "这个NPC的位置未知。",
'difficultyPH' => "这个NPC是不同模式下的占位符", 'difficultyPH' => '这个NPC是不同模式下的占位符 <a href="?npc=%1$d">%2$s</a>.',
'seat' => "Seat", 'seat' => "Seat",
'accessory' => "附件", 'accessory' => "附件",
'accessoryFor' => "这个NPC是载具的附件", 'accessoryFor' => "这个NPC是载具的附件",

View File

@@ -10,7 +10,7 @@ class NpcPage extends GenericPage
{ {
use TrDetailPage; use TrDetailPage;
protected $placeholder = null; protected $placeholder = [];
protected $accessory = []; protected $accessory = [];
protected $quotes = []; protected $quotes = [];
protected $reputation = []; protected $reputation = [];
@@ -67,7 +67,7 @@ class NpcPage extends GenericPage
$_typeFlags = $this->subject->getField('typeFlags'); $_typeFlags = $this->subject->getField('typeFlags');
$_altIds = []; $_altIds = [];
$_altNPCs = null; $_altNPCs = null;
$placeholder = null; $placeholder = [];
$accessory = []; $accessory = [];
// difficulty entries of self // difficulty entries of self
@@ -83,7 +83,7 @@ class NpcPage extends GenericPage
$_altNPCs = new CreatureList(array(['id', array_keys($_altIds)])); $_altNPCs = new CreatureList(array(['id', array_keys($_altIds)]));
} }
if ($_ = DB::World()->selectCol('SELECT DISTINCT entry FROM vehicle_template_accessory WHERE accessory_entry = ?d', $this->typeId)) if ($_ = DB::World()->selectCol('SELECT DISTINCT `entry` FROM vehicle_template_accessory WHERE `accessory_entry` = ?d', $this->typeId))
{ {
$vehicles = new CreatureList(array(['id', $_])); $vehicles = new CreatureList(array(['id', $_]));
foreach ($vehicles->iterate() as $id => $__) foreach ($vehicles->iterate() as $id => $__)
@@ -92,11 +92,11 @@ class NpcPage extends GenericPage
// try to determine, if it's spawned in a dungeon or raid (shaky at best, if spawned by script) // try to determine, if it's spawned in a dungeon or raid (shaky at best, if spawned by script)
$mapType = 0; $mapType = 0;
if ($maps = DB::Aowow()->selectCol('SELECT DISTINCT areaId from ?_spawns WHERE type = ?d AND typeId = ?d', Type::NPC, $this->typeId)) if ($maps = DB::Aowow()->selectCol('SELECT DISTINCT `areaId` FROM ?_spawns WHERE `type` = ?d AND `typeId` = ?d', Type::NPC, $this->typeId))
{ {
if (count($maps) == 1) // should only exist in one instance if (count($maps) == 1) // should only exist in one instance
{ {
switch (DB::Aowow()->selectCell('SELECT `type` FROM ?_zones WHERE id = ?d', $maps[0])) switch (DB::Aowow()->selectCell('SELECT `type` FROM ?_zones WHERE `id` = ?d', $maps[0]))
{ {
// case MAP_TYPE_DUNGEON: // case MAP_TYPE_DUNGEON:
case MAP_TYPE_DUNGEON_HC: case MAP_TYPE_DUNGEON_HC:
@@ -108,17 +108,15 @@ class NpcPage extends GenericPage
} }
} }
} }
else if ($d = DB::Aowow()->selectCell('SELECT MAX(`difficulty`) FROM ?_loot_link WHERE `npcId` = ?d', $this->typeId)) // npc is difficulty dummy: get max difficulty from parent npc
$mapType = $d > 2 ? 2 : 1; if ($placeholder && ($mt = DB::Aowow()->selectCell('SELECT IF(`difficultyEntry1` = ?d, 1, 2) FROM ?_creature WHERE `difficultyEntry1` = ?d OR `difficultyEntry2` = ?d OR `difficultyEntry3` = ?d', $this->typeId, $this->typeId, $this->typeId, $this->typeId)))
else if ($mt = DB::Aowow()->selectCell('SELECT IF(`difficultyEntry1` = ?d, 1, 2) FROM ?_creature WHERE `difficultyEntry1` = ?d OR `difficultyEntry2` = ?d OR `difficultyEntry3` = ?d', $this->typeId, $this->typeId, $this->typeId, $this->typeId)) $mapType = max($mapType, $mt);
$mapType = $mt; // npc has difficulty dummys: 2+ dummies -> definitely raid (10/25 + hc); 1 dummy -> may be heroic (used here), but may also be 10/25-raid
else if ($_altIds) // not spawned, but has difficultyDummies if ($_altIds)
{ $mapType = max($mapType, count($_altIds) > 1 ? 2 : 1);
if (count($_altIds) > 1) // 3 or more version -> definitly raid (10/25 + hc) // for event encounters a single npc may be reused over multiple difficulties but have different chests assigned
$mapType = 2; if ($d = DB::Aowow()->selectCell('SELECT MAX(`difficulty`) FROM ?_loot_link WHERE `npcId` IN (?a)', array_merge($_altIds, [$this->typeId])))
else // 2 versions; may be Heroic (use this), but may also be 10/25-raid $mapType = max($mapType, $d > 2 ? 2 : 1);
$mapType = 1;
}
/***********/ /***********/
@@ -128,7 +126,7 @@ class NpcPage extends GenericPage
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags')); $infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// Event (ignore events, where the object only gets removed) // Event (ignore events, where the object only gets removed)
if ($_ = DB::World()->selectCol('SELECT DISTINCT ge.eventEntry FROM game_event ge, game_event_creature gec, creature c WHERE ge.eventEntry = gec.eventEntry AND c.guid = gec.guid AND c.id = ?d', $this->typeId)) if ($_ = DB::World()->selectCol('SELECT DISTINCT ge.`eventEntry` FROM game_event ge, game_event_creature gec, creature c WHERE ge.`eventEntry` = gec.`eventEntry` AND c.`guid` = gec.`guid` AND c.`id` = ?d', $this->typeId))
{ {
$this->extendGlobalIds(Type::WORLDEVENT, ...$_); $this->extendGlobalIds(Type::WORLDEVENT, ...$_);
$ev = []; $ev = [];
@@ -725,7 +723,7 @@ class NpcPage extends GenericPage
ksort($sourceFor); ksort($sourceFor);
foreach ($sourceFor as $i => [$lootTpl, $lootId, $tabName, $tabId, $hiddenCols, $note]) foreach ($sourceFor as [$lootTpl, $lootId, $tabName, $tabId, $hiddenCols, $note])
{ {
$creatureLoot = new Loot(); $creatureLoot = new Loot();
if ($creatureLoot->getByContainer($lootTpl, $lootId)) if ($creatureLoot->getByContainer($lootTpl, $lootId))
@@ -828,7 +826,7 @@ class NpcPage extends GenericPage
} }
// tab: passengers // tab: passengers
if ($_ = DB::World()->selectCol('SELECT accessory_entry AS ARRAY_KEY, GROUP_CONCAT(seat_id) FROM vehicle_template_accessory WHERE entry = ?d GROUP BY accessory_entry', $this->typeId)) if ($_ = DB::World()->selectCol('SELECT `accessory_entry` AS ARRAY_KEY, GROUP_CONCAT(`seat_id`) FROM vehicle_template_accessory WHERE `entry` = ?d GROUP BY `accessory_entry`', $this->typeId))
{ {
$passengers = new CreatureList(array(['id', array_keys($_)])); $passengers = new CreatureList(array(['id', array_keys($_)]));
if (!$passengers->error) if (!$passengers->error)
@@ -863,7 +861,7 @@ class NpcPage extends GenericPage
$this->soundIds = array_merge($this->soundIds, SmartAI::getSoundsPlayedForOwner($this->typeId, SAI_SRC_TYPE_CREATURE)); $this->soundIds = array_merge($this->soundIds, SmartAI::getSoundsPlayedForOwner($this->typeId, SAI_SRC_TYPE_CREATURE));
// up to 4 possible displayIds .. for the love of things betwixt, just use the first! // up to 4 possible displayIds .. for the love of things betwixt, just use the first!
$activitySounds = DB::Aowow()->selectRow('SELECT * FROM ?_creature_sounds WHERE id = ?d', $this->subject->getField('displayId1')); $activitySounds = DB::Aowow()->selectRow('SELECT * FROM ?_creature_sounds WHERE `id` = ?d', $this->subject->getField('displayId1'));
array_shift($activitySounds); // remove id-column array_shift($activitySounds); // remove id-column
$this->soundIds = array_merge($this->soundIds, array_values($activitySounds)); $this->soundIds = array_merge($this->soundIds, array_values($activitySounds));
@@ -912,14 +910,14 @@ class NpcPage extends GenericPage
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
} }
private function getRepForId($entries, &$spillover) private function getRepForId(array $entries, array &$spillover) : array
{ {
$rows = DB::World()->select(' $rows = DB::World()->select(
SELECT creature_id AS npc, RewOnKillRepFaction1 AS faction, RewOnKillRepValue1 AS qty, MaxStanding1 AS maxRank, isTeamAward1 AS spillover 'SELECT `creature_id` AS "npc", `RewOnKillRepFaction1` AS "faction", `RewOnKillRepValue1` AS "qty", `MaxStanding1` AS "maxRank", `isTeamAward1` AS "spillover"
FROM creature_onkill_reputation WHERE creature_id IN (?a) AND RewOnKillRepFaction1 > 0 UNION FROM creature_onkill_reputation WHERE `creature_id` IN (?a) AND `RewOnKillRepFaction1` > 0 UNION
SELECT creature_id AS npc, RewOnKillRepFaction2 As faction, RewOnKillRepValue2 AS qty, MaxStanding2 AS maxRank, isTeamAward2 AS spillover SELECT `creature_id` AS "npc", `RewOnKillRepFaction2` AS "faction", `RewOnKillRepValue2` AS "qty", `MaxStanding2` AS "maxRank", `isTeamAward2` AS "spillover"
FROM creature_onkill_reputation WHERE creature_id IN (?a) AND RewOnKillRepFaction2 > 0', FROM creature_onkill_reputation WHERE `creature_id` IN (?a) AND `RewOnKillRepFaction2` > 0',
(array)$entries, (array)$entries $entries, $entries
); );
$factions = new FactionList(array(['id', array_column($rows, 'faction')])); $factions = new FactionList(array(['id', array_column($rows, 'faction')]));
@@ -938,7 +936,7 @@ class NpcPage extends GenericPage
'cap' => $row['maxRank'] && $row['maxRank'] < REP_EXALTED ? Lang::game('rep', $row['maxRank']) : null 'cap' => $row['maxRank'] && $row['maxRank'] < REP_EXALTED ? Lang::game('rep', $row['maxRank']) : null
); );
$cuRate = DB::World()->selectCell('SELECT creature_rate FROM reputation_reward_rate WHERE creature_rate <> 1 AND faction = ?d', $row['faction']); $cuRate = DB::World()->selectCell('SELECT `creature_rate` FROM reputation_reward_rate WHERE `creature_rate` <> 1 AND `faction` = ?d', $row['faction']);
if ($cuRate !== null) if ($cuRate !== null)
$set['qty'][1] = $set['qty'][0] * ($cuRate - 1); $set['qty'][1] = $set['qty'][0] * ($cuRate - 1);
@@ -957,13 +955,13 @@ class NpcPage extends GenericPage
return $result; return $result;
} }
private function getOnKillRep($dummyIds, $mapType) private function getOnKillRep(array $dummyIds, int $mapType) : array
{ {
$spilledParents = []; $spilledParents = [];
$reputation = []; $reputation = [];
// base NPC // base NPC
if ($base = $this->getRepForId($this->typeId, $spilledParents)) if ($base = $this->getRepForId([$this->typeId], $spilledParents))
$reputation[] = [Lang::npc('modes', 1, 0), $base]; $reputation[] = [Lang::npc('modes', 1, 0), $base];
// difficulty dummys // difficulty dummys
@@ -1019,7 +1017,7 @@ class NpcPage extends GenericPage
return $reputation; return $reputation;
} }
private function getQuotes() private function getQuotes() : array
{ {
[$quotes, $nQuotes, $soundIds] = Game::getQuotesForCreature($this->typeId, true, $this->subject->getField('name', true)); [$quotes, $nQuotes, $soundIds] = Game::getQuotesForCreature($this->typeId, true, $this->subject->getField('name', true));

View File

@@ -26,8 +26,8 @@ if ($this->accessory):
echo ".</div>\n"; echo ".</div>\n";
endif; endif;
if (is_array($this->placeholder)): if ($this->placeholder):
echo ' <div>'.Lang::npc('difficultyPH').' <a href="?npc='.$this->placeholder[0].'">'.$this->placeholder[1]."</a>.</div>\n"; echo ' <div>'.Lang::npc('difficultyPH', $this->placeholder)."</div>\n";
?> ?>
<div class="pad"></div> <div class="pad"></div>
<?php <?php