Core/Conditions: Added conditions for object visibility (#27565)

This commit is contained in:
ModoX
2022-01-12 21:54:03 +01:00
committed by GitHub
parent 80014010e7
commit b987a8968b
3 changed files with 65 additions and 3 deletions

View File

@@ -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;

View File

@@ -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()

View File

@@ -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)
{