aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Object/Object.cpp46
-rw-r--r--src/server/game/Entities/Object/Object.h4
-rw-r--r--src/server/game/Maps/Map.cpp11
-rw-r--r--src/server/game/Maps/Map.h10
-rw-r--r--src/server/game/Spells/Spell.cpp18
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp11
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp77
-rw-r--r--src/server/worldserver/worldserver.conf.dist9
10 files changed, 72 insertions, 118 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 8eb18694c84..51c7273de96 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1142,20 +1142,6 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
return thisOrTransport->IsInDist2d(objOrObjTransport, maxdist);
}
-bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlags ignoreFlags) const
-{
- if (!IsInMap(obj))
- return false;
-
- float x, y, z;
- if (obj->GetTypeId() == TYPEID_PLAYER)
- obj->GetPosition(x, y, z);
- else
- obj->GetHitSpherePointFor(GetPosition(), x, y, z);
-
- return IsWithinLOS(x, y, z, ignoreFlags);
-}
-
float WorldObject::GetDistance(const WorldObject* obj) const
{
float d = GetExactDist(obj) - GetCombatReach() - obj->GetCombatReach();
@@ -1230,12 +1216,17 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare,
return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius);
}
-bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags) const
+Position WorldObject::GetHitSpherePointFor(Position const& dest) const
+{
+ G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ());
+ G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
+ G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach());
+
+ return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y));
+}
+
+bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
{
- /*float x, y, z;
- GetPosition(x, y, z);
- VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager();
- return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);*/
if (IsInWorld())
{
float x, y, z;
@@ -1244,19 +1235,24 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFla
else
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
- return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask(), ignoreFlags);
+ return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask(), checks, ignoreFlags);
}
return true;
}
-Position WorldObject::GetHitSpherePointFor(Position const& dest) const
+bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
{
- G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ());
- G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
- G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach());
+ if (!IsInMap(obj))
+ return false;
- return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y));
+ float x, y, z;
+ if (obj->GetTypeId() == TYPEID_PLAYER)
+ obj->GetPosition(x, y, z);
+ else
+ obj->GetHitSpherePointFor(GetPosition(), x, y, z);
+
+ return IsWithinLOS(x, y, z, checks, ignoreFlags);
}
void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 56842bd6d1e..c949d1fd524 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -490,8 +490,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
// use only if you will sure about placing both object at same map
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const;
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool incOwnRadius = true, bool incTargetRadius = true) const;
- bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
- bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
+ bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
+ bool IsWithinLOSInMap(WorldObject const* obj, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
Position GetHitSpherePointFor(Position const& dest) const;
void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const;
bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 41e8129889f..2e956616e09 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2713,10 +2713,15 @@ float Map::GetWaterLevel(float x, float y) const
return 0;
}
-bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) const
+bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
{
- return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2, ignoreFlags)
- && _dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask);
+ if ((checks & LINEOFSIGHT_CHECK_VMAP)
+ && !VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2, ignoreFlags))
+ return false;
+ if (sWorld->getBoolConfig(CONFIG_CHECK_GOBJECT_LOS) && (checks & LINEOFSIGHT_CHECK_GOBJECT)
+ && !_dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask))
+ return false;
+ return true;
}
bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index ec7f1cc8752..5f55fc4f8f4 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -176,6 +176,14 @@ struct PositionFullTerrainStatus
Optional<LiquidData> liquidInfo;
};
+enum LineOfSightChecks
+{
+ LINEOFSIGHT_CHECK_VMAP = 0x1, // check static floor layout data
+ LINEOFSIGHT_CHECK_GOBJECT = 0x2, // check dynamic game object data
+
+ LINEOFSIGHT_ALL_CHECKS = (LINEOFSIGHT_CHECK_VMAP | LINEOFSIGHT_CHECK_GOBJECT)
+};
+
class TC_GAME_API GridMap
{
uint32 _flags;
@@ -519,7 +527,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
float GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float* ground = NULL, bool swim = false) const;
float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
- bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) const;
+ bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const;
void Balance() { _dynamicTree.balance(); }
void RemoveGameObjectModel(const GameObjectModel& model) { _dynamicTree.remove(model); }
void InsertGameObjectModel(const GameObjectModel& model) { _dynamicTree.insert(model); }
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 7b88ff487fd..1b16666eb92 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1852,7 +1852,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
if (Unit* unit = (*itr)->ToUnit())
{
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
- if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
+ if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
{
foundItr = itr;
maxHPDeficit = deficit;
@@ -1867,10 +1867,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
{
if (foundItr == tempTargets.end())
{
- if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
+ if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
foundItr = itr;
}
- else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
+ else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
foundItr = itr;
}
}
@@ -4998,7 +4998,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell->Id))
losTarget = dynObj;
- if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, VMAP::ModelIgnoreFlags::M2))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
return SPELL_FAILED_LINE_OF_SIGHT;
}
}
@@ -5010,7 +5010,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
float x, y, z;
m_targets.GetDstPos()->GetPosition(x, y, z);
- if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
return SPELL_FAILED_LINE_OF_SIGHT;
}
@@ -6891,7 +6891,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
{
if (!m_targets.GetCorpseTargetGUID())
{
- if (target->IsWithinLOSInMap(m_caster, VMAP::ModelIgnoreFlags::M2) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
+ if (target->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
return true;
return false;
@@ -6907,7 +6907,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
if (!corpse->HasFlag(CORPSE_FIELD_FLAGS, CORPSE_FLAG_LOOTABLE))
return false;
- if (!corpse->IsWithinLOSInMap(m_caster, VMAP::ModelIgnoreFlags::M2))
+ if (!corpse->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
return false;
break;
@@ -6915,7 +6915,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
default: // normal case
{
if (losPosition)
- return target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ(), VMAP::ModelIgnoreFlags::M2);
+ return target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2);
else
{
// Get GO cast coordinates if original caster -> GO
@@ -6924,7 +6924,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
if (!caster)
caster = m_caster;
- if (target != m_caster && !target->IsWithinLOSInMap(caster, VMAP::ModelIgnoreFlags::M2))
+ if (target != m_caster && !target->IsWithinLOSInMap(caster, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2))
return false;
}
break;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index a3eae2f7679..2f09d03893f 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1346,6 +1346,9 @@ void World::LoadConfigSettings(bool reload)
// Allow to cache data queries
m_bool_configs[CONFIG_CACHE_DATA_QUERIES] = sConfigMgr->GetBoolDefault("CacheDataQueries", true);
+ // Whether to use LoS from game objects
+ m_bool_configs[CONFIG_CHECK_GOBJECT_LOS] = sConfigMgr->GetBoolDefault("CheckGameObjectLoS", true);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 1eec3d45f53..a976ba5bd7b 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -178,6 +178,7 @@ enum WorldBoolConfigs
CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED,
CONFIG_PREVENT_RENAME_CUSTOMIZATION,
CONFIG_CACHE_DATA_QUERIES,
+ CONFIG_CHECK_GOBJECT_LOS,
BOOL_CONFIG_VALUE_COUNT
};
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 8406139d018..2adab479d44 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -1100,8 +1100,15 @@ public:
static bool HandleDebugLoSCommand(ChatHandler* handler, char const* /*args*/)
{
if (Unit* unit = handler->getSelectedUnit())
- handler->PSendSysMessage("Unit %s (GuidLow: %u) is %sin LoS", unit->GetName().c_str(), unit->GetGUID().GetCounter(), handler->GetSession()->GetPlayer()->IsWithinLOSInMap(unit) ? "" : "not ");
- return true;
+ {
+ Player* player = handler->GetSession()->GetPlayer();
+ handler->PSendSysMessage("Checking LoS %s -> %s:", player->GetName().c_str(), unit->GetName().c_str());
+ handler->PSendSysMessage(" VMAP LoS: %s", player->IsWithinLOSInMap(unit, LINEOFSIGHT_CHECK_VMAP) ? "clear" : "obstructed");
+ handler->PSendSysMessage(" GObj LoS: %s", player->IsWithinLOSInMap(unit, LINEOFSIGHT_CHECK_GOBJECT) ? "clear" : "obstructed");
+ handler->PSendSysMessage("%s is %sin line of sight of %s.", unit->GetName().c_str(), (player->IsWithinLOSInMap(unit) ? "" : "not "), player->GetName().c_str());
+ return true;
+ }
+ return false;
}
static bool HandleDebugSetAuraStateCommand(ChatHandler* handler, char const* args)
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
index f0490e7d1d4..29e0d9f1555 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
@@ -340,6 +340,7 @@ class boss_sapphiron : public CreatureScript
case EVENT_EXPLOSION:
DoCastAOE(SPELL_FROST_BREATH);
DoCastAOE(SPELL_FROST_BREATH_ANTICHEAT);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ICEBOLT);
events.ScheduleEvent(EVENT_LAND, Seconds(3) + Milliseconds(500), 0, PHASE_FLIGHT);
return;
case EVENT_LAND:
@@ -505,81 +506,6 @@ class spell_sapphiron_icebolt : public SpellScriptLoader
}
};
-// @hack Hello, developer from the future! How has your day been?
-// Anyway, this is, as you can undoubtedly see, a hack to emulate line of sight checks on a spell that abides line of sight anyway.
-// In the current core, line of sight is not properly checked for people standing behind an ice block. This is not a good thing and kills people.
-// Thus, we have this hack to check for ice block LoS in a "safe" way. Kind of. It's inaccurate, but in a good way (tends to save people when it shouldn't in edge cases).
-// If LoS handling is better in whatever the current revision is when you read this, please get rid of the hack. Thanks!
-class spell_sapphiron_frost_breath : public SpellScriptLoader
-{
- public:
- spell_sapphiron_frost_breath() : SpellScriptLoader("spell_sapphiron_frost_breath") { }
-
- class spell_sapphiron_frost_breath_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_sapphiron_frost_breath_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return !!sSpellMgr->GetSpellInfo(SPELL_FROST_BREATH);
- }
-
- void HandleTargets(std::list<WorldObject*>& targetList)
- {
- std::list<GameObject*> blocks;
- if (GetCaster())
- GetCaster()->GetGameObjectListWithEntryInGrid(blocks, GO_ICEBLOCK, 200.0f);
-
- std::vector<Unit*> toRemove;
- toRemove.reserve(3);
- std::list<WorldObject*>::iterator it = targetList.begin();
- while (it != targetList.end())
- {
- Unit* target = (*it)->ToUnit();
- if (!target)
- {
- it = targetList.erase(it);
- continue;
- }
-
- if (target->HasAura(SPELL_ICEBOLT))
- {
- it = targetList.erase(it);
- toRemove.push_back(target);
- continue;
- }
-
- bool found = false;
- for (GameObject* block : blocks)
- if (block->IsInBetween(GetCaster(), target, 2.0f) && GetCaster()->GetExactDist2d(block) + 5 >= GetCaster()->GetExactDist2d(target))
- {
- found = true;
- break;
- }
- if (found)
- {
- it = targetList.erase(it);
- continue;
- }
- ++it;
- }
-
- for (Unit* block : toRemove)
- block->RemoveAura(SPELL_ICEBOLT);
- }
-
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sapphiron_frost_breath_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_sapphiron_frost_breath_SpellScript();
- }
-};
-
class spell_sapphiron_summon_blizzard : public SpellScriptLoader
{
public:
@@ -641,7 +567,6 @@ void AddSC_boss_sapphiron()
new go_sapphiron_birth();
new spell_sapphiron_change_blizzard_target();
new spell_sapphiron_icebolt();
- new spell_sapphiron_frost_breath();
new spell_sapphiron_summon_blizzard();
new achievement_the_hundred_club();
}
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index ec4d6ac83ad..a4943047a97 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -400,6 +400,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
# object (+size) after that new target movement point calculated.