Files
aowow/includes/components/SmartAI/SmartTarget.class.php
Sarjuuk 870cbea2ca SmartAI/Update
* update events and actions to match TrinityCore again
   * removed events and actions have been kept but marked as deprecated
 * general rewording and use of UIES for better readability
 * move constants to respective classes
 * reevaluate usage of UNIT_FIELD_BYTES1 content
2025-02-27 16:25:24 +01:00

184 lines
12 KiB
PHP

<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// TrinityCore - SmartAI
class SmartTarget
{
use SmartHelper;
public const TARGET_NONE = 0; // None.
public const TARGET_SELF = 1; // Self cast.
public const TARGET_VICTIM = 2; // Our current target. (ie: highest aggro)
public const TARGET_HOSTILE_SECOND_AGGRO = 3; // Second highest aggro.
public const TARGET_HOSTILE_LAST_AGGRO = 4; // Dead last on aggro.
public const TARGET_HOSTILE_RANDOM = 5; // Just any random target on our threat list.
public const TARGET_HOSTILE_RANDOM_NOT_TOP = 6; // Any random target except top threat.
public const TARGET_ACTION_INVOKER = 7; // Unit who caused this Event to occur.
public const TARGET_POSITION = 8; // Use xyz from event params.
public const TARGET_CREATURE_RANGE = 9; // (Random?) creature with specified ID within specified range.
public const TARGET_CREATURE_GUID = 10; // Creature with specified GUID.
public const TARGET_CREATURE_DISTANCE = 11; // Creature with specified ID within distance. (Different from #9?)
public const TARGET_STORED = 12; // Uses pre-stored target(list)
public const TARGET_GAMEOBJECT_RANGE = 13; // (Random?) object with specified ID within specified range.
public const TARGET_GAMEOBJECT_GUID = 14; // Object with specified GUID.
public const TARGET_GAMEOBJECT_DISTANCE = 15; // Object with specified ID within distance. (Different from #13?)
public const TARGET_INVOKER_PARTY = 16; // Invoker's party members
public const TARGET_PLAYER_RANGE = 17; // (Random?) player within specified range.
public const TARGET_PLAYER_DISTANCE = 18; // (Random?) player within specified distance. (Different from #17?)
public const TARGET_CLOSEST_CREATURE = 19; // Closest creature with specified ID within specified range.
public const TARGET_CLOSEST_GAMEOBJECT = 20; // Closest object with specified ID within specified range.
public const TARGET_CLOSEST_PLAYER = 21; // Closest player within specified range.
public const TARGET_ACTION_INVOKER_VEHICLE = 22; // Unit's vehicle who caused this Event to occur
public const TARGET_OWNER_OR_SUMMONER = 23; // Unit's owner or summoner
public const TARGET_THREAT_LIST = 24; // All units on creature's threat list
public const TARGET_CLOSEST_ENEMY = 25; // Any attackable target (creature or player) within maxDist
public const TARGET_CLOSEST_FRIENDLY = 26; // Any friendly unit (creature, player or pet) within maxDist
public const TARGET_LOOT_RECIPIENTS = 27; // All tagging players
public const TARGET_FARTHEST = 28; // Farthest unit on the threat list
public const TARGET_VEHICLE_PASSENGER = 29; // Vehicle can target unit in given seat
public const TARGET_CLOSEST_UNSPAWNED_GO = 30; // entry(0any), maxDist
private const TARGET_TPL = '[tooltip name=t-#rowIdx#]%1$s[/tooltip][span class=tip tooltip=t-#rowIdx#]%2$s[/span]';
private array $targets = array(
self::TARGET_NONE => [null, null, null, null], // NONE
self::TARGET_SELF => [null, null, null, null], // Self cast
self::TARGET_VICTIM => [null, null, null, null], // Our current target (ie: highest aggro)
self::TARGET_HOSTILE_SECOND_AGGRO => [null, null, null, null], // Second highest aggro, maxdist, playerOnly, powerType + 1
self::TARGET_HOSTILE_LAST_AGGRO => [null, null, null, null], // Dead last on aggro, maxdist, playerOnly, powerType + 1
self::TARGET_HOSTILE_RANDOM => [null, null, null, null], // Just any random target on our threat list, maxdist, playerOnly, powerType + 1
self::TARGET_HOSTILE_RANDOM_NOT_TOP => [null, null, null, null], // Any random target except top threat, maxdist, playerOnly, powerType + 1
self::TARGET_ACTION_INVOKER => [null, null, null, null], // Unit who caused this Event to occur
self::TARGET_POSITION => [null, null, null, null], // use xyz from event params
self::TARGET_CREATURE_RANGE => [Type::NPC, ['numRange', 10, false], null, null], // CreatureEntry(0any), minDist, maxDist
self::TARGET_CREATURE_GUID => [null, Type::NPC, null, null], // guid, entry
self::TARGET_CREATURE_DISTANCE => [Type::NPC, null, null, null], // CreatureEntry(0any), maxDist
self::TARGET_STORED => [null, null, null, null], // id, uses pre-stored target(list)
self::TARGET_GAMEOBJECT_RANGE => [Type::OBJECT, ['numRange', 10, false], null, null], // entry(0any), min, max
self::TARGET_GAMEOBJECT_GUID => [null, Type::OBJECT, null, null], // guid, entry
self::TARGET_GAMEOBJECT_DISTANCE => [Type::OBJECT, null, null, null], // entry(0any), maxDist
self::TARGET_INVOKER_PARTY => [null, null, null, null], // invoker's party members
self::TARGET_PLAYER_RANGE => [['numRange', 10, false], null, null, null], // min, max
self::TARGET_PLAYER_DISTANCE => [null, null, null, null], // maxDist
self::TARGET_CLOSEST_CREATURE => [Type::NPC, null, null, null], // CreatureEntry(0any), maxDist, dead?
self::TARGET_CLOSEST_GAMEOBJECT => [Type::OBJECT, null, null, null], // entry(0any), maxDist
self::TARGET_CLOSEST_PLAYER => [null, null, null, null], // maxDist
self::TARGET_ACTION_INVOKER_VEHICLE => [null, null, null, null], // Unit's vehicle who caused this Event to occur
self::TARGET_OWNER_OR_SUMMONER => [null, null, null, null], // Unit's owner or summoner, Use Owner/Charmer of this unit
self::TARGET_THREAT_LIST => [null, null, null, null], // All units on creature's threat list, maxdist
self::TARGET_CLOSEST_ENEMY => [null, null, null, null], // maxDist, playerOnly
self::TARGET_CLOSEST_FRIENDLY => [null, null, null, null], // maxDist, playerOnly
self::TARGET_LOOT_RECIPIENTS => [null, null, null, null], // all players that have tagged this creature (for kill credit)
self::TARGET_FARTHEST => [null, null, null, null], // maxDist, playerOnly, isInLos
self::TARGET_VEHICLE_PASSENGER => [null, null, null, null], // seatMask (0 - all seats)
self::TARGET_CLOSEST_UNSPAWNED_GO => [Type::OBJECT, null, null, null] // entry(0any), maxDist
);
private array $jsGlobals = [];
public function __construct(
private int $id,
public readonly int $type,
private array $param,
private array $worldPos,
private SmartAI &$smartAI)
{
// additional parameters
Util::checkNumeric($this->param, NUM_CAST_INT);
Util::checkNumeric($this->worldPos, NUM_CAST_FLOAT);
$this->param = array_pad($this->param, 15, '');
$this->worldPos = array_pad($this->worldPos, 4, 0.0);
}
public function process() : string
{
$target = '';
$targetTT = Lang::smartAI('targetTT', array_merge([$this->type], $this->param, $this->worldPos));
for ($i = 0; $i < 4; $i++)
{
$tParams = $this->targets[$this->type];
if (is_array($tParams[$i]))
{
[$fn, $idx, $extraParam] = $tParams[$i];
$this->param[$idx] = $this->{$fn}($this->param[$i], $this->param[$i + 1], $extraParam);
}
else if (is_int($tParams[$i]) && $this->param[$i])
$this->jsGlobals[$tParams[$i]][$this->param[$i]] = $this->param[$i];
}
// non-generic cases
switch ($this->type)
{
case self::TARGET_HOSTILE_SECOND_AGGRO:
case self::TARGET_HOSTILE_LAST_AGGRO:
case self::TARGET_HOSTILE_RANDOM:
case self::TARGET_HOSTILE_RANDOM_NOT_TOP:
if ($this->param[2])
$this->param[10] = Lang::spell('powerTypes', $this->param[2] - 1);
break;
case self::TARGET_VEHICLE_PASSENGER:
if ($this->param[0])
$this->param[10] = Lang::concat(Util::mask2bits($this->param[0]));
break;
case self::TARGET_CREATURE_GUID:
if ($_ = $this->resolveGuid(Type::NPC, $this->param[0]))
{
$this->jsGlobals[Type::NPC][$_] = $_;
$this->param[10] = $_;
}
break;
case self::TARGET_GAMEOBJECT_GUID:
if ($_ = $this->resolveGuid(Type::OBJECT, $this->param[0]))
{
$this->jsGlobals[Type::OBJECT][$_] = $_;
$this->param[10] = $_;
}
break;
}
$this->smartAI->addJsGlobals($this->jsGlobals);
$target = Lang::smartAI('targets', $this->type, $this->param) ?? Lang::smartAI('targetUNK', [$this->type]);
// resolve conditionals
$i = 0;
while (strstr($target, ')?') && $i++ < 3)
$target = preg_replace_callback('/\(([^\)]*?)\)\?([^:]*):(([^;]*);*);/i', fn($m) => $m[1] ? $m[2] : $m[3], $target);
// wrap in tooltip (suspend action-tooltip)
return '[/span]'.sprintf(self::TARGET_TPL, $targetTT, $target).'[span tooltip=a-#rowIdx#]';
}
public function getWorldPos() : array
{
return $this->worldPos;
}
// not really feasable. Too many target types can be players or creatures, depending on context
public function getTalkSource(bool &$playerSrc = false) : int
{
if ($this->type == SmartTarget::TARGET_CLOSEST_PLAYER)
$playerSrc = true;
return match ($this->type)
{
SmartTarget::TARGET_CREATURE_GUID => $this->resolveGuid(Type::NPC, $this->param[0]) ?? 0,
SmartTarget::TARGET_CREATURE_RANGE,
SmartTarget::TARGET_CREATURE_DISTANCE,
SmartTarget::TARGET_CLOSEST_CREATURE => $this->param[0],
SmartTarget::TARGET_CLOSEST_PLAYER,
SmartTarget::TARGET_SELF => $this->smartAI->getEntry(),
default => $this->smartAI->getEntry()
};
}
}
?>