mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
* 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
184 lines
12 KiB
PHP
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()
|
|
};
|
|
}
|
|
}
|
|
|
|
?>
|