diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.cpp | 60 | ||||
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.h | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 3 |
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) { |