Core/Creatures: Implement CREATURE_STATIC_FLAG_4_IGNORE_LOS_WHEN_CASTING_ON_ME
Port From (https://github.com/TrinityCore/TrinityCore/commit/815e158a3ec5f5e173376ff4273913990e9bce10)
This commit is contained in:
@@ -87,7 +87,7 @@ namespace Game.Collision
|
||||
|
||||
public bool IsInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
if (!IsLineOfSightCalcEnabled() || Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapLOS))
|
||||
if (!IsLineOfSightCalcEnabled() || Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLOS))
|
||||
return true;
|
||||
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
@@ -104,7 +104,7 @@ namespace Game.Collision
|
||||
|
||||
public bool GetObjectHitPos(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
if (IsLineOfSightCalcEnabled() && !Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapLOS))
|
||||
if (IsLineOfSightCalcEnabled() && !Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLOS))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
@@ -130,7 +130,7 @@ namespace Game.Collision
|
||||
|
||||
public float GetHeight(uint mapId, float x, float y, float z, float maxSearchDist)
|
||||
{
|
||||
if (IsHeightCalcEnabled() && !Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapHeight))
|
||||
if (IsHeightCalcEnabled() && !Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapHeight))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
@@ -153,7 +153,7 @@ namespace Game.Collision
|
||||
adtId = 0;
|
||||
rootId = 0;
|
||||
groupId = 0;
|
||||
if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapAreaFlag))
|
||||
if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapAreaFlag))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
@@ -171,7 +171,7 @@ namespace Game.Collision
|
||||
|
||||
public bool GetLiquidLevel(uint mapId, float x, float y, float z, uint reqLiquidType, ref float level, ref float floor, ref uint type, ref uint mogpFlags)
|
||||
{
|
||||
if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapLiquidStatus))
|
||||
if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
@@ -198,7 +198,7 @@ namespace Game.Collision
|
||||
{
|
||||
var data = new AreaAndLiquidData();
|
||||
|
||||
if (Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapLiquidStatus))
|
||||
if (Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus))
|
||||
{
|
||||
data.floorZ = z;
|
||||
int adtId, rootId, groupId;
|
||||
@@ -221,7 +221,7 @@ namespace Game.Collision
|
||||
if (info.hitInstance.GetLiquidLevel(pos, info, ref liquidLevel))
|
||||
data.liquidInfo = new(liquidType, liquidLevel);
|
||||
|
||||
if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, (byte)DisableFlags.VmapLiquidStatus))
|
||||
if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus))
|
||||
data.areaInfo = new(info.hitInstance.adtId, info.rootId, (int)info.hitModel.GetWmoID(), info.hitModel.GetMogpFlags());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace Game
|
||||
Log.outInfo(LogFilter.ServerLoading, "Checked {0} quest disables in {1} ms", m_DisableMap[DisableType.Quest].Count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
public bool IsDisabledFor(DisableType type, uint entry, WorldObject refe, ushort flags = 0)
|
||||
public bool IsDisabledFor(DisableType type, uint entry, WorldObject refe, DisableFlags flags = 0)
|
||||
{
|
||||
Cypher.Assert(type < DisableType.Max);
|
||||
if (!m_DisableMap.ContainsKey(type) || m_DisableMap[type].Empty())
|
||||
@@ -331,7 +331,7 @@ namespace Game
|
||||
}
|
||||
else if (spellFlags.HasFlag(DisableFlags.SpellDeprecatedSpell)) // call not from spellcast
|
||||
return true;
|
||||
else if (flags.HasAnyFlag((byte)DisableFlags.SpellLOS))
|
||||
else if (flags.HasAnyFlag(DisableFlags.SpellLOS))
|
||||
return spellFlags.HasFlag(DisableFlags.SpellLOS);
|
||||
|
||||
break;
|
||||
@@ -373,13 +373,13 @@ namespace Game
|
||||
case DisableType.MMAP:
|
||||
return true;
|
||||
case DisableType.VMAP:
|
||||
return flags.HasAnyFlag(data.flags);
|
||||
return flags.HasAnyFlag((DisableFlags)data.flags);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsVMAPDisabledFor(uint entry, byte flags)
|
||||
public bool IsVMAPDisabledFor(uint entry, DisableFlags flags)
|
||||
{
|
||||
return IsDisabledFor(DisableType.VMAP, entry, null, flags);
|
||||
}
|
||||
|
||||
@@ -3289,6 +3289,8 @@ namespace Game.Entities
|
||||
public bool CanMelee() { return !_staticFlags.HasFlag(CreatureStaticFlags.NoMelee); }
|
||||
|
||||
public void SetCanMelee(bool canMelee) { _staticFlags.ApplyFlag(CreatureStaticFlags.NoMelee, !canMelee); }
|
||||
|
||||
public bool CanIgnoreLineOfSightWhenCastingOnMe() { return _staticFlags.HasFlag(CreatureStaticFlags4.IgnoreLosWhenCastingOnMe); }
|
||||
|
||||
public sbyte GetOriginalEquipmentId() { return m_originalEquipmentId; }
|
||||
public byte GetCurrentEquipmentId() { return m_equipmentId; }
|
||||
|
||||
+41
-18
@@ -1771,7 +1771,7 @@ namespace Game.Spells
|
||||
if (unitTarget != null)
|
||||
{
|
||||
uint deficit = (uint)(unitTarget.GetMaxHealth() - unitTarget.GetHealth());
|
||||
if ((deficit > maxHPDeficit || found == null) && chainSource.IsWithinDist(unitTarget, jumpRadius) && chainSource.IsWithinLOSInMap(unitTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if ((deficit > maxHPDeficit || found == null) && chainSource.IsWithinDist(unitTarget, jumpRadius) && IsWithinLOS(chainSource, unitTarget, false, ModelIgnoreFlags.M2))
|
||||
{
|
||||
found = obj;
|
||||
maxHPDeficit = deficit;
|
||||
@@ -1786,10 +1786,10 @@ namespace Game.Spells
|
||||
{
|
||||
if (found == null)
|
||||
{
|
||||
if (chainSource.IsWithinDist(obj, jumpRadius) && chainSource.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if (chainSource.IsWithinDist(obj, jumpRadius) && IsWithinLOS(chainSource, obj, false, ModelIgnoreFlags.M2))
|
||||
found = obj;
|
||||
}
|
||||
else if (chainSource.GetDistanceOrder(obj, found) && chainSource.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
else if (chainSource.GetDistanceOrder(obj, found) && IsWithinLOS(chainSource, obj, false, ModelIgnoreFlags.M2))
|
||||
found = obj;
|
||||
}
|
||||
}
|
||||
@@ -2604,11 +2604,11 @@ namespace Game.Spells
|
||||
Cast(true);
|
||||
else
|
||||
{
|
||||
// commented out !m_spellInfo->StartRecoveryTime, it forces instant spells with global cooldown to be processed in spell::update
|
||||
// commented out !m_spellInfo.StartRecoveryTime, it forces instant spells with global cooldown to be processed in spell::update
|
||||
// as a result a spell that passed CheckCast and should be processed instantly may suffer from this delayed process
|
||||
// the easiest bug to observe is LoS check in AddUnitTarget, even if spell passed the CheckCast LoS check the situation can change in spell::update
|
||||
// because target could be relocated in the meantime, making the spell fly to the air (no targets can be registered, so no effects processed, nothing in combat log)
|
||||
bool willCastDirectly = m_casttime == 0 && /*!m_spellInfo->StartRecoveryTime && */ GetCurrentContainer() == CurrentSpellTypes.Generic;
|
||||
bool willCastDirectly = m_casttime == 0 && /*!m_spellInfo.StartRecoveryTime && */ GetCurrentContainer() == CurrentSpellTypes.Generic;
|
||||
|
||||
Unit unitCaster = m_caster.ToUnit();
|
||||
if (unitCaster != null)
|
||||
@@ -4919,7 +4919,7 @@ namespace Game.Spells
|
||||
losTarget = dynObj;
|
||||
}
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS) && !unitTarget.IsWithinLOSInMap(losTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if (!IsWithinLOS(losTarget, unitTarget, true, ModelIgnoreFlags.M2))
|
||||
return SpellCastResult.LineOfSight;
|
||||
}
|
||||
}
|
||||
@@ -4927,13 +4927,8 @@ namespace Game.Spells
|
||||
|
||||
// Check for line of sight for spells with dest
|
||||
if (m_targets.HasDst())
|
||||
{
|
||||
float x, y, z;
|
||||
m_targets.GetDstPos().GetPosition(out x, out y, out z);
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS) && !m_caster.IsWithinLOS(x, y, z, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if (!IsWithinLOS(m_caster, m_targets.GetDstPos(), ModelIgnoreFlags.M2))
|
||||
return SpellCastResult.LineOfSight;
|
||||
}
|
||||
|
||||
// check pet presence
|
||||
if (unitCaster != null)
|
||||
@@ -5218,7 +5213,7 @@ namespace Game.Spells
|
||||
return SpellCastResult.DontReport;
|
||||
|
||||
// first we must check to see if the target is in LoS. A path can usually be built but LoS matters for charge spells
|
||||
if (!target.IsWithinLOSInMap(unitCaster)) //Do full LoS/Path check. Don't exclude m2
|
||||
if (!IsWithinLOS(unitCaster, target, true, ModelIgnoreFlags.Nothing)) //Do full LoS/Path check. Don't exclude m2
|
||||
return SpellCastResult.LineOfSight;
|
||||
|
||||
float objSize = target.GetCombatReach();
|
||||
@@ -7097,7 +7092,7 @@ namespace Game.Spells
|
||||
}
|
||||
|
||||
// check for ignore LOS on the effect itself
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS))
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS))
|
||||
return true;
|
||||
|
||||
// check if gameobject ignores LOS
|
||||
@@ -7107,7 +7102,7 @@ namespace Game.Spells
|
||||
return true;
|
||||
|
||||
// if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr5.AlwaysLineOfSight) && IsTriggered() && m_triggeredByAuraSpell != null && (m_triggeredByAuraSpell.HasAttribute(SpellAttr2.IgnoreLineOfSight) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_triggeredByAuraSpell.Id, null, (byte)DisableFlags.SpellLOS)))
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr5.AlwaysLineOfSight) && IsTriggered() && m_triggeredByAuraSpell != null && (m_triggeredByAuraSpell.HasAttribute(SpellAttr2.IgnoreLineOfSight) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_triggeredByAuraSpell.Id, null, DisableFlags.SpellLOS)))
|
||||
return true;
|
||||
|
||||
// @todo shit below shouldn't be here, but it's temporary
|
||||
@@ -7118,7 +7113,7 @@ namespace Game.Spells
|
||||
{
|
||||
if (m_targets.GetCorpseTargetGUID().IsEmpty())
|
||||
{
|
||||
if (target.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2) && target.HasUnitFlag(UnitFlags.Skinnable))
|
||||
if (IsWithinLOS(m_caster, target, true, ModelIgnoreFlags.M2) && target.HasUnitFlag(UnitFlags.Skinnable))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -7134,7 +7129,7 @@ namespace Game.Spells
|
||||
if (!corpse.HasCorpseDynamicFlag(CorpseDynFlags.Lootable))
|
||||
return false;
|
||||
|
||||
if (!corpse.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if (!IsWithinLOS(m_caster, corpse, true, ModelIgnoreFlags.M2))
|
||||
return false;
|
||||
|
||||
break;
|
||||
@@ -7149,7 +7144,8 @@ namespace Game.Spells
|
||||
caster = m_caster.GetMap().GetGameObject(m_originalCasterGUID);
|
||||
if (!caster)
|
||||
caster = m_caster;
|
||||
if (target != m_caster && !target.IsWithinLOSInMap(caster, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
|
||||
if (target != m_caster && !IsWithinLOS(caster, target, true, ModelIgnoreFlags.M2))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7716,6 +7712,33 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
|
||||
bool IsWithinLOS(WorldObject source, WorldObject target, bool targetAsSourceLocation, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight))
|
||||
return true;
|
||||
|
||||
if (Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS))
|
||||
return true;
|
||||
|
||||
if (target.IsCreature() && target.ToCreature().CanIgnoreLineOfSightWhenCastingOnMe())
|
||||
return true;
|
||||
|
||||
WorldObject src = targetAsSourceLocation ? target : source;
|
||||
WorldObject dst = targetAsSourceLocation ? source : target;
|
||||
return src.IsWithinLOSInMap(dst, LineOfSightChecks.All, ignoreFlags);
|
||||
}
|
||||
|
||||
bool IsWithinLOS(WorldObject source, Position target, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight))
|
||||
return true;
|
||||
|
||||
if (Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS))
|
||||
return true;
|
||||
|
||||
return source.IsWithinLOS(target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), LineOfSightChecks.All, ignoreFlags);
|
||||
}
|
||||
|
||||
bool CheckScriptEffectImplicitTargets(uint effIndex, uint effIndexToCheck)
|
||||
{
|
||||
// Skip if there are not any script
|
||||
|
||||
Reference in New Issue
Block a user