aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Conditions/ConditionMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Conditions/ConditionMgr.cpp')
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp63
1 files changed, 56 insertions, 7 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 48d22c458f4..b8fccb7ecdb 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -92,7 +92,8 @@ char const* const ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX_D
"AreaTrigger Client Triggered",
"Trainer Spell",
"Object Visibility (by ID)",
- "Spawn Group"
+ "Spawn Group",
+ "Player Condition"
};
ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[CONDITION_MAX] =
@@ -657,8 +658,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const
case CONDITION_PLAYER_CONDITION:
{
if (Player const* player = object->ToPlayer())
- if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(ConditionValue1))
- condMeets = ConditionMgr::IsPlayerMeetingCondition(player, playerCondition);
+ condMeets = ConditionMgr::IsPlayerMeetingCondition(player, ConditionValue1);
break;
}
case CONDITION_PRIVATE_OBJECT:
@@ -1444,6 +1444,40 @@ void ConditionMgr::LoadConditions(bool isReload)
for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_GRAVEYARD])
addToGraveyardData(id, conditions);
+ struct
+ {
+ bool operator()(uint32 playerConditionId, std::vector<Condition> const& conditions, ConditionsByEntryMap const& referenceConditions) const
+ {
+ return std::any_of(conditions.begin(), conditions.end(), [&](Condition const& condition)
+ {
+ if (condition.ConditionType == CONDITION_PLAYER_CONDITION)
+ {
+ if (condition.ConditionValue1 == playerConditionId)
+ return true;
+ }
+ else if (condition.ReferenceId)
+ {
+ auto refItr = referenceConditions.find({ condition.ReferenceId, 0, 0 });
+ if (refItr != referenceConditions.end())
+ if (operator()(playerConditionId, *refItr->second, referenceConditions))
+ return true;
+ }
+ return false;
+ });
+ }
+ } isPlayerConditionIdUsedByCondition;
+
+ for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_PLAYER_CONDITION])
+ {
+ if (isPlayerConditionIdUsedByCondition(id.SourceEntry, *conditions, ConditionStore[CONDITION_SOURCE_TYPE_REFERENCE_CONDITION]))
+ {
+ TC_LOG_ERROR("sql.sql", "[Condition SourceType: CONDITION_SOURCE_TYPE_PLAYER_CONDITION, SourceGroup: {}, SourceEntry: {}, SourceId: {}] "
+ "has a circular reference to player condition id {}, removed all conditions for this SourceEntry!",
+ id.SourceGroup, id.SourceEntry, id.SourceId, id.SourceEntry);
+ conditions->clear();
+ }
+ }
+
TC_LOG_INFO("server.loading", ">> Loaded {} conditions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
}
@@ -2028,10 +2062,6 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
}
break;
}
- case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
- case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
- case CONDITION_SOURCE_TYPE_SMART_EVENT:
- break;
case CONDITION_SOURCE_TYPE_GRAVEYARD:
if (!sObjectMgr->FindGraveyardData(cond->SourceEntry, cond->SourceGroup))
{
@@ -2125,6 +2155,11 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
}
break;
}
+ case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
+ case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
+ case CONDITION_SOURCE_TYPE_SMART_EVENT:
+ case CONDITION_SOURCE_TYPE_PLAYER_CONDITION:
+ break;
default:
TC_LOG_ERROR("sql.sql", "{} Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString());
return false;
@@ -2822,6 +2857,20 @@ uint32 ConditionMgr::GetPlayerConditionLfgValue(Player const* player, PlayerCond
return 0;
}
+bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, uint32 conditionId)
+{
+ if (!conditionId)
+ return true;
+
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_PLAYER_CONDITION, conditionId, player))
+ return false;
+
+ if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(conditionId))
+ return IsPlayerMeetingCondition(player, playerCondition);
+
+ return true;
+}
+
bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition)
{
if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(condition->ContentTuningID, player->m_playerData->CtrOptions->ContentTuningConditionMask))