mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/SAI: Implement SMART_TARGET_ACTION_INVOKER in SMART_EVENT_FRIENDLY_HEALTH_PCT (#25318)
* Core/SAI: Implement SMART_TARGET_ACTION_INVOKER in SMART_EVENT_FRIENDLY_HEALTH_PCT
* Require radius (5th parameter) to be set
(cherry picked from commit cbed1039c4)
This commit is contained in:
@@ -3598,7 +3598,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
|
||||
ObjectVector targets;
|
||||
Unit* unitTarget = nullptr;
|
||||
switch (e.GetTargetType())
|
||||
{
|
||||
case SMART_TARGET_CREATURE_RANGE:
|
||||
@@ -3608,26 +3608,31 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
case SMART_TARGET_CLOSEST_PLAYER:
|
||||
case SMART_TARGET_PLAYER_RANGE:
|
||||
case SMART_TARGET_PLAYER_DISTANCE:
|
||||
{
|
||||
ObjectVector targets;
|
||||
GetTargets(targets, e);
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat())
|
||||
{
|
||||
uint32 healthPct = uint32(target->ToUnit()->GetHealthPct());
|
||||
if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct)
|
||||
continue;
|
||||
|
||||
unitTarget = target->ToUnit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_TARGET_ACTION_INVOKER:
|
||||
unitTarget = DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* unitTarget = nullptr;
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat())
|
||||
{
|
||||
uint32 healthPct = uint32(target->ToUnit()->GetHealthPct());
|
||||
if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct)
|
||||
continue;
|
||||
|
||||
unitTarget = target->ToUnit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
@@ -4231,6 +4236,18 @@ Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) const
|
||||
return unit;
|
||||
}
|
||||
|
||||
Unit* SmartScript::DoSelectLowestHpPercentFriendly(float range, uint32 minHpPct, uint32 maxHpPct) const
|
||||
{
|
||||
if (!me)
|
||||
return nullptr;
|
||||
|
||||
Unit* unit = nullptr;
|
||||
Trinity::MostHPPercentMissingInRange u_check(me, range, minHpPct, maxHpPct);
|
||||
Trinity::UnitLastSearcher<Trinity::MostHPPercentMissingInRange> searcher(me, unit, u_check);
|
||||
Cell::VisitGridObjects(me, searcher, range);
|
||||
return unit;
|
||||
}
|
||||
|
||||
void SmartScript::DoFindFriendlyCC(std::vector<Creature*>& creatures, float range) const
|
||||
{
|
||||
if (!me)
|
||||
|
||||
@@ -70,6 +70,7 @@ class TC_GAME_API SmartScript
|
||||
void OnMoveInLineOfSight(Unit* who);
|
||||
|
||||
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) const;
|
||||
Unit* DoSelectLowestHpPercentFriendly(float range, uint32 minHpPct, uint32 maxHpPct) const;
|
||||
void DoFindFriendlyCC(std::vector<Creature*>& creatures, float range) const;
|
||||
void DoFindFriendlyMissingBuff(std::vector<Creature*>& creatures, float range, uint32 spellid) const;
|
||||
Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly) const;
|
||||
|
||||
@@ -1018,6 +1018,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_TARGET_PLAYER_RANGE:
|
||||
case SMART_TARGET_PLAYER_DISTANCE:
|
||||
break;
|
||||
case SMART_TARGET_ACTION_INVOKER:
|
||||
if (!NotNULL(e, e.event.friendlyHealthPct.radius))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid target_type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||
return false;
|
||||
|
||||
@@ -422,6 +422,7 @@ struct SmartEvent
|
||||
uint32 maxHpPct;
|
||||
uint32 repeatMin;
|
||||
uint32 repeatMax;
|
||||
uint32 radius;
|
||||
} friendlyHealthPct;
|
||||
|
||||
struct
|
||||
|
||||
@@ -887,6 +887,27 @@ namespace Trinity
|
||||
uint64 i_hp;
|
||||
};
|
||||
|
||||
class MostHPPercentMissingInRange
|
||||
{
|
||||
public:
|
||||
MostHPPercentMissingInRange(Unit const* obj, float range, uint32 minHpPct, uint32 maxHpPct) : i_obj(obj), i_range(range), i_minHpPct(minHpPct), i_maxHpPct(maxHpPct), i_hpPct(101.f) { }
|
||||
|
||||
bool operator()(Unit* u)
|
||||
{
|
||||
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && i_minHpPct <= u->GetHealthPct() && u->GetHealthPct() <= i_maxHpPct && u->GetHealthPct() < i_hpPct)
|
||||
{
|
||||
i_hpPct = u->GetHealthPct();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Unit const* i_obj;
|
||||
float i_range;
|
||||
float i_minHpPct, i_maxHpPct, i_hpPct;
|
||||
};
|
||||
|
||||
class FriendlyBelowHpPctEntryInRange
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user