feat(Core/SmartScripts): Improvements to SMART_EVENT_FRIENDLY_HEALTH_PCT: (#11171)

* Added new parameter: radius.
* The event can be used with SMART_TARGET_SELF and SMART_TARGET_ACTION_INVOKER target types.
* Closes #5270
This commit is contained in:
UltraNix
2022-04-18 19:35:37 +02:00
committed by GitHub
parent c93a84e821
commit f7214e24ea
5 changed files with 71 additions and 24 deletions

View File

@@ -4502,8 +4502,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (!me || !me->IsInCombat())
return;
ObjectList* _targets = nullptr;
Unit* target = nullptr;
switch (e.GetTargetType())
{
case SMART_TARGET_CREATURE_RANGE:
@@ -4513,33 +4512,34 @@ 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:
_targets = GetTargets(e);
{
ObjectList* targets = GetTargets(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;
}
target = target->ToUnit();
break;
}
}
delete targets;
break;
}
case SMART_TARGET_SELF:
case SMART_TARGET_ACTION_INVOKER:
target = DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct);
break;
default:
return;
}
if (!_targets)
return;
Unit* target = nullptr;
for (ObjectList::const_iterator itr = _targets->begin(); itr != _targets->end(); ++itr)
{
if (IsUnit(*itr) && me->IsFriendlyTo((*itr)->ToUnit()) && (*itr)->ToUnit()->IsAlive() && (*itr)->ToUnit()->IsInCombat())
{
uint32 healthPct = uint32((*itr)->ToUnit()->GetHealthPct());
if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct)
continue;
target = (*itr)->ToUnit();
break;
}
}
delete _targets;
if (!target)
return;
@@ -5033,6 +5033,20 @@ Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
return unit;
}
Unit* SmartScript::DoSelectLowestHpPercentFriendly(float range, uint32 minHpPct, uint32 maxHpPct) const
{
if (!me)
{
return nullptr;
}
Unit* unit = nullptr;
Acore::MostHPPercentMissingInRange u_check(me, range, minHpPct, maxHpPct);
Acore::UnitLastSearcher<Acore::MostHPPercentMissingInRange> searcher(me, unit, u_check);
Cell::VisitGridObjects(me, searcher, range);
return unit;
}
void SmartScript::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
{
if (!me)

View File

@@ -85,6 +85,7 @@ public:
void OnMoveInLineOfSight(Unit* who);
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff);
Unit* DoSelectLowestHpPercentFriendly(float range, uint32 minHpPct, uint32 maxHpPct) const;
void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
void DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid);
Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly);

View File

@@ -1138,6 +1138,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_TARGET_PLAYER_RANGE:
case SMART_TARGET_PLAYER_DISTANCE:
break;
case SMART_TARGET_SELF:
case SMART_TARGET_ACTION_INVOKER:
if (!NotNULL(e, e.event.friendlyHealthPct.radius))
{
return false;
}
break;
default:
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid target_type {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
return false;

View File

@@ -419,6 +419,7 @@ struct SmartEvent
uint32 maxHpPct;
uint32 repeatMin;
uint32 repeatMax;
uint32 radius;
} friendlyHealthPct;
struct

View File

@@ -787,6 +787,30 @@ namespace Acore
uint32 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 FriendlyCCedInRange
{
public: