aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp60
-rw-r--r--src/server/game/Conditions/ConditionMgr.h5
-rw-r--r--src/server/game/Entities/Object/Object.cpp3
3 files changed, 65 insertions, 3 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index d9a67f3bcf7..ed23050f57c 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -82,7 +82,8 @@ char const* const ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX]
"AreaTrigger",
"ConversationLine",
"AreaTrigger Client Triggered",
- "Trainer Spell"
+ "Trainer Spell",
+ "Object Visibility (by ID)"
};
ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[CONDITION_MAX] =
@@ -954,7 +955,8 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType)
sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR ||
sourceType == CONDITION_SOURCE_TYPE_PHASE ||
sourceType == CONDITION_SOURCE_TYPE_AREATRIGGER ||
- sourceType == CONDITION_SOURCE_TYPE_TRAINER_SPELL);
+ sourceType == CONDITION_SOURCE_TYPE_TRAINER_SPELL ||
+ sourceType == CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY);
}
bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType)
@@ -1096,6 +1098,16 @@ bool ConditionMgr::IsObjectMeetingTrainerSpellConditions(uint32 trainerId, uint3
return true;
}
+bool ConditionMgr::IsObjectMeetingVisibilityByObjectIdConditions(uint32 objectType, uint32 entry, WorldObject* seer) const
+{
+ if (ConditionContainer const* conditions = Trinity::Containers::MapGetValuePtr(ObjectVisibilityConditionStore, { objectType, entry }))
+ {
+ TC_LOG_DEBUG("condition", "IsObjectMeetingVisibilityByObjectIdConditions: found conditions for objectType %u entry %u", objectType, entry);
+ return IsObjectMeetToConditions(seer, *conditions);
+ }
+ return true;
+}
+
ConditionMgr* ConditionMgr::instance()
{
static ConditionMgr instance;
@@ -1348,6 +1360,13 @@ void ConditionMgr::LoadConditions(bool isReload)
++count;
continue;
}
+ case CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY:
+ {
+ ObjectVisibilityConditionStore[{ cond->SourceGroup, uint32(cond->SourceEntry) }].push_back(cond);
+ valid = true;
+ ++count;
+ continue;
+ }
default:
break;
}
@@ -1992,6 +2011,37 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
}
break;
}
+ case CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY:
+ {
+ if (cond->SourceGroup <= 0 || cond->SourceGroup >= NUM_CLIENT_OBJECT_TYPES)
+ {
+ TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, is no valid object type, ignoring.", cond->ToString().c_str());
+ return false;
+ }
+
+ if (cond->SourceGroup == TYPEID_UNIT)
+ {
+ if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
+ {
+ TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str());
+ return false;
+ }
+ }
+ else if (cond->SourceGroup == TYPEID_GAMEOBJECT)
+ {
+ if (!sObjectMgr->GetGameObjectTemplate(cond->SourceEntry))
+ {
+ TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `gameobject_template`, ignoring.", cond->ToString().c_str());
+ return false;
+ }
+ }
+ else
+ {
+ TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, uses unchecked type id, ignoring.", cond->ToString().c_str());
+ return false;
+ }
+ break;
+ }
default:
TC_LOG_ERROR("sql.sql", "%s Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString().c_str());
return false;
@@ -2585,6 +2635,12 @@ void ConditionMgr::Clean()
TrainerSpellConditionContainerStore.clear();
+ for (auto&& [_, conditions] : ObjectVisibilityConditionStore)
+ for (Condition* condition : conditions)
+ delete condition;
+
+ ObjectVisibilityConditionStore.clear();
+
// this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
for (std::vector<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
delete *itr;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 82ecbc98c52..b2783cfc5f8 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -174,7 +174,8 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_CONVERSATION_LINE = 29,
CONDITION_SOURCE_TYPE_AREATRIGGER_CLIENT_TRIGGERED = 30,
CONDITION_SOURCE_TYPE_TRAINER_SPELL = 31,
- CONDITION_SOURCE_TYPE_MAX = 32 // MAX
+ CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY = 32,
+ CONDITION_SOURCE_TYPE_MAX = 33 // MAX
};
enum RelationType
@@ -298,6 +299,7 @@ class TC_GAME_API ConditionMgr
ConditionContainer const* GetConditionsForAreaTrigger(uint32 areaTriggerId, bool isServerSide) const;
bool IsObjectMeetingTrainerSpellConditions(uint32 trainerId, uint32 spellId, Player* player) const;
+ bool IsObjectMeetingVisibilityByObjectIdConditions(uint32 objectType, uint32 entry, WorldObject* seer) const;
static uint32 GetPlayerConditionLfgValue(Player const* player, PlayerConditionLfgStatus status);
static bool IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition);
@@ -337,6 +339,7 @@ class TC_GAME_API ConditionMgr
std::unordered_set<uint32> SpellsUsedInSpellClickConditions;
ConditionEntriesByAreaTriggerIdMap AreaTriggerConditionContainerStore;
ConditionEntriesByCreatureIdMap TrainerSpellConditionContainerStore;
+ std::unordered_map<std::pair<uint32 /*object type*/, uint32 /*object id*/>, ConditionContainer> ObjectVisibilityConditionStore;
};
#define sConditionMgr ConditionMgr::instance()
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 31c4bcefbac..4a89ecb2674 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1404,6 +1404,9 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
if (!obj->CheckPrivateObjectOwnerVisibility(this))
return false;
+ if (!sConditionMgr->IsObjectMeetingVisibilityByObjectIdConditions(obj->GetTypeId(), obj->GetEntry(), const_cast<WorldObject*>(this)))
+ return false;
+
bool corpseVisibility = false;
if (distanceCheck)
{