Core/Spells: Implemented SPELL_ATTR5_NOT_ON_PLAYER and SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC

This commit is contained in:
Shauren authored and Ovahlord committed 2022-09-30 02:05:54 +02:00
1 parent 86fbfb77f4
commit 8fa4b57925
5 files changed
+59 -20

No files matched your search

+33 -4
View File
@@ -133,8 +133,23 @@ SpellCastResult UnitAI::DoCast(uint32 spellId)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
{
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
target = SelectTarget(SELECT_TARGET_RANDOM, 0, spellInfo->GetMaxRange(false), playerOnly);
DefaultTargetSelector targetSelectorInner(me, spellInfo->GetMaxRange(false), false, true, 0);
auto targetSelector = [&](Unit const* candidate) -> bool
{
if (!candidate->IsPlayer())
{
if (spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER))
return false;
if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC) && candidate->IsControlledByPlayer())
return false;
}
else if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER))
return false;
return targetSelectorInner(candidate);
};
target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector);
}
break;
}
@@ -148,10 +163,24 @@ SpellCastResult UnitAI::DoCast(uint32 spellId)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
{
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
float range = spellInfo->GetMaxRange(false);
DefaultTargetSelector targetSelector(me, range, playerOnly, true, -(int32)spellId);
DefaultTargetSelector targetSelectorInner(me, range, false, true, -(int32)spellId);
auto targetSelector = [&](Unit const* candidate) -> bool
{
if (!candidate->IsPlayer())
{
if (spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER))
return false;
if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC) && candidate->IsControlledByPlayer())
return false;
}
else if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER))
return false;
return targetSelectorInner(candidate);
};
if (!spellInfo->HasAuraInterruptFlag(SpellAuraInterruptFlags::NOT_VICTIM) && targetSelector(me->GetVictim()))
target = me->GetVictim();
else
+13 -11
View File
@@ -1065,23 +1065,26 @@ namespace Trinity
AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr, bool incOwnRadius = true, bool incTargetRadius = true)
: i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius)
{
Unit const* check = i_funit;
Unit const* owner = i_funit->GetOwner();
if (owner)
check = owner;
i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER);
}
bool operator()(Unit* u)
{
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
// Check contains checks for: live, uninteractible, non-attackable flags, flight check and GM check, ignore totems
if (u->GetTypeId() == TYPEID_UNIT && u->IsTotem())
return false;
if (_spellInfo && _spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER) && u->GetTypeId() != TYPEID_PLAYER)
return false;
if (_spellInfo)
{
if (!u->IsPlayer())
{
if (_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER))
return false;
if (_spellInfo && _spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER) && u->GetTypeId() == TYPEID_PLAYER)
return false;
if (_spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC) && u->IsControlledByPlayer())
return false;
}
else if (_spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER))
return false;
}
if (!i_funit->IsValidAttackTarget(u, _spellInfo))
return false;
@@ -1095,7 +1098,6 @@ namespace Trinity
return u->IsInMap(i_obj) && u->IsInPhase(i_obj) && u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius);
}
private:
bool i_targetForPlayer;
WorldObject const* i_obj;
Unit const* i_funit;
SpellInfo const* _spellInfo;
@@ -541,8 +541,8 @@ enum SpellAttr5 : uint32
SPELL_ATTR5_TRIGGERS_CHANNELING = 0x00000010, // TITLE Triggers Channeling
SPELL_ATTR5_LIMIT_N = 0x00000020, // TITLE Limit N DESCRIPTION Remove previous application to another unit if applied
SPELL_ATTR5_IGNORE_AREA_EFFECT_PVP_CHECK = 0x00000040, // TITLE Ignore Area Effect PvP Check
SPELL_ATTR5_NOT_ON_PLAYER = 0x00000080, /*NYI*/ // TITLE Not On Player
SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC = 0x00000100, /*NYI*/ // TITLE Not On Player Controlled NPC
SPELL_ATTR5_NOT_ON_PLAYER = 0x00000080, // TITLE Not On Player
SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC = 0x00000100, // TITLE Not On Player Controlled NPC
SPELL_ATTR5_EXTRA_INITIAL_PERIOD = 0x00000200, // TITLE Extra Initial Period DESCRIPTION Immediately do periodic tick on apply
SPELL_ATTR5_DO_NOT_DISPLAY_DURATION = 0x00000400, // TITLE Do Not Display Duration
SPELL_ATTR5_IMPLIED_TARGETING = 0x00000800, // TITLE Implied Targeting (client only)
+1 -1
View File
@@ -1966,7 +1966,7 @@ uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionConta
if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_GHOSTS))
retMask &= GRID_MAP_TYPE_MASK_PLAYER;
if (m_spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER))
retMask &= ~(GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER);
retMask &= ~GRID_MAP_TYPE_MASK_PLAYER;
if (condList)
retMask &= sConditionMgr->GetSearcherTypeMaskForConditionList(*condList);
+10 -2
View File
@@ -1942,8 +1942,16 @@ SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject co
else return SPELL_CAST_OK;
// corpseOwner and unit specific target checks
if (HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER) && unitTarget->GetTypeId() != TYPEID_PLAYER)
return SPELL_FAILED_TARGET_NOT_PLAYER;
if (!unitTarget->IsPlayer())
{
if (HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER))
return SPELL_FAILED_TARGET_NOT_PLAYER;
if (HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC) && unitTarget->IsControlledByPlayer())
return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED;
}
else if (HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER))
return SPELL_FAILED_TARGET_IS_PLAYER;
if (!IsAllowingDeadTarget() && !unitTarget->IsAlive())
return SPELL_FAILED_TARGETS_DEAD;