mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
SmarAI/Lookups
* unify lookups in functional groups * move code to class SmartAI
This commit is contained in:
@@ -19,6 +19,302 @@ class SmartAI
|
|||||||
private $quotes = [];
|
private $quotes = [];
|
||||||
private $summons = null;
|
private $summons = null;
|
||||||
|
|
||||||
|
/*********************/
|
||||||
|
/* Lookups by action */
|
||||||
|
/*********************/
|
||||||
|
|
||||||
|
public static function getOwnerOfNPCSummon(int $npcId, int $typeFilter = 0) : array
|
||||||
|
{
|
||||||
|
if ($npcId <= 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$lookup = array(
|
||||||
|
SAI_ACTION_SUMMON_CREATURE => [1 => $npcId],
|
||||||
|
SAI_ACTION_MOUNT_TO_ENTRY_OR_MODEL => [1 => $npcId]
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($npcGuids = DB::Aowow()->selectCol('SELECT guid FROM ?_spawns WHERE `type` = ?d AND `typeId` = ?d', TYPE_NPC, $npcId))
|
||||||
|
if ($groups = DB::World()->selectCol('SELECT `groupId` FROM spawn_group WHERE `spawnType` = 0 AND `spawnId` IN (?a)', $npcGuids))
|
||||||
|
foreach ($groups as $g)
|
||||||
|
$lookup[SAI_ACTION_SPAWN_SPAWNGROUP][1] = $g;
|
||||||
|
|
||||||
|
$result = self::getActionOwner($lookup, $typeFilter);
|
||||||
|
|
||||||
|
// can skip lookups for SAI_ACTION_SUMMON_CREATURE_GROUP as creature_summon_groups already contains summoner info
|
||||||
|
if ($sgs = DB::World()->select('SELECT `summonerType` AS "0", `summonerId` AS "1" FROM creature_summon_groups WHERE `entry` = ?d', $npcId))
|
||||||
|
foreach ($sgs as [$type, $typeId])
|
||||||
|
$result[$type][] = $typeId;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getOwnerOfObjectSummon(int $objectId, int $typeFilter = 0) : array
|
||||||
|
{
|
||||||
|
if ($objectId <= 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$lookup = array(
|
||||||
|
SAI_ACTION_SUMMON_GO => [1 => $objectId]
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($objGuids = DB::Aowow()->selectCol('SELECT guid FROM ?_spawns WHERE `type` = ?d AND `typeId` = ?d', TYPE_OBJECT, $objectId))
|
||||||
|
if ($groups = DB::World()->selectCol('SELECT `groupId` FROM spawn_group WHERE `spawnType` = 1 AND `spawnId` IN (?a)', $objGuids))
|
||||||
|
foreach ($groups as $g)
|
||||||
|
$lookup[SAI_ACTION_SPAWN_SPAWNGROUP][1] = $g;
|
||||||
|
|
||||||
|
return self::getActionOwner($lookup, $typeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getOwnerOfSpellCast(int $spellId, int $typeFilter = 0) : array
|
||||||
|
{
|
||||||
|
if ($spellId <= 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$lookup = array(
|
||||||
|
SAI_ACTION_CAST => [1 => $spellId],
|
||||||
|
SAI_ACTION_ADD_AURA => [1 => $spellId],
|
||||||
|
SAI_ACTION_SELF_CAST => [1 => $spellId],
|
||||||
|
SAI_ACTION_CROSS_CAST => [1 => $spellId],
|
||||||
|
SAI_ACTION_INVOKER_CAST => [1 => $spellId]
|
||||||
|
);
|
||||||
|
|
||||||
|
return self::getActionOwner($lookup, $typeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getOwnerOfSoundPlayed(int $soundId, int $typeFilter = 0) : array
|
||||||
|
{
|
||||||
|
if ($soundId <= 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$lookup = array(
|
||||||
|
SAI_ACTION_SOUND => [1 => $soundId]
|
||||||
|
);
|
||||||
|
|
||||||
|
return self::getActionOwner($lookup, $typeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getActionOwner(array $lookup, int $typeFilter = 0) : array
|
||||||
|
{
|
||||||
|
$qParts = [];
|
||||||
|
$result = [];
|
||||||
|
$genLimit = $talLimit = [];
|
||||||
|
switch ($typeFilter)
|
||||||
|
{
|
||||||
|
case TYPE_NPC:
|
||||||
|
$genLimit = [SAI_SRC_TYPE_CREATURE, SAI_SRC_TYPE_ACTIONLIST];
|
||||||
|
$talLimit = [SAI_SRC_TYPE_CREATURE];
|
||||||
|
break;
|
||||||
|
case TYPE_OBJECT:
|
||||||
|
$genLimit = [SAI_SRC_TYPE_OBJECT, SAI_SRC_TYPE_ACTIONLIST];
|
||||||
|
$talLimit = [SAI_SRC_TYPE_OBJECT];
|
||||||
|
break;
|
||||||
|
case TYPE_AREATRIGGER:
|
||||||
|
$genLimit = [SAI_SRC_TYPE_AREATRIGGER, SAI_SRC_TYPE_ACTIONLIST];
|
||||||
|
$talLimit = [SAI_SRC_TYPE_AREATRIGGER];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($lookup as $action => $params)
|
||||||
|
{
|
||||||
|
$aq = '(`action_type` = '.(int)$action.' AND (';
|
||||||
|
$pq = [];
|
||||||
|
foreach ($params as $idx => $p)
|
||||||
|
$pq[] = '`action_param'.(int)$idx.'` = '.(int)$p;
|
||||||
|
|
||||||
|
if ($pq)
|
||||||
|
$qParts[] = $aq.implode(' OR ', $pq).'))';
|
||||||
|
}
|
||||||
|
|
||||||
|
$smartS = DB::World()->select(sprintf('SELECT `source_type` AS "0", `entryOrGUID` AS "1" FROM smart_scripts WHERE (%s){ AND `source_type` IN (?a)} GROUP BY "0", "1"', $qParts ? implode(' OR ', $qParts) : '0'), $genLimit ?: DBSIMPLE_SKIP);
|
||||||
|
|
||||||
|
// filter for TAL shenanigans
|
||||||
|
if ($smartTAL = array_filter($smartS, function ($x) {return $x[0] == SAI_SRC_TYPE_ACTIONLIST;}))
|
||||||
|
{
|
||||||
|
$smartS = array_diff_key($smartS, $smartTAL);
|
||||||
|
|
||||||
|
$q = [];
|
||||||
|
foreach ($smartTAL as [, $eog])
|
||||||
|
{
|
||||||
|
// SAI_ACTION_CALL_TIMED_ACTIONLIST
|
||||||
|
$q[] = '`action_type` = '.SAI_ACTION_CALL_TIMED_ACTIONLIST.' AND `action_param1` = '.$eog;
|
||||||
|
|
||||||
|
// SAI_ACTION_CALL_RANDOM_TIMED_ACTIONLIST
|
||||||
|
$q[] = '`action_type` = '.SAI_ACTION_CALL_RANDOM_TIMED_ACTIONLIST.' AND (`action_param1` = '.$eog.' OR `action_param2` = '.$eog.' OR `action_param3` = '.$eog.' OR `action_param4` = '.$eog.' OR `action_param5` = '.$eog.')';
|
||||||
|
|
||||||
|
// SAI_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST
|
||||||
|
$q[] = '`action_type` = '.SAI_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST.' AND `action_param1` <= '.$eog.' AND `action_param2` >= '.$eog;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_ = DB::World()->select(sprintf('SELECT `source_type` AS "0", `entryOrGUID` AS "1" FROM smart_scripts WHERE ((%s)){ AND `source_type` IN (?a)} GROUP BY "0", "1"', $q ? implode(') OR (', $q) : '0'), $talLimit ?: DBSIMPLE_SKIP))
|
||||||
|
$smartS = array_merge($smartS, $_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter guids for entries
|
||||||
|
if ($smartG = array_filter($smartS, function ($x) {return $x[1] < 0;}))
|
||||||
|
{
|
||||||
|
$smartS = array_diff_key($smartS, $smartG);
|
||||||
|
|
||||||
|
$q = [];
|
||||||
|
foreach ($smartG as [$st, $eog])
|
||||||
|
{
|
||||||
|
if ($st == SAI_SRC_TYPE_CREATURE)
|
||||||
|
$q[] = '`type` = '.TYPE_NPC.' AND `guid` = '.-$eog;
|
||||||
|
else if ($st == SAI_SRC_TYPE_OBJECT)
|
||||||
|
$q[] = '`type` = '.TYPE_OBJECT.' AND `guid` = '.-$eog;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($q)
|
||||||
|
$result = DB::Aowow()->selectCol(sprintf('SELECT `type` AS ARRAY_KEY, `typeId` FROM ?_spawns WHERE (%s)', implode(') OR (', $q)));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($smartS as [$st, $eog])
|
||||||
|
{
|
||||||
|
if ($st == SAI_SRC_TYPE_CREATURE)
|
||||||
|
$result[TYPE_NPC][] = $eog;
|
||||||
|
else if ($st == SAI_SRC_TYPE_OBJECT)
|
||||||
|
$result[TYPE_OBJECT][] = $eog;
|
||||||
|
else if ($st == SAI_SRC_TYPE_AREATRIGGER)
|
||||||
|
$result[TYPE_AREATRIGGER][] = $eog;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************/
|
||||||
|
/* Lookups by owner */
|
||||||
|
/********************/
|
||||||
|
|
||||||
|
public static function getNPCSummonsForOwner(int $entry, int $srcType = SAI_SRC_TYPE_CREATURE) : array
|
||||||
|
{
|
||||||
|
// action => paramIdx with npcIds/spawnGoupIds
|
||||||
|
$lookup = array(
|
||||||
|
SAI_ACTION_SUMMON_CREATURE => [1],
|
||||||
|
SAI_ACTION_MOUNT_TO_ENTRY_OR_MODEL => [1],
|
||||||
|
SAI_ACTION_SPAWN_SPAWNGROUP => [1]
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = self::getOwnerAction($srcType, $entry, $lookup);
|
||||||
|
|
||||||
|
// can skip lookups for SAI_ACTION_SUMMON_CREATURE_GROUP as creature_summon_groups already contains summoner info
|
||||||
|
if ($srcType == SAI_SRC_TYPE_CREATURE || $srcType == SAI_SRC_TYPE_OBJECT)
|
||||||
|
{
|
||||||
|
$st = $srcType == SAI_SRC_TYPE_CREATURE ? 0 : 1;// 0:SUMMONER_TYPE_CREATURE; 1:SUMMONER_TYPE_GAMEOBJECT
|
||||||
|
if ($csg = DB::World()->selectCol('SELECT `entry` FROM creature_summon_groups WHERE `summonerType` = ?d AND `summonerId` = ?d', $st, $entry))
|
||||||
|
$result = array_merge($result, $csg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($moreInfo[SAI_ACTION_SPAWN_SPAWNGROUP]))
|
||||||
|
{
|
||||||
|
$grp = $moreInfo[SAI_ACTION_SPAWN_SPAWNGROUP];
|
||||||
|
if ($sgs = DB::World()->selectCol('SELECT `spawnId` FROM spawn_group WHERE `spawnType` = ?d AND `groupId` IN (?a)', 0 /*0:SUMMONER_TYPE_CREATURE*/, $grp))
|
||||||
|
if ($ids = DB::Aowow()->selectCol('SELECT DISTINCT `typeId` FROM ?_spawns WHERE `type` = ?d AND `guid` IN (?a)', TYPE_NPC, $sgs))
|
||||||
|
$result = array_merge($result, $ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getObjectSummonsForOwner(int $entry, int $srcType = SAI_SRC_TYPE_CREATURE) : array
|
||||||
|
{
|
||||||
|
// action => paramIdx with gobIds/spawnGoupIds
|
||||||
|
$lookup = array(
|
||||||
|
SAI_ACTION_SUMMON_GO => [1],
|
||||||
|
SAI_ACTION_SPAWN_SPAWNGROUP => [1]
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = self::getOwnerAction($srcType, $entry, $lookup, $moreInfo);
|
||||||
|
|
||||||
|
if (!empty($moreInfo[SAI_ACTION_SPAWN_SPAWNGROUP]))
|
||||||
|
{
|
||||||
|
$grp = $moreInfo[SAI_ACTION_SPAWN_SPAWNGROUP];
|
||||||
|
if ($sgs = DB::World()->selectCol('SELECT `spawnId` FROM spawn_group WHERE `spawnType` = ?d AND `groupId` IN (?a)', 1 /*1:SUMMONER_TYPE_GAMEOBJECT*/, $grp))
|
||||||
|
if ($ids = DB::Aowow()->selectCol('SELECT DISTINCT `typeId` FROM ?_spawns WHERE `type` = ?d AND `guid` IN (?a)', TYPE_OBJECT, $sgs))
|
||||||
|
$result = array_merge($result, $ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSpellCastsForOwner(int $entry, int $srcType = SAI_SRC_TYPE_CREATURE) : array
|
||||||
|
{
|
||||||
|
// action => paramIdx with spellIds
|
||||||
|
$lookup = array(
|
||||||
|
SAI_SRC_TYPE_CREATURE => [1],
|
||||||
|
SAI_ACTION_CAST => [1],
|
||||||
|
SAI_ACTION_ADD_AURA => [1],
|
||||||
|
SAI_ACTION_INVOKER_CAST => [1],
|
||||||
|
SAI_ACTION_CROSS_CAST => [1]
|
||||||
|
);
|
||||||
|
|
||||||
|
return self::getOwnerAction($srcType, $entry, $lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSoundsPlayedForOwner(int $entry, int $srcType = SAI_SRC_TYPE_CREATURE) : array
|
||||||
|
{
|
||||||
|
// action => paramIdx with soundIds
|
||||||
|
$lookup = [SAI_ACTION_SOUND => [1]];
|
||||||
|
|
||||||
|
return self::getOwnerAction($srcType, $entry, $lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getOwnerAction(int $sourceType, int $entry, array $lookup, ?array $moreInfo = []) : array
|
||||||
|
{
|
||||||
|
if ($entry < 0) // please not individual entities :(
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$smartScripts = DB::World()->select('SELECT action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6 FROM smart_scripts WHERE source_type = ?d AND action_type IN (?a) AND entryOrGUID = ?d', $sourceType, array_merge(array_keys($lookup), SAI_ACTION_ALL_TIMED_ACTION_LISTS), $entry);
|
||||||
|
$smartResults = [];
|
||||||
|
$smartTALs = [];
|
||||||
|
foreach ($smartScripts as $s)
|
||||||
|
{
|
||||||
|
if ($e['action_type'] == SAI_ACTION_SPAWN_SPAWNGROUP)
|
||||||
|
$moreInfo[SAI_ACTION_SPAWN_SPAWNGROUP][] = $e['action_param'.$i];
|
||||||
|
else if (in_array($s['action_type'], array_keys($lookup)))
|
||||||
|
{
|
||||||
|
foreach ($lookup[$s['action_type']] as $p)
|
||||||
|
$smartResults[] = $s['action_param'.$p];
|
||||||
|
}
|
||||||
|
else if ($s['action_type'] == SAI_ACTION_CALL_TIMED_ACTIONLIST)
|
||||||
|
$smartTALs[] = $s['action_param1'];
|
||||||
|
else if ($s['action_type'] == SAI_ACTION_CALL_RANDOM_TIMED_ACTIONLIST)
|
||||||
|
{
|
||||||
|
for ($i = 1; $i < 7; $i++)
|
||||||
|
if ($s['action_param'.$i])
|
||||||
|
$smartTALs[] = $s['action_param'.$i];
|
||||||
|
}
|
||||||
|
else if ($s['action_type'] == SAI_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST)
|
||||||
|
{
|
||||||
|
for ($i = $s['action_param1']; $i <= $s['action_param2']; $i++)
|
||||||
|
$smartTALs[] = $i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($smartTALs)
|
||||||
|
{
|
||||||
|
if ($TALActList = DB::World()->selectCol('SELECT action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6 FROM smart_scripts WHERE source_type = ?d AND action_type IN (?a) AND entryOrGUID IN (?a)', SAI_SRC_TYPE_ACTIONLIST, $lookup, $smartTALs))
|
||||||
|
{
|
||||||
|
foreach ($TALActList as $e)
|
||||||
|
{
|
||||||
|
foreach ($lookup[$e['action_type']] as $i)
|
||||||
|
{
|
||||||
|
if ($e['action_type'] == SAI_ACTION_SPAWN_SPAWNGROUP)
|
||||||
|
$moreInfo[SAI_ACTION_SPAWN_SPAWNGROUP][] = $e['action_param'.$i];
|
||||||
|
else
|
||||||
|
$smartResults[] = $e['action_param'.$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $smartResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************/
|
||||||
|
/* Structured Lisview Display */
|
||||||
|
/******************************/
|
||||||
|
|
||||||
public function __construct(int $srcType, int $entry, array $miscData = [])
|
public function __construct(int $srcType, int $entry, array $miscData = [])
|
||||||
{
|
{
|
||||||
$this->srcType = $srcType;
|
$this->srcType = $srcType;
|
||||||
@@ -167,11 +463,12 @@ class SmartAI
|
|||||||
return $this->jsGlobals;
|
return $this->jsGlobals;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTabs() : array
|
public function getTabs() : array
|
||||||
{
|
{
|
||||||
return $this->tabs;
|
return $this->tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function &iterate() : iterable
|
private function &iterate() : iterable
|
||||||
{
|
{
|
||||||
reset($this->rawData);
|
reset($this->rawData);
|
||||||
|
|||||||
@@ -408,36 +408,8 @@ class NpcPage extends GenericPage
|
|||||||
/**************/
|
/**************/
|
||||||
|
|
||||||
// tab: abilities / tab_controlledabilities (dep: VehicleId)
|
// tab: abilities / tab_controlledabilities (dep: VehicleId)
|
||||||
// SMART_SCRIPT_TYPE_CREATURE = 0; SMART_ACTION_CAST = 11; SMART_ACTION_ADD_AURA = 75; SMART_ACTION_INVOKER_CAST = 85; SMART_ACTION_CROSS_CAST = 86
|
|
||||||
$smartScripts = DB::World()->select('SELECT action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6 FROM smart_scripts WHERE source_type = ?d AND action_type IN (?a) AND entryOrGUID = ?d', SAI_SRC_TYPE_CREATURE, array_merge(SAI_ACTION_ALL_SPELLCASTS, SAI_ACTION_ALL_TIMED_ACTION_LISTS), $this->typeId);
|
|
||||||
$smartSpells = [];
|
|
||||||
$smartTALs = [];
|
|
||||||
foreach ($smartScripts as $s)
|
|
||||||
{
|
|
||||||
if (in_array($s['action_type'], SAI_ACTION_ALL_SPELLCASTS))
|
|
||||||
$smartSpells[] = $s['action_param1'];
|
|
||||||
else if ($s['action_type'] == SAI_ACTION_CALL_TIMED_ACTIONLIST)
|
|
||||||
$smartTALs[] = $s['action_param1'];
|
|
||||||
else if ($s['action_type'] == SAI_ACTION_CALL_RANDOM_TIMED_ACTIONLIST)
|
|
||||||
{
|
|
||||||
for ($i = 1; $i < 7; $i++)
|
|
||||||
if ($s['action_param'.$i])
|
|
||||||
$smartTALs[] = $s['action_param'.$i];
|
|
||||||
}
|
|
||||||
else if ($s['action_type'] == SAI_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST)
|
|
||||||
{
|
|
||||||
for ($i = $s['action_param1']; $i <= $s['action_param2']; $i++)
|
|
||||||
$smartTALs[] = $i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
var_dump($s);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($smartTALs)
|
|
||||||
if ($_ = DB::World()->selectCol('SELECT action_param1 FROM smart_scripts WHERE source_type = ?d AND action_type IN (?a) AND entryOrGUID IN (?a)', SAI_SRC_TYPE_ACTIONLIST, SAI_ACTION_ALL_SPELLCASTS, $smartTALs))
|
|
||||||
$smartSpells = array_merge($smartSpells, $_);
|
|
||||||
|
|
||||||
$tplSpells = [];
|
$tplSpells = [];
|
||||||
|
$smartSpells = [];
|
||||||
$conditions = ['OR'];
|
$conditions = ['OR'];
|
||||||
|
|
||||||
for ($i = 1; $i < 9; $i++)
|
for ($i = 1; $i < 9; $i++)
|
||||||
@@ -447,7 +419,7 @@ class NpcPage extends GenericPage
|
|||||||
if ($tplSpells)
|
if ($tplSpells)
|
||||||
$conditions[] = ['id', $tplSpells];
|
$conditions[] = ['id', $tplSpells];
|
||||||
|
|
||||||
if ($smartSpells)
|
if ($smartSpells = SmartAI::getSpellCastsForOwner($this->typeId, SAI_SRC_TYPE_CREATURE))
|
||||||
$conditions[] = ['id', $smartSpells];
|
$conditions[] = ['id', $smartSpells];
|
||||||
|
|
||||||
// Pet-Abilities
|
// Pet-Abilities
|
||||||
@@ -511,7 +483,7 @@ class NpcPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tab: summoned by
|
// tab: summoned by [spell]
|
||||||
$conditions = array(
|
$conditions = array(
|
||||||
'OR',
|
'OR',
|
||||||
['AND', ['effect1Id', [28, 56, 112]], ['effect1MiscValue', $this->typeId]],
|
['AND', ['effect1Id', [28, 56, 112]], ['effect1MiscValue', $this->typeId]],
|
||||||
@@ -519,18 +491,51 @@ class NpcPage extends GenericPage
|
|||||||
['AND', ['effect3Id', [28, 56, 112]], ['effect3MiscValue', $this->typeId]]
|
['AND', ['effect3Id', [28, 56, 112]], ['effect3MiscValue', $this->typeId]]
|
||||||
);
|
);
|
||||||
|
|
||||||
$summoned = new SpellList($conditions);
|
$sbSpell = new SpellList($conditions);
|
||||||
if (!$summoned->error)
|
if (!$sbSpell->error)
|
||||||
{
|
{
|
||||||
$this->extendGlobalData($summoned->getJSGlobals());
|
$this->extendGlobalData($sbSpell->getJSGlobals());
|
||||||
|
|
||||||
$this->lvTabs[] = ['spell', array(
|
$this->lvTabs[] = ['spell', array(
|
||||||
'data' => array_values($summoned->getListviewData()),
|
'data' => array_values($sbSpell->getListviewData()),
|
||||||
'name' => '$LANG.tab_summonedby',
|
'name' => '$LANG.tab_summonedby',
|
||||||
'id' => 'summoned-by'
|
'id' => 'summoned-by-spell'
|
||||||
)];
|
)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tab: summoned by [NPC]
|
||||||
|
$sb = SmartAI::getOwnerOfNPCSummon($this->typeId);
|
||||||
|
if (!empty($sb[TYPE_NPC]))
|
||||||
|
{
|
||||||
|
$sbNPC = new CreatureList(array(['id', $sb[TYPE_NPC]]));
|
||||||
|
if (!$sbNPC->error)
|
||||||
|
{
|
||||||
|
$this->extendGlobalData($sbNPC->getJSGlobals());
|
||||||
|
|
||||||
|
$this->lvTabs[] = ['creature', array(
|
||||||
|
'data' => array_values($sbNPC->getListviewData()),
|
||||||
|
'name' => '$LANG.tab_summonedby',
|
||||||
|
'id' => 'summoned-by-npc'
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tab: summoned by [Object]
|
||||||
|
if (!empty($sb[TYPE_OBJECT]))
|
||||||
|
{
|
||||||
|
$sbGO = new GameObjectList(array(['id', $sb[TYPE_OBJECT]]));
|
||||||
|
if (!$sbGO->error)
|
||||||
|
{
|
||||||
|
$this->extendGlobalData($sbGO->getJSGlobals());
|
||||||
|
|
||||||
|
$this->lvTabs[] = ['object', array(
|
||||||
|
'data' => array_values($sbGO->getListviewData()),
|
||||||
|
'name' => '$LANG.tab_summonedby',
|
||||||
|
'id' => 'summoned-by-object'
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// tab: teaches
|
// tab: teaches
|
||||||
if ($this->subject->getField('npcflag') & NPC_FLAG_TRAINER)
|
if ($this->subject->getField('npcflag') & NPC_FLAG_TRAINER)
|
||||||
{
|
{
|
||||||
@@ -865,27 +870,7 @@ class NpcPage extends GenericPage
|
|||||||
* Dialogue VO => creature_text
|
* Dialogue VO => creature_text
|
||||||
* onClick VO => CreatureDisplayInfo.dbc => NPCSounds.dbc
|
* onClick VO => CreatureDisplayInfo.dbc => NPCSounds.dbc
|
||||||
*/
|
*/
|
||||||
$ssActionLists = DB::World()->select('SELECT action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6 FROM smart_scripts WHERE entryorguid = ?d AND source_type = 0 AND action_type IN (80, 87, 88)', $this->typeId);
|
$this->soundIds = array_merge($this->soundIds, SmartAI::getSoundsPlayedForOwner($this->typeId, SAI_SRC_TYPE_CREATURE));
|
||||||
$actionListIds = [];
|
|
||||||
foreach ($ssActionLists as $sal)
|
|
||||||
{
|
|
||||||
$iMax = 0;
|
|
||||||
switch ($sal['action_type'])
|
|
||||||
{
|
|
||||||
case 80: $iMax = 1; break;
|
|
||||||
case 87: $iMax = 6; break;
|
|
||||||
case 88: $iMax = 2; break;
|
|
||||||
default: continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 1; $i <= $iMax; $i++)
|
|
||||||
if ($sal['action_param'.$i])
|
|
||||||
$actionListIds[] = $sal['action_param'.$i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// not going for a per guid basis. The infos are nested enough as is.
|
|
||||||
$smartScripts = DB::World()->selectCol('SELECT action_param1 FROM smart_scripts WHERE action_type = 4 AND ((source_type = 0 AND entryorguid = ?d) { OR (source_type = 9 AND entryorguid IN (?a)) } )', $this->typeId, $actionListIds ?: DBSIMPLE_SKIP);
|
|
||||||
$this->soundIds = array_merge($this->soundIds, $smartScripts);
|
|
||||||
|
|
||||||
// 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'));
|
||||||
|
|||||||
@@ -269,39 +269,11 @@ class SoundPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ssQuery = '
|
|
||||||
SELECT
|
|
||||||
source_type AS ARRAY_KEY,
|
|
||||||
entryorguid AS ARRAY_KEY2,
|
|
||||||
0
|
|
||||||
FROM
|
|
||||||
smart_scripts
|
|
||||||
WHERE
|
|
||||||
(action_type = 4 AND action_param1 = ?d AND source_type <> 9) {
|
|
||||||
OR (action_type = 80 AND (action_param1 IN (?a)))
|
|
||||||
OR (action_type = 87 AND (action_param1 IN (?a) OR action_param2 IN (?a) OR action_param3 IN (?a) OR action_param4 IN (?a) OR action_param5 IN (?a) OR action_param6 IN (?a)))
|
|
||||||
OR (action_type = 88 AND (action_param1 IN (?a) OR action_param2 IN (?a)))
|
|
||||||
}
|
|
||||||
';
|
|
||||||
|
|
||||||
$ssActionLists = DB::World()->selectCol('SELECT entryorguid FROM smart_scripts WHERE action_type = 4 AND action_param1 = ?d AND source_type = 9', $this->typeId);
|
|
||||||
$smartScripts = DB::World()->selectCol($ssQuery, $this->typeId, $ssActionLists ?: DBSIMPLE_SKIP, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists);
|
|
||||||
|
|
||||||
$creatureIds = DB::World()->selectCol('SELECT ct.CreatureID FROM creature_text ct LEFT JOIN broadcast_text bct ON bct.ID = ct.BroadCastTextId WHERE bct.SoundEntriesID = ?d OR ct.Sound = ?d', $this->typeId, $this->typeId);
|
$creatureIds = DB::World()->selectCol('SELECT ct.CreatureID FROM creature_text ct LEFT JOIN broadcast_text bct ON bct.ID = ct.BroadCastTextId WHERE bct.SoundEntriesID = ?d OR ct.Sound = ?d', $this->typeId, $this->typeId);
|
||||||
foreach ($smartScripts as $source => $ids)
|
|
||||||
{
|
|
||||||
switch($source)
|
|
||||||
{
|
|
||||||
case 0: // npc
|
|
||||||
// filter for guids (id < 0)
|
|
||||||
$creatureIds = array_merge($creatureIds, array_keys(array_filter($ids, function($x) { return $x > 0; })) );
|
|
||||||
break;
|
|
||||||
case 1: // gameobject
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// can objects or areatrigger play sound...?
|
||||||
|
if ($goosp = SmartAI::getOwnerOfSoundPlayed($this->typeId, TYPE_NPC))
|
||||||
|
$creatureIds = array_merge($creatureIds, $goosp[TYPE_NPC]);
|
||||||
|
|
||||||
// tab: NPC (dialogues...?, generic creature sound)
|
// tab: NPC (dialogues...?, generic creature sound)
|
||||||
// skipping (always empty): transforms, footsteps
|
// skipping (always empty): transforms, footsteps
|
||||||
|
|||||||
@@ -325,6 +325,8 @@ class SpellPage extends GenericPage
|
|||||||
|
|
||||||
$j = [null, 'A', 'B', 'C'];
|
$j = [null, 'A', 'B', 'C'];
|
||||||
|
|
||||||
|
$ubSAI = SmartAI::getOwnerOfSpellCast($this->typeId);
|
||||||
|
|
||||||
// tab: abilities [of shapeshift form]
|
// tab: abilities [of shapeshift form]
|
||||||
for ($i = 1; $i < 4; $i++)
|
for ($i = 1; $i < 4; $i++)
|
||||||
{
|
{
|
||||||
@@ -610,8 +612,8 @@ class SpellPage extends GenericPage
|
|||||||
['onUseSpell', $this->subject->id], ['onSuccessSpell', $this->subject->id],
|
['onUseSpell', $this->subject->id], ['onSuccessSpell', $this->subject->id],
|
||||||
['auraSpell', $this->subject->id], ['triggeredSpell', $this->subject->id]
|
['auraSpell', $this->subject->id], ['triggeredSpell', $this->subject->id]
|
||||||
);
|
);
|
||||||
if ($_ = $this->ubSmartScript(TYPE_OBJECT))
|
if (!empty($ubSAI[TYPE_OBJECT]))
|
||||||
$conditions[] = ['id', $_];
|
$conditions[] = ['id', $ubSAI[TYPE_OBJECT]];
|
||||||
|
|
||||||
$ubObjects = new GameObjectList($conditions);
|
$ubObjects = new GameObjectList($conditions);
|
||||||
if (!$ubObjects->error)
|
if (!$ubObjects->error)
|
||||||
@@ -628,9 +630,9 @@ class SpellPage extends GenericPage
|
|||||||
// tab: used by - areatrigger
|
// tab: used by - areatrigger
|
||||||
if (User::isInGroup(U_GROUP_EMPLOYEE))
|
if (User::isInGroup(U_GROUP_EMPLOYEE))
|
||||||
{
|
{
|
||||||
if ($_ = $this->ubSmartScript(TYPE_AREATRIGGER))
|
if (!empty($ubSAI[TYPE_AREATRIGGER]))
|
||||||
{
|
{
|
||||||
$ubTriggers = new AreaTriggerList(array(['id', $_]));
|
$ubTriggers = new AreaTriggerList(array(['id', $ubSAI[TYPE_AREATRIGGER]]));
|
||||||
if (!$ubTriggers->error)
|
if (!$ubTriggers->error)
|
||||||
{
|
{
|
||||||
$this->lvTabs[] = ['areatrigger', array(
|
$this->lvTabs[] = ['areatrigger', array(
|
||||||
@@ -845,8 +847,8 @@ class SpellPage extends GenericPage
|
|||||||
['spell1', $this->typeId], ['spell2', $this->typeId], ['spell3', $this->typeId], ['spell4', $this->typeId],
|
['spell1', $this->typeId], ['spell2', $this->typeId], ['spell3', $this->typeId], ['spell4', $this->typeId],
|
||||||
['spell5', $this->typeId], ['spell6', $this->typeId], ['spell7', $this->typeId], ['spell8', $this->typeId]
|
['spell5', $this->typeId], ['spell6', $this->typeId], ['spell7', $this->typeId], ['spell8', $this->typeId]
|
||||||
);
|
);
|
||||||
if ($_ = $this->ubSmartScript(TYPE_NPC))
|
if (!empty($ubSAI[TYPE_NPC]))
|
||||||
$conditions[] = ['id', $_];
|
$conditions[] = ['id', $ubSAI[TYPE_NPC]];
|
||||||
|
|
||||||
$ubCreature = new CreatureList($conditions);
|
$ubCreature = new CreatureList($conditions);
|
||||||
if (!$ubCreature->error)
|
if (!$ubCreature->error)
|
||||||
@@ -2231,37 +2233,6 @@ class SpellPage extends GenericPage
|
|||||||
|
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function ubSmartScript(int $type) : array
|
|
||||||
{
|
|
||||||
$src = -1;
|
|
||||||
if ($type == TYPE_OBJECT)
|
|
||||||
$src = SAI_SRC_TYPE_OBJECT;
|
|
||||||
else if ($type == TYPE_NPC)
|
|
||||||
$src = SAI_SRC_TYPE_CREATURE;
|
|
||||||
else if ($type == TYPE_AREATRIGGER)
|
|
||||||
$src = SAI_SRC_TYPE_AREATRIGGER;
|
|
||||||
else
|
|
||||||
return [];
|
|
||||||
|
|
||||||
$ids = [];
|
|
||||||
if ($smartS = DB::World()->select('SELECT entryOrGUID, source_type FROM smart_scripts WHERE entryOrGUID > 0 AND source_type IN (?a) AND action_type IN (?a) AND action_param1 = ?d', [$src, SAI_SRC_TYPE_ACTIONLIST], SAI_ACTION_ALL_SPELLCASTS, $this->typeId))
|
|
||||||
{
|
|
||||||
// filter for timed action list
|
|
||||||
if ($tal = array_filter($smartS, function($x) {return $x['source_type'] == SAI_SRC_TYPE_ACTIONLIST;}))
|
|
||||||
{
|
|
||||||
$talIds = array_column($tal, 'entryOrGUID');
|
|
||||||
if ($_ = DB::World()->selectCol('SELECT entryOrGUID FROM smart_scripts WHERE entryOrGUID > 0 AND source_type = ?d AND action_type IN (?a) AND (action_param1 IN (?a) OR action_param2 IN (?a) OR action_param3 IN (?a) OR action_param4 IN (?a) OR action_param5 IN (?a) OR action_param6 IN (?a))', $src, SAI_ACTION_ALL_TIMED_ACTION_LISTS, $talIds, $talIds, $talIds, $talIds, $talIds, $talIds))
|
|
||||||
$ids = $_;
|
|
||||||
|
|
||||||
$smartS = array_diff_key($smartS, $tal);
|
|
||||||
}
|
|
||||||
if ($smartS);
|
|
||||||
$ids = array_merge($ids, array_column($smartS, 'entryOrGUID'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ids;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user