From ddaaae896e6d06c82e543de955ff7df5e5f67cff Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 23 Jul 2020 19:01:15 -0400 Subject: [PATCH] So, I came in trying to fix gameobject LoS. So I restructured some stuff. Port From (https://github.com/TrinityCore/TrinityCore/commit/5392212799b669d91c80cf0e9539a3aaa2abbe79) --- Source/Framework/Constants/MapConst.cs | 8 +++++ Source/Framework/Constants/SharedConst.cs | 1 + Source/Game/Chat/Commands/DebugCommands.cs | 11 +++++-- Source/Game/Entities/Object/WorldObject.cs | 32 +++++++++---------- Source/Game/Maps/Map.cs | 11 +++++-- Source/Game/Server/WorldConfig.cs | 3 ++ Source/Game/Spells/Spell.cs | 18 +++++------ Source/WorldServer/WorldServer.conf.dist | 9 ++++++ ...020_07_16_02_world_2017_06_10_00_world.sql | 1 + 9 files changed, 64 insertions(+), 30 deletions(-) create mode 100644 sql/updates/world/master/2020_07_16_02_world_2017_06_10_00_world.sql diff --git a/Source/Framework/Constants/MapConst.cs b/Source/Framework/Constants/MapConst.cs index 8505d7d5c..81f217e2b 100644 --- a/Source/Framework/Constants/MapConst.cs +++ b/Source/Framework/Constants/MapConst.cs @@ -192,4 +192,12 @@ namespace Framework.Constants Nothing = 0x00, M2 = 0x01 } + + public enum LineOfSightChecks + { + Vmap = 0x1, // check static floor layout data + Gobject = 0x2, // check dynamic game object data + + All = Vmap | Gobject + } } diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index 7deaaea4b..059ced0fd 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -1109,6 +1109,7 @@ namespace Framework.Constants ChatStrictLinkCheckingSeverity, ChatWhisperLevelReq, ChatYellLevelReq, + CheckGobjectLos, CleanCharacterDb, ClientCacheVersion, Compression, diff --git a/Source/Game/Chat/Commands/DebugCommands.cs b/Source/Game/Chat/Commands/DebugCommands.cs index 11c3191a0..728b2751b 100644 --- a/Source/Game/Chat/Commands/DebugCommands.cs +++ b/Source/Game/Chat/Commands/DebugCommands.cs @@ -494,8 +494,15 @@ namespace Game.Chat { Unit unit = handler.GetSelectedUnit(); if (unit) - handler.SendSysMessage("Unit {0} (GuidLow: {1}) is {2}in LoS", unit.GetName(), unit.GetGUID().ToString(), handler.GetSession().GetPlayer().IsWithinLOSInMap(unit) ? "" : "not "); - return true; + { + Player player = handler.GetSession().GetPlayer(); + handler.SendSysMessage($"Checking LoS {player.GetName()} -> {unit.GetName()}:"); + handler.SendSysMessage($" VMAP LoS: {(player.IsWithinLOSInMap(unit, LineOfSightChecks.Vmap) ? "clear" : "obstructed")}"); + handler.SendSysMessage($" GObj LoS: {(player.IsWithinLOSInMap(unit, LineOfSightChecks.Gobject) ? "clear" : "obstructed")}"); + handler.SendSysMessage($"{unit.GetName()} is {(player.IsWithinLOSInMap(unit) ? "" : "not ")}in line of sight of {player.GetName()}."); + return true; + } + return false; } [Command("moveflags", RBACPermissions.CommandDebugMoveflags)] diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 358aeafaf..9bd2eaff8 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1806,20 +1806,6 @@ namespace Game.Entities return thisOrTransport.IsInDist2d(objOrObjTransport, maxdist); } - public bool IsWithinLOSInMap(WorldObject obj, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing) - { - if (!IsInMap(obj)) - return false; - - float x, y, z; - if (obj.IsTypeId(TypeId.Player)) - obj.GetPosition(out x, out y, out z); - else - obj.GetHitSpherePointFor(GetPosition(), out x, out y, out z); - - return IsWithinLOS(x, y, z, ignoreFlags); - } - public float GetDistance(WorldObject obj) { float d = GetExactDist(obj.GetPosition()) - GetCombatReach() - obj.GetCombatReach(); @@ -1895,7 +1881,7 @@ namespace Game.Entities return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius); } - public bool IsWithinLOS(float ox, float oy, float oz, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing) + public bool IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks checks = LineOfSightChecks.All, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing) { if (IsInWorld) { @@ -1905,12 +1891,26 @@ namespace Game.Entities else GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z); - return GetMap().IsInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, ignoreFlags); + return GetMap().IsInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, checks, ignoreFlags); } return true; } + public bool IsWithinLOSInMap(WorldObject obj, LineOfSightChecks checks = LineOfSightChecks.All, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing) + { + if (!IsInMap(obj)) + return false; + + float x, y, z; + if (obj.IsTypeId(TypeId.Player)) + obj.GetPosition(out x, out y, out z); + else + obj.GetHitSpherePointFor(GetPosition(), out x, out y, out z); + + return IsWithinLOS(x, y, z, checks, ignoreFlags); + } + Position GetHitSpherePointFor(Position dest) { Vector3 vThis = new Vector3(GetPositionX(), GetPositionY(), GetPositionZ()); diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 516d9cfe9..925e6c7d2 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -2204,10 +2204,15 @@ namespace Game.Maps return 0; } - public bool IsInLineOfSight(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) + public bool IsInLineOfSight(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, ModelIgnoreFlags ignoreFlags) { - return Global.VMapMgr.IsInLineOfSight(PhasingHandler.GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2, ignoreFlags) - && _dynamicTree.IsInLineOfSight(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), phaseShift); + if (checks.HasAnyFlag(LineOfSightChecks.Vmap) && Global.VMapMgr.IsInLineOfSight(PhasingHandler.GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2, ignoreFlags)) + return false; + + if (WorldConfig.GetBoolValue(WorldCfg.CheckGobjectLos) && checks.HasAnyFlag(LineOfSightChecks.Gobject) && _dynamicTree.IsInLineOfSight(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), phaseShift)) + return false; + + return true; } public bool GetObjectHitPos(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist) diff --git a/Source/Game/Server/WorldConfig.cs b/Source/Game/Server/WorldConfig.cs index db115cf7d..b57a0a8aa 100644 --- a/Source/Game/Server/WorldConfig.cs +++ b/Source/Game/Server/WorldConfig.cs @@ -916,6 +916,9 @@ namespace Game Values[WorldCfg.CreatureCheckInvalidPostion] = GetDefaultValue("Creature.CheckInvalidPosition", false); Values[WorldCfg.GameobjectCheckInvalidPostion] = GetDefaultValue("GameObject.CheckInvalidPosition", false); + // Whether to use LoS from game objects + Values[WorldCfg.CheckGobjectLos] = GetDefaultValue("CheckGameObjectLoS", true); + // call ScriptMgr if we're reloading the configuration if (reload) Global.ScriptMgr.OnConfigLoad(reload); diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 84b9d4138..4291d1b94 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -1452,7 +1452,7 @@ namespace Game.Spells if (unitTarget != null) { uint deficit = (uint)(unitTarget.GetMaxHealth() - unitTarget.GetHealth()); - if ((deficit > maxHPDeficit || found == null) && target.IsWithinDist(unitTarget, jumpRadius) && target.IsWithinLOSInMap(unitTarget, ModelIgnoreFlags.M2)) + if ((deficit > maxHPDeficit || found == null) && target.IsWithinDist(unitTarget, jumpRadius) && target.IsWithinLOSInMap(unitTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2)) { found = obj; maxHPDeficit = deficit; @@ -1467,10 +1467,10 @@ namespace Game.Spells { if (found == null) { - if ((!isBouncingFar || target.IsWithinDist(obj, jumpRadius)) && target.IsWithinLOSInMap(obj, ModelIgnoreFlags.M2)) + if ((!isBouncingFar || target.IsWithinDist(obj, jumpRadius)) && target.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2)) found = obj; } - else if (target.GetDistanceOrder(obj, found) && target.IsWithinLOSInMap(obj, ModelIgnoreFlags.M2)) + else if (target.GetDistanceOrder(obj, found) && target.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2)) found = obj; } } @@ -4643,7 +4643,7 @@ namespace Game.Spells } if (!m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS) - && !unitTarget.IsWithinLOSInMap(losTarget, ModelIgnoreFlags.M2)) + && !unitTarget.IsWithinLOSInMap(losTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2)) return SpellCastResult.LineOfSight; } } @@ -4656,7 +4656,7 @@ namespace Game.Spells m_targets.GetDstPos().GetPosition(out x, out y, out z); if (!m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS) - && !m_caster.IsWithinLOS(x, y, z, ModelIgnoreFlags.M2)) + && !m_caster.IsWithinLOS(x, y, z, LineOfSightChecks.All, ModelIgnoreFlags.M2)) return SpellCastResult.LineOfSight; } @@ -6594,7 +6594,7 @@ namespace Game.Spells { if (m_targets.GetCorpseTargetGUID().IsEmpty()) { - if (target.IsWithinLOSInMap(m_caster, ModelIgnoreFlags.M2) && target.HasUnitFlag(UnitFlags.Skinnable)) + if (target.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2) && target.HasUnitFlag(UnitFlags.Skinnable)) return true; return false; @@ -6610,7 +6610,7 @@ namespace Game.Spells if (!corpse.HasDynamicFlag(UnitDynFlags.Lootable)) return false; - if (!corpse.IsWithinLOSInMap(m_caster, ModelIgnoreFlags.M2)) + if (!corpse.IsWithinLOSInMap(m_caster, LineOfSightChecks.All, ModelIgnoreFlags.M2)) return false; break; @@ -6618,7 +6618,7 @@ namespace Game.Spells default: { if (losPosition != null) - return target.IsWithinLOS(losPosition.GetPositionX(), losPosition.GetPositionY(), losPosition.GetPositionZ(), ModelIgnoreFlags.M2); + return target.IsWithinLOS(losPosition.GetPositionX(), losPosition.GetPositionY(), losPosition.GetPositionZ(), LineOfSightChecks.All, ModelIgnoreFlags.M2); else { // Get GO cast coordinates if original caster -> GO @@ -6627,7 +6627,7 @@ namespace Game.Spells caster = m_caster.GetMap().GetGameObject(m_originalCasterGUID); if (!caster) caster = m_caster; - if (target != m_caster && !target.IsWithinLOSInMap(caster, ModelIgnoreFlags.M2)) + if (target != m_caster && !target.IsWithinLOSInMap(caster, LineOfSightChecks.All, ModelIgnoreFlags.M2)) return false; } diff --git a/Source/WorldServer/WorldServer.conf.dist b/Source/WorldServer/WorldServer.conf.dist index e0168443f..fca823d1c 100644 --- a/Source/WorldServer/WorldServer.conf.dist +++ b/Source/WorldServer/WorldServer.conf.dist @@ -410,6 +410,15 @@ vmap.EnableIndoorCheck = 1 DetectPosCollision = 1 +# +# CheckGameObjectLoS +# Description: Include dynamic game objects (doors, chests etc.) in line of sight checks. +# This increases CPU usage somewhat. +# Default: 1 - (Enabled) +# 0 - (Disabled, may break some boss encounters) + +CheckGameObjectLoS = 1 + # # TargetPosRecalculateRange # Description: Max distance from movement target point (+moving unit size) and targeted diff --git a/sql/updates/world/master/2020_07_16_02_world_2017_06_10_00_world.sql b/sql/updates/world/master/2020_07_16_02_world_2017_06_10_00_world.sql new file mode 100644 index 000000000..d07d707eb --- /dev/null +++ b/sql/updates/world/master/2020_07_16_02_world_2017_06_10_00_world.sql @@ -0,0 +1 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_sapphiron_frost_breath';