93 "AreaTrigger Client Triggered",
95 "Object Visibility (by ID)",
99 "Player Choice Response"
104 { .
Name =
"None", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
105 { .Name =
"Aura", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
106 { .Name =
"Item Stored", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
107 { .Name =
"Item Equipped", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
108 { .Name =
"Zone", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
109 { .Name =
"Reputation", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
110 { .Name =
"Team", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
111 { .Name =
"Skill", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
112 { .Name =
"Quest Rewarded", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
113 { .Name =
"Quest Taken", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
114 { .Name =
"Drunken", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
115 { .Name =
"WorldState", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
116 { .Name =
"Active Event", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
117 { .Name =
"Instance Info", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
118 { .Name =
"Quest None", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
119 { .Name =
"Class", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
120 { .Name =
"Race", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
121 { .Name =
"Achievement", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
122 { .Name =
"Title", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
123 { .Name =
"SpawnMask", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
124 { .Name =
"Gender", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
125 { .Name =
"Unit State", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
126 { .Name =
"Map", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
127 { .Name =
"Area", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
128 { .Name =
"CreatureType", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
129 { .Name =
"Spell Known", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
130 { .Name =
"Phase", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
131 { .Name =
"Level", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
132 { .Name =
"Quest Completed", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
133 { .Name =
"Near Creature", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
134 { .Name =
"Near GameObject", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
135 { .Name =
"Object Entry or Guid", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
136 { .Name =
"Object TypeMask", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
137 { .Name =
"Relation", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
138 { .Name =
"Reaction", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
139 { .Name =
"Distance", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
140 { .Name =
"Alive", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
141 { .Name =
"Health Value", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
142 { .Name =
"Health Pct", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
143 { .Name =
"Realm Achievement", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
144 { .Name =
"In Water", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
145 { .Name =
"Terrain Swap", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
146 { .Name =
"Sit/stand state", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
147 { .Name =
"Daily Quest Completed", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
148 { .Name =
"Charmed", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
149 { .Name =
"Pet type", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
150 { .Name =
"On Taxi", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
151 { .Name =
"Quest state mask", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
152 { .Name =
"Quest objective progress", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
153 { .Name =
"Map Difficulty", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
154 { .Name =
"Is Gamemaster", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
155 { .Name =
"Object Entry or Guid", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
156 { .Name =
"Object TypeMask", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
157 { .Name =
"BattlePet Species Learned", .HasConditionValue1 =
true, .HasConditionValue2 =
true, .HasConditionValue3 =
true, .HasConditionStringValue1 =
false },
158 { .Name =
"On Scenario Step", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
159 { .Name =
"Scene In Progress", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
160 { .Name =
"Player Condition", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
161 { .Name =
"Private Object", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
162 { .Name =
"String ID", .HasConditionValue1 =
false, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
true },
163 { .Name =
"Label", .HasConditionValue1 =
true, .HasConditionValue2 =
false, .HasConditionValue3 =
false, .HasConditionStringValue1 =
false },
167 mConditionTargets({ target0, target1, target2 }),
168 mConditionMap(
nullptr),
169 mLastFailedCondition(
nullptr)
171 if (
WorldObject const* target = Coalesce<WorldObject const>(target0, target1, target2))
172 mConditionMap = target->GetMap();
178 mLastFailedCondition(nullptr)
198 bool condMeets =
false;
199 bool needsObject =
false;
212 if (
InstanceScript const* instance = instanceMap->GetInstanceScript())
233 ZoneScript const* zoneScript = bgMap->GetBattlegroundScript();
272 if (
Scenario const* scenario = instanceMap->GetInstanceScenario())
284 if (needsObject && !
object)
286 TC_LOG_DEBUG(
"condition",
"Condition object not found for {}", *
this);
322 condMeets = (
ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))) != 0;
465 condMeets = unit == toUnit;
509 condMeets = unit->IsAlive();
550 condMeets = unit->IsInWater();
565 condMeets = unit->IsStandState();
567 condMeets = unit->IsSitState();
580 condMeets = unit->IsCharmed();
586 if (
Pet const* pet = player->GetPet())
593 condMeets = player->IsInFlight();
636 condMeets = player->CanBeGameMaster();
638 condMeets = player->IsGameMaster();
653 condMeets = player->GetSceneMgr().GetActiveSceneCount(
ConditionValue1) > 0;
664 condMeets = !
object->GetPrivateObjectOwner().IsEmpty();
688 condMeets = !condMeets;
693 return condMeets &&
sScriptMgr->OnConditionCheck(
this, sourceInfo);
905 ABORT_MSG(
"Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
933template <
typename FormatContext>
936 ctx.advance_to(std::ranges::copy(
"[Condition SourceType: ("sv, ctx.out()).out);
940 ctx.advance_to(std::ranges::copy(
"Reference"sv, ctx.out()).out);
942 ctx.advance_to(std::ranges::copy(
"Unknown"sv, ctx.out()).out);
946 std::array<char, 20> buf;
950 ctx.advance_to(std::ranges::copy(
", SourceGroup: "sv, ctx.out()).out);
951 ctx.advance_to(std::ranges::copy(buf.data(), std::to_chars(buf.data(), buf.data() + buf.size(), condition.SourceGroup).ptr, ctx.out()).out);
954 ctx.advance_to(std::ranges::copy(
", SourceEntry: "sv, ctx.out()).out);
955 ctx.advance_to(std::ranges::copy(buf.data(), std::to_chars(buf.data(), buf.data() + buf.size(), condition.SourceEntry).ptr, ctx.out()).out);
959 ctx.advance_to(std::ranges::copy(
", SourceId: "sv, ctx.out()).out);
960 ctx.advance_to(std::ranges::copy(buf.data(), std::to_chars(buf.data(), buf.data() + buf.size(), condition.SourceId).ptr, ctx.out()).out);
963 ctx.advance_to(std::ranges::copy(
", ConditionType: "sv, ctx.out()).out);
964 ctx.advance_to(std::ranges::copy(buf.data(), std::to_chars(buf.data(), buf.data() + buf.size(),
int32(condition.ConditionType)).ptr, ctx.out()).out);
965 ctx.advance_to(std::ranges::copy(
" ("sv, ctx.out()).out);
969 ctx.advance_to(std::ranges::copy(
"Unknown"sv, ctx.out()).out);
971 ctx.advance_to(std::ranges::copy(
")]"sv, ctx.out()).out);
985 if (conditions.empty())
988 std::map<uint32, uint32> elseGroupSearcherTypeMasks;
989 for (ConditionContainer::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
992 ASSERT(i->isLoaded() &&
"ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
1009 itr->second &= i->GetSearcherTypeMaskForCondition();
1015 for (std::map<uint32, uint32>::const_iterator i = elseGroupSearcherTypeMasks.begin(); i != elseGroupSearcherTypeMasks.end(); ++i)
1024 std::map<uint32, bool> elseGroupStore;
1025 for (
Condition const& condition : conditions)
1027 TC_LOG_DEBUG(
"condition",
"ConditionMgr::IsPlayerMeetToConditionList {} val1: {}", condition, condition.ConditionValue1);
1028 if (condition.isLoaded())
1031 std::map<uint32, bool>::iterator itr = elseGroupStore.try_emplace(condition.ElseGroup,
true).first;
1035 if (condition.ReferenceId)
1041 if (condition.NegativeCondition)
1042 condMeets = !condMeets;
1045 itr->second =
false;
1049 TC_LOG_DEBUG(
"condition",
"ConditionMgr::IsPlayerMeetToConditionList {} Reference template -{} not found",
1050 condition, condition.ReferenceId);
1056 if (!condition.Meets(sourceInfo))
1057 itr->second =
false;
1061 for (std::map<uint32, bool>::const_iterator i = elseGroupStore.begin(); i != elseGroupStore.end(); ++i)
1082 if (conditions.empty())
1085 TC_LOG_DEBUG(
"condition",
"ConditionMgr::IsObjectMeetToConditions");
1129 switch (conditionType)
1157 TC_LOG_DEBUG(
"condition",
"GetConditionsForNotGroupedEntry: found conditions for type {} and entry {}",
uint32(sourceType), entry);
1190 TC_LOG_DEBUG(
"condition",
"IsObjectMeetingSpellClickConditions: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1202 TC_LOG_DEBUG(
"condition",
"HasConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1213 TC_LOG_DEBUG(
"condition",
"GetConditionsForVehicleSpell: found conditions for Vehicle entry {} spell {}", creatureId, spellId);
1225 TC_LOG_DEBUG(
"condition",
"GetConditionsForSmartEvent: found conditions for Smart Event entry or guid {} eventId {}", entryOrGuid, eventId);
1237 TC_LOG_DEBUG(
"condition",
"GetConditionsForNpcVendor: found conditions for creature entry {} item {}", creatureId, itemId);
1249 TC_LOG_DEBUG(
"condition",
"GetConditionsForNpcVendor: found conditions for creature entry {} item {}", playerChoiceId, playerChoiceResponseId);
1264 return itr->second.get();
1273 TC_LOG_DEBUG(
"condition",
"IsObjectMeetingTrainerSpellConditions: found conditions for trainer id {} spell {}", trainerId, spellId);
1284 TC_LOG_DEBUG(
"condition",
"IsObjectMeetingVisibilityByObjectIdConditions: found conditions for objectType {} entry {} guid {}", obj->
GetTypeId(), obj->
GetEntry(), obj->
GetGUID());
1305 sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
1310 QueryResult result =
WorldDatabase.Query(
"SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
1311 "ConditionValue1, ConditionValue2, ConditionValue3, ConditionStringValue1, "
1312 "NegativeCondition, ErrorType, ErrorTextId, ScriptName FROM conditions");
1316 TC_LOG_INFO(
"server.loading",
">> Loaded 0 conditions. DB table `conditions` is empty!");
1324 auto [itr, inserted] =
ConditionStore[sourceType].try_emplace(
id,
nullptr);
1326 itr->second = std::make_shared<std::vector<Condition>>();
1332 Field* fields = result->Fetch();
1351 if (iConditionTypeOrReference >= 0)
1354 if (iSourceTypeOrReferenceId >= 0)
1357 if (iConditionTypeOrReference < 0)
1359 if (iConditionTypeOrReference == iSourceTypeOrReferenceId)
1361 TC_LOG_ERROR(
"sql.sql",
"Condition reference {} is referencing self, skipped", iSourceTypeOrReferenceId);
1367 char const* rowType =
"reference template";
1368 if (iSourceTypeOrReferenceId >= 0)
1369 rowType =
"reference";
1372 TC_LOG_ERROR(
"sql.sql",
"Condition {} {} has useless data in ConditionTarget ({})!", rowType, iSourceTypeOrReferenceId, cond.
ConditionTarget);
1374 TC_LOG_ERROR(
"sql.sql",
"Condition {} {} has useless data in value1 ({})!", rowType, iSourceTypeOrReferenceId, cond.
ConditionValue1);
1376 TC_LOG_ERROR(
"sql.sql",
"Condition {} {} has useless data in value2 ({})!", rowType, iSourceTypeOrReferenceId, cond.
ConditionValue2);
1378 TC_LOG_ERROR(
"sql.sql",
"Condition {} {} has useless data in value3 ({})!", rowType, iSourceTypeOrReferenceId, cond.
ConditionValue3);
1383 if (iSourceTypeOrReferenceId < 0)
1386 TC_LOG_ERROR(
"sql.sql",
"Condition reference template {} has useless data in SourceGroup ({})!", iSourceTypeOrReferenceId, cond.
SourceGroup);
1388 TC_LOG_ERROR(
"sql.sql",
"Condition reference template {} has useless data in SourceEntry ({})!", iSourceTypeOrReferenceId, cond.
SourceEntry);
1390 TC_LOG_ERROR(
"sql.sql",
"Condition reference template {} has useless data in SourceId ({})!", iSourceTypeOrReferenceId, cond.
SourceId);
1422 getOrInitConditions(cond.
SourceType, { cond.SourceGroup, cond.SourceEntry, cond.SourceId })->emplace_back(std::move(cond));
1425 while (result->NextRow());
1471 for (
Condition const& condition : *conditions)
1476 for (
Condition const& condition : *conditions)
1489 return std::ranges::any_of(conditions, [&](
Condition const& condition)
1493 if (condition.ConditionValue1 == playerConditionId)
1495 auto playerCondItr = store[CONDITION_SOURCE_TYPE_PLAYER_CONDITION].find({ 0, int32(condition.ConditionValue1), 0 });
1497 if (
operator()(playerConditionId, *playerCondItr->second, store))
1504 if (
operator()(playerConditionId, *refItr->second, store))
1510 } isPlayerConditionIdUsedByCondition;
1514 if (isPlayerConditionIdUsedByCondition(
id.SourceEntry, *conditions, ConditionStore))
1516 TC_LOG_ERROR(
"sql.sql",
"[Condition SourceType: CONDITION_SOURCE_TYPE_PLAYER_CONDITION, SourceGroup: {}, SourceEntry: {}, SourceId: {}] "
1517 "has a circular reference to player condition id {}, removed all conditions for this SourceEntry!",
1518 id.SourceGroup,
id.SourceEntry,
id.SourceId,
id.SourceEntry);
1519 conditions->clear();
1530 for (
Condition const& condition : *conditions)
1531 TC_LOG_ERROR(
"sql.sql",
"{} LootTemplate {} not found.", condition,
id.SourceGroup);
1538 for (
Condition const& condition : *conditions)
1539 TC_LOG_ERROR(
"sql.sql",
"{} Item {} not found in LootTemplate {}.", condition,
id.SourceEntry,
id.SourceGroup);
1546 if (pMenuBounds.first != pMenuBounds.second)
1548 for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
1549 if (itr->second.MenuID ==
id.SourceGroup && (itr->second.TextID ==
uint32(
id.SourceEntry) ||
id.SourceEntry == 0))
1550 itr->second.Conditions = { conditions };
1555 for (
Condition const& condition : *conditions)
1556 TC_LOG_ERROR(
"sql.sql",
"{} GossipMenu {} not found.", condition, id.SourceGroup);
1562 for (
auto& [_, gossipMenuItem] : pMenuItemBounds)
1564 if (gossipMenuItem.MenuID ==
id.SourceGroup && gossipMenuItem.OrderIndex ==
uint32(
id.SourceEntry))
1566 gossipMenuItem.Conditions = { conditions };
1571 for (
Condition const& condition : *conditions)
1572 TC_LOG_ERROR(
"sql.sql",
"{} GossipMenuId {} Item {} not found.", condition,
id.SourceGroup,
id.SourceEntry);
1579 uint32 conditionEffMask = cond.SourceGroup;
1580 std::list<uint32> sharedMasks;
1581 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1584 if (conditionEffMask & (1 << spellEffectInfo.EffectIndex))
1586 switch (cond.ConditionType)
1588 case CONDITION_OBJECT_ENTRY_GUID:
1590 uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType());
1591 if ((implicitTargetMask & TARGET_FLAG_UNIT_MASK) && cond.ConditionValue1 != TYPEID_UNIT && cond.ConditionValue1 != TYPEID_PLAYER)
1593 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table - spell {} EFFECT_{} - "
1594 "target requires ConditionValue1 to be either TYPEID_UNIT ({}) or TYPEID_PLAYER ({})", cond, spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER));
1598 if ((implicitTargetMask & TARGET_FLAG_GAMEOBJECT_MASK) && cond.ConditionValue1 != TYPEID_GAMEOBJECT)
1600 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table - spell {} EFFECT_{} - "
1601 "target requires ConditionValue1 to be TYPEID_GAMEOBJECT ({})", cond, spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_GAMEOBJECT));
1605 if ((implicitTargetMask & TARGET_FLAG_CORPSE_MASK) && cond.ConditionValue1 != TYPEID_CORPSE)
1607 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table - spell {} EFFECT_{} - "
1608 "target requires ConditionValue1 to be TYPEID_CORPSE ({})", cond, spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_CORPSE));
1619 auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [&](uint32 mask) { return !!(mask & (1 << spellEffectInfo.EffectIndex)); });
1620 if (itr != sharedMasks.end())
1624 uint32 sharedMask = 1 << spellEffectInfo.EffectIndex;
1625 for (size_t effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo->GetEffects().size(); ++effIndex)
1626 if (spellInfo->GetEffect(SpellEffIndex(effIndex)).ImplicitTargetConditions == spellEffectInfo.ImplicitTargetConditions)
1627 sharedMask |= 1 << effIndex;
1629 sharedMasks.push_back(sharedMask);
1632 for (
uint32 effectMask : sharedMasks)
1635 if (
uint32 commonMask = effectMask & conditionEffMask)
1637 size_t firstEffIndex = 0;
1638 for (; firstEffIndex < spellInfo->
GetEffects().size(); ++firstEffIndex)
1639 if ((1 << firstEffIndex) & effectMask)
1642 if (firstEffIndex >= spellInfo->
GetEffects().size())
1646 std::shared_ptr<ConditionContainer> sharedList = spellInfo->
GetEffect(
SpellEffIndex(firstEffIndex)).ImplicitTargetConditions;
1652 if (conditionEffMask != effectMask)
1654 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table, has incorrect SourceGroup {} (spell effectMask) set - "
1655 "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring (Difficulty {}).",
1664 sharedList = std::make_shared<ConditionContainer>();
1665 bool assigned =
false;
1666 for (
size_t i = firstEffIndex; i < spellInfo->
GetEffects().size(); ++i)
1668 if ((1 << i) & commonMask)
1678 sharedList->push_back(cond);
1687 if (!
id.SourceEntry)
1692 for (
uint32 areaId : phaseInfo->Areas)
1694 if (std::vector<PhaseAreaInfo>* phases =
const_cast<std::vector<PhaseAreaInfo>*
>(
sObjectMgr->GetPhasesForArea(areaId)))
1698 if (phase.PhaseInfo->Id ==
id.SourceGroup)
1700 phase.Conditions.insert(phase.Conditions.end(), conditions->begin(), conditions->end());
1711 else if (std::vector<PhaseAreaInfo>* phases =
const_cast<std::vector<PhaseAreaInfo>*
>(
sObjectMgr->GetPhasesForArea(
id.SourceEntry)))
1715 if (phase.PhaseInfo->Id ==
id.SourceGroup)
1717 phase.Conditions.insert(phase.Conditions.end(), conditions->begin(), conditions->end());
1723 for (
Condition const& condition : *conditions)
1724 TC_LOG_ERROR(
"sql.sql",
"{} Area {} does not have phase {}.", condition,
id.SourceEntry,
id.SourceGroup);
1731 graveyard->Conditions = { conditions };
1735 for (
Condition const& condition : *conditions)
1736 TC_LOG_ERROR(
"sql.sql",
"{}, Graveyard {} does not have ghostzone {}.", condition,
id.SourceEntry,
id.SourceGroup);
1747 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `creature_loot_template`, ignoring.", *cond);
1756 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", *cond);
1765 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `fishing_loot_template`, ignoring.", *cond);
1774 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", *cond);
1783 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `item_loot_template`, ignoring.", *cond);
1792 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `mail_loot_template`, ignoring.", *cond);
1801 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `milling_loot_template`, ignoring.", *cond);
1810 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", *cond);
1819 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", *cond);
1828 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `reference_loot_template`, ignoring.", *cond);
1837 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `skinning_loot_template`, ignoring.", *cond);
1846 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `spell_loot_template`, ignoring.", *cond);
1856 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", *cond);
1862 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table, has incorrect SourceGroup (spell effectMask) set, ignoring.", *cond);
1870 if (!((1 << spellEffectInfo.EffectIndex) & cond->
SourceGroup))
1873 if (spellEffectInfo.ChainTargets > 0)
1876 switch (spellEffectInfo.TargetA.GetSelectionCategory())
1888 switch (spellEffectInfo.TargetB.GetSelectionCategory())
1900 switch (spellEffectInfo.Effect)
1917 TC_LOG_ERROR(
"sql.sql",
"SourceEntry {} SourceGroup {} in `condition` table - spell {} does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ or is not SPELL_EFFECT_PERSISTENT_AREA_AURA or SPELL_EFFECT_APPLY_AREA_AURA_* for effect {}, SourceGroup needs correction, ignoring.", cond->
SourceEntry, origGroup, cond->
SourceEntry,
uint32(spellEffectInfo.EffectIndex));
1918 cond->
SourceGroup &= ~(1 << spellEffectInfo.EffectIndex);
1929 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", *cond);
1940 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", *cond);
1948 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry specifies non-existing quest, skipped.", *cond);
1955 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", *cond);
1961 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", *cond);
1968 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", *cond);
1974 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", *cond);
1982 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", *cond);
1988 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, item does not exist, ignoring.", *cond);
1997 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in Map.db2, ignoring.", *cond);
2006 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in AreaTable.db2, ignoring.", *cond);
2014 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in `graveyard_zone`, ignoring.", *cond);
2021 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table, unexpected SourceEntry value (expected 0 or 1), ignoring.", *cond);
2024 if (!
sAreaTriggerDataStore->GetAreaTriggerTemplate({ uint32(cond->SourceGroup), cond->SourceEntry == 1 }))
2026 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table, does not exist in `areatrigger_template`, ignoring.", *cond);
2033 TC_LOG_ERROR(
"sql.sql",
"{} does not exist in `conversation_line_template`, ignoring.", *cond);
2040 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exists in AreaTrigger.db2, ignoring.", *cond);
2048 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `trainer`, ignoring.", *cond);
2053 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", *cond);
2062 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, is no valid object type, ignoring.", *cond);
2070 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", *cond);
2078 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in `gameobject_template`, ignoring.", *cond);
2084 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, uses unchecked type id, ignoring.", *cond);
2094 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in `spawn_group_template`, ignoring.", *cond);
2099 TC_LOG_ERROR(
"sql.sql",
"{} in `spawn_group_template` table cannot have SPAWNGROUP_FLAG_SYSTEM flags, ignoring.", *cond);
2107 if (!skillLineAbility)
2109 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in SkillLineAbility.db2, ignoring.", *cond);
2114 TC_LOG_ERROR(
"sql.sql",
"{} in SkillLineAbility.db2 does not have AcquireMethod = {} (LearnedOrAutomaticCharLevel), ignoring.",
2125 TC_LOG_ERROR(
"sql.sql",
"{} SourceGroup in `condition` table, does not exist in `playerchoice`, ignoring.", *cond);
2130 TC_LOG_ERROR(
"sql.sql",
"{} SourceEntry in `condition` table, does not exist in `playerchoice_response`, ignoring.", *cond);
2141 TC_LOG_ERROR(
"sql.sql",
"{} Invalid ConditionSourceType in `condition` table, ignoring.", *cond);
2156 TC_LOG_ERROR(
"sql.sql",
"{} must have `NegativeCondition` or `ScriptName` in `condition` table, ignoring.", *cond);
2172 TC_LOG_ERROR(
"sql.sql",
"{} spell {} has non existing effect index ({}) (must be 0..{}), skipped.",
2179 TC_LOG_ERROR(
"sql.sql",
"{} spell {} effect index {} is not an aura, skipped.",
2196 TC_LOG_ERROR(
"sql.sql",
"{} Zero item count in ConditionValue2, skipped.", *cond);
2222 TC_LOG_ERROR(
"sql.sql",
"{} requires to be in area ({}) which is a subzone but zone expected, skipped.", *cond, cond->
ConditionValue1);
2314 if (!invalidRaceMask.
IsEmpty())
2316 TC_LOG_ERROR(
"sql.sql",
"{} has non existing racemask ({}), skipped.", *cond, invalidRaceMask.
RawValue);
2469 TC_LOG_ERROR(
"sql.sql",
"{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", *cond, cond->
ConditionValue1);
2474 TC_LOG_ERROR(
"sql.sql",
"{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", *cond, cond->
ConditionValue1);
2488 TC_LOG_ERROR(
"sql.sql",
"{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", *cond, cond->
ConditionValue1);
2493 TC_LOG_ERROR(
"sql.sql",
"{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", *cond, cond->
ConditionValue1);
2507 TC_LOG_ERROR(
"sql.sql",
"{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", *cond, cond->
ConditionValue1);
2512 TC_LOG_ERROR(
"sql.sql",
"{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", *cond, cond->
ConditionValue1);
2575 TC_LOG_ERROR(
"sql.sql",
"{} using deprecated condition type CONDITION_SPAWNMASK.", *cond);
2654 TC_LOG_ERROR(
"sql.sql",
"{} has unsupported ConditionValue3 {} (INSTANCE_INFO_GUID_DATA), skipped.", *cond, cond->
ConditionValue3);
2684 TC_LOG_ERROR(
"sql.sql",
"{} has invalid (greater than {}) value2 ({}), skipped.", *cond,
2722 TC_LOG_ERROR(
"sql.sql",
"{} Invalid ConditionType in `condition` table, ignoring.", *cond);
2728 TC_LOG_ERROR(
"sql.sql",
"{} in `condition` table, has incorrect ConditionTarget set, ignoring.", *cond);
2746 TC_LOG_ERROR(
"sql.sql",
"{} has useless data in ConditionValue{} ({})!", *cond, index, value);
2751 TC_LOG_ERROR(
"sql.sql",
"{} has useless data in ConditionStringValue{} ({})!", *cond, index, value);
2757 conditionsMap.clear();
2764 switch (comparisonType)
2767 return value1 == value2;
2769 return value1 != value2;
2771 return value1 > value2;
2773 return value1 >= value2;
2775 return value1 < value2;
2777 return value1 <= value2;
2784template <std::
size_t N>
2787 static_assert(N < 8,
"Logic array size must be equal to or less than 8");
2789 uint32 resultsMask = results.to_ulong() ^ (logic >> 16);
2790 uint32 result = resultsMask & 1;
2791 for (std::size_t i = 1; i < results.size(); ++i)
2793 switch ((logic >> (2 * (i - 1))) & 3)
2796 result &= (resultsMask >> i) & 1;
2799 result |= (resultsMask >> i) & 1;
2809template <
typename T, std::size_t N,
typename... ExtraParams,
Trinity::invocable_r<bool,
Player const*, T,
typename ExtraParams::value_type...> Predicate>
2812 static_assert(((std::tuple_size_v<ExtraParams> == N) && ...));
2813 std::bitset<N> results;
2815 for (std::size_t i = 0; i < N; ++i)
2816 if (predicate(player, conditions[i],
params[i]...))
2841 if (!selectedRandomDungeon)
2845 if (
Quest const* quest =
sObjectMgr->GetQuestTemplate(reward->firstQuest))
2903 if (minLevel && level >= minLevel && (!maxLevel || level <= maxLevel))
2906 if (maxLevel && level <= maxLevel && (!minLevel || level >= minLevel))
2911 if (minLevel && level < minLevel)
2914 if (maxLevel && level > maxLevel)
2950 if (std::ranges::any_of(condition->
SkillID, [](
uint32 skillId) { return skillId != 0; }))
2958 return skillValue != 0 && skillValue > minSkill && skillValue < maxSkill;
2967 int32 languageSkill = 0;
2969 languageSkill = 300;
2973 languageSkill = std::max<int32>(languageSkill, player->
GetSkillValue(languageDesc.second.SkillId));
2985 auto isMinFactionConditionSatisfied = [](
Player const* player,
uint32 factionId,
uint8 minReputationRank)
2996 auto isMaxFactionConditionSatisfied = [](
Player const* player,
uint32 factionId,
uint8 maxReputationRank)
3015 std::bitset<minFactionResults.size() + 1> results(minFactionResults.to_ulong());
3122 return !spellId || player->
HasSpell(spellId);
3123 }, player, condition->
SpellID);
3129 if (condition->
ItemID[0])
3136 EnumFlag<ItemSearchLocation> where = ItemSearchLocation::Equipment;
3137 if ((itemFlags & 1) != 0)
3138 where |= ItemSearchLocation::Bank | ItemSearchLocation::ReagentBank | ItemSearchLocation::AccountBank;
3139 if ((itemFlags & 2) == 0)
3140 where |= ItemSearchLocation::Inventory;
3142 uint32 foundCount = 0;
3143 bool foundItemCount = !player->ForEachItem(where, [&](Item const* item)
3145 if (item->GetEntry() == uint32(itemId))
3147 foundCount += item->GetCount();
3148 if (foundCount >= itemCount)
3149 return ItemSearchCallbackResult::Stop;
3152 return ItemSearchCallbackResult::Continue;
3168 if (condition->CurrencyID[0])
3173 }, player, condition->CurrencyID, condition->CurrencyCount);
3179 if (condition->Explored[0] || condition->Explored[1])
3181 for (std::size_t i = 0; i < condition->Explored.size(); ++i)
3187 if (condition->AuraSpellID[0])
3197 return player->
HasAura(spellId);
3198 }, player, condition->AuraSpellID, condition->AuraStacks);
3204 if (condition->Time[0])
3209 if (condition->Time[1])
3221 if (condition->WorldStateExpressionID)
3224 if (!worldStateExpression)
3227 if (!IsMeetingWorldStateExpression(player->
GetMap(), worldStateExpression))
3231 if (condition->WeatherID)
3235 if (condition->Achievement[0])
3244 return player->HasAchieved(achievementId);
3245 }, player, condition->Achievement);
3251 if (condition->LfgStatus[0])
3256 }, player, condition->LfgStatus, condition->LfgCompare, condition->LfgValue);
3262 if (condition->AreaID[0])
3267 }, player, condition->AreaID);
3273 if (condition->MinExpansionLevel != -1 && player->
GetSession()->
GetExpansion() < condition->MinExpansionLevel)
3276 if (condition->MaxExpansionLevel != -1 && player->
GetSession()->
GetExpansion() > condition->MaxExpansionLevel)
3279 if (condition->MinExpansionLevel != -1 && condition->MinExpansionTier != -1 && !player->
IsGameMaster()
3284 if (condition->PhaseID || condition->PhaseGroupID || condition->PhaseUseFlags)
3288 if (condition->QuestKillID)
3290 Quest const* quest =
sObjectMgr->GetQuestTemplate(condition->QuestKillID);
3301 return objective.Type == QUEST_OBJECTIVE_MONSTER && uint32(objective.ObjectID) == creatureId;
3304 }, player, condition->QuestKillMonster);
3311 if (condition->MinAvgItemLevel &&
int32(std::floor(player->
m_playerData->AvgItemLevel[0])) < condition->MinAvgItemLevel)
3314 if (condition->MaxAvgItemLevel &&
int32(std::floor(player->
m_playerData->AvgItemLevel[0])) > condition->MaxAvgItemLevel)
3317 if (condition->MinAvgEquippedItemLevel &&
uint32(std::floor(player->
m_playerData->AvgItemLevel[1])) < condition->MinAvgEquippedItemLevel)
3320 if (condition->MaxAvgEquippedItemLevel &&
uint32(std::floor(player->
m_playerData->AvgItemLevel[1])) > condition->MaxAvgEquippedItemLevel)
3326 if (condition->CovenantID && player->
m_playerData->CovenantID != condition->CovenantID)
3329 if (std::ranges::any_of(condition->TraitNodeEntryID, [](
int32 traitNodeEntryId) { return traitNodeEntryId != 0; }))
3333 if (!traitNodeEntryId)
3338 for (
auto const& [_, traitConfig] : player->m_activePlayerData->TraitConfigs)
3348 if (traitEntry.TraitNodeEntryID == traitNodeEntryId)
3349 return traitEntry.Rank;
3355 && (!minRank || *rank >= minRank)
3356 && (!maxRank || *rank <= maxRank);
3357 }, player, condition->TraitNodeEntryID, condition->TraitNodeEntryMinRank, condition->TraitNodeEntryMaxRank);
3377 return irand(std::min(arg1, arg2), std::max(arg1, arg2));
3396 return localTime->tm_hour *
MINUTE + localTime->tm_min;
3402 return sRealmList->GetCurrentRealmId().Region;
3409 return currentHour <= 12 ? (currentHour ? currentHour : 12) : currentHour - 12;
3416 return difficulty->OldEnumValue;
3449 uint32 raidOrigin = 1135695600;
3451 raidOrigin = region->Raidorigin;
3453 return (now - raidOrigin) /
WEEK;
3587 std::mt19937 mt(arg2 ? arg2 : 1);
3588 return mt() % arg1 + 1;
3669 switch (operatorType)
3689 return leftValue != 0;
3693 switch (compareLogic)
3718 bool finalResult =
EvalRelOp(buffer, map);
3726 bool secondResult =
EvalRelOp(buffer, map);
3728 switch (resultLogic)
3736 }
while (buffer.
rpos() < buffer.
size());
3740catch (std::exception
const& e)
3742 TC_LOG_ERROR(
"condition",
"Failed to parse WorldStateExpression {}: {}", expression->ID, e.what());
3757 return unit == otherUnit;
3788 }) !=
nullptr ? value : 0;
3793 }) !=
nullptr ? value : 0;
3798 }) !=
nullptr ? value : 0;
3803 }) !=
nullptr ? value : 0;
3808 }) !=
nullptr ? value : 0;
3813 }) !=
nullptr ? value : 0;
3818 }) !=
nullptr ? value : 0;
3844 return std::ranges::count_if(unit->
getAttackers(), [unit](
Unit const* attacker)
3846 float distance = std::max(unit->GetCombatReach() + attacker->GetCombatReach() + 1.3333334f, 5.0f);
3847 if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || attacker->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3849 return unit->GetExactDistSq(attacker) < distance * distance;
3893 return std::ranges::count_if(unit->
getAttackers(), [unit](
Unit const* attacker)
3895 float distance = std::max(unit->GetCombatReach() + attacker->GetCombatReach() + 1.3333334f, 5.0f);
3896 if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || attacker->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3898 return unit->GetExactDistSq(attacker) >= distance * distance;
3905 float distance = std::max(unit->
GetCombatReach() + target->GetCombatReach() + 1.3333334f, 5.0f);
3914 float distance = std::max(unit->
GetCombatReach() + target->GetCombatReach() + 1.3333334f, 5.0f);
3923 return unit->
HasSpell(value) ? value : 0;
3958 return unit->
HasAura(value) ? value : 0;
3993 return unit->
GetLevel() >= levelRange->MinLevel && unit->
GetLevel() <= levelRange->MaxLevel ? value : 0;
4008 }) !=
nullptr ? value : 0;
4028 meets = unitValue == condition->
Value[i];
4031 meets = unitValue != condition->
Value[i];
4034 meets = unitValue < condition->
Value[i];
4037 meets = unitValue <= condition->
Value[i];
4040 meets = unitValue > condition->
Value[i];
4043 meets = unitValue >= condition->
Value[i];
#define sAreaTriggerDataStore
bool PlayerConditionCompare(int32 comparisonType, int32 value1, int32 value2)
int32 GetUnitConditionVariable(Unit const *unit, Unit const *otherUnit, UnitConditionVariable variable, int32 value)
bool EvalRelOp(ByteBuffer &buffer, Map const *map)
int32 EvalSingleValue(ByteBuffer &buffer, Map const *map)
static std::bitset< N > GetPlayerConditionSingleResult(Predicate predicate, Player const *player, std::array< T, N > const &conditions, ExtraParams const &... params)
bool PlayerConditionLogic(uint32 logic, std::bitset< N > &results)
int32 EvalValue(ByteBuffer &buffer, Map const *map)
std::vector< Condition > ConditionContainer
@ CONDITION_SOURCE_TYPE_MAX
@ CONDITION_SOURCE_TYPE_CONVERSATION_LINE
@ CONDITION_SOURCE_TYPE_VEHICLE_SPELL
@ CONDITION_SOURCE_TYPE_SKILL_LINE_ABILITY
@ CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_TERRAIN_SWAP
@ CONDITION_SOURCE_TYPE_NPC_VENDOR
@ CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION
@ CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT
@ CONDITION_SOURCE_TYPE_REFERENCE_CONDITION
@ CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_PHASE
@ CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_SMART_EVENT
@ CONDITION_SOURCE_TYPE_PLAYER_CHOICE_RESPONSE
@ CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_AREATRIGGER_CLIENT_TRIGGERED
@ CONDITION_SOURCE_TYPE_AREATRIGGER
@ CONDITION_SOURCE_TYPE_PLAYER_CONDITION
@ CONDITION_SOURCE_TYPE_SPAWN_GROUP
@ CONDITION_SOURCE_TYPE_SPELL
@ CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY
@ CONDITION_SOURCE_TYPE_GOSSIP_MENU
@ CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE
@ CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET
@ CONDITION_SOURCE_TYPE_GRAVEYARD
@ CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_TRAINER_SPELL
@ CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_SPELL_PROC
@ CONDITION_SOURCE_TYPE_QUEST_AVAILABLE
@ CONDITION_SOURCE_TYPE_NONE
@ CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED
std::array< ConditionsByEntryMap, CONDITION_SOURCE_TYPE_MAX > ConditionEntriesByTypeArray
@ INSTANCE_INFO_BOSS_STATE
@ INSTANCE_INFO_GUID_DATA
@ CONDITION_NEAR_GAMEOBJECT
@ CONDITION_QUESTREWARDED
@ CONDITION_REALM_ACHIEVEMENT
@ CONDITION_QUEST_OBJECTIVE_PROGRESS
@ CONDITION_DAILY_QUEST_DONE
@ CONDITION_SPAWNMASK_DEPRECATED
@ CONDITION_INSTANCE_INFO
@ CONDITION_PRIVATE_OBJECT
@ CONDITION_OBJECT_ENTRY_GUID
@ CONDITION_DIFFICULTY_ID
@ CONDITION_SCENARIO_STEP
@ CONDITION_BATTLE_PET_COUNT
@ CONDITION_REPUTATION_RANK
@ CONDITION_QUEST_COMPLETE
@ CONDITION_OBJECT_ENTRY_GUID_LEGACY
@ CONDITION_ITEM_EQUIPPED
@ CONDITION_SCENE_IN_PROGRESS
@ CONDITION_PLAYER_CONDITION
@ CONDITION_NEAR_CREATURE
@ CONDITION_CREATURE_TYPE
@ CONDITION_TYPE_MASK_LEGACY
@ RELATION_IN_RAID_OR_PARTY
#define sConversationDataStore
DB2Storage< PhaseEntry > sPhaseStore("Phase.db2", &PhaseLoadInfo::Instance)
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< SkillLineEntry > sSkillLineStore("SkillLine.db2", &SkillLineLoadInfo::Instance)
DB2Storage< AchievementEntry > sAchievementStore("Achievement.db2", &AchievementLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< WorldStateExpressionEntry > sWorldStateExpressionStore("WorldStateExpression.db2", &WorldStateExpressionLoadInfo::Instance)
DB2Storage< CharTitlesEntry > sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
DB2Storage< SceneScriptPackageEntry > sSceneScriptPackageStore("SceneScriptPackage.db2", &SceneScriptPackageLoadInfo::Instance)
DB2Storage< ScenarioStepEntry > sScenarioStepStore("ScenarioStep.db2", &ScenarioStepLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
DB2Storage< AreaTriggerEntry > sAreaTriggerStore("AreaTrigger.db2", &AreaTriggerLoadInfo::Instance)
DB2Storage< Cfg_RegionsEntry > sCfgRegionsStore("Cfg_Regions.db2", &CfgRegionsLoadInfo::Instance)
DB2Storage< SkillLineAbilityEntry > sSkillLineAbilityStore("SkillLineAbility.db2", &SkillLineAbilityLoadInfo::Instance)
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
#define MAX_UNIT_CONDITION_VALUES
@ InLFGFirstRandomDungeon
@ HasHarmfulAuraCanceledByDamage
@ HasHarmfulAuraWithPeriodicDamage
@ LevelWithinContentTuning
@ NumberOfRangedAttackers
@ HasHarmfulAuraDispelType
@ HasHelpfulAuraDispelType
WorldStateExpressionFunctions
WorldStateExpressionValueType
@ LearnedOrAutomaticCharLevel
WorldStateExpressionComparisonType
WorldStateExpressionLogic
WorldStateExpressionOperatorType
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
std::unordered_set< uint32 > params[2]
bool IsHolidayActive(HolidayIds id)
@ GRID_MAP_TYPE_MASK_PLAYER
@ GRID_MAP_TYPE_MASK_CREATURE
@ GRID_MAP_TYPE_MASK_GAMEOBJECT
@ GRID_MAP_TYPE_MASK_CORPSE
@ GRID_MAP_TYPE_MASK_AREATRIGGER
#define TC_LOG_DEBUG(filterType__, message__,...)
#define TC_LOG_ERROR(filterType__, message__,...)
#define TC_LOG_INFO(filterType__, message__,...)
LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false)
LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true)
LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject entry", true)
LootStore LootTemplates_Item("item_loot_template", "item entry", true)
LootStore LootTemplates_Milling("milling_loot_template", "item entry (herb)", true)
LootStore LootTemplates_Reference("reference_loot_template", "reference id", false)
LootStore LootTemplates_Disenchant("disenchant_loot_template", "item disenchant id", true)
LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry (ore)", true)
LootStore LootTemplates_Creature("creature_loot_template", "creature entry", true)
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template", "creature pickpocket lootid", true)
LootStore LootTemplates_Mail("mail_loot_template", "mail template id", false)
LootStore LootTemplates_Fishing("fishing_loot_template", "area id", true)
@ NUM_CLIENT_OBJECT_TYPES
std::pair< GossipMenusContainer::iterator, GossipMenusContainer::iterator > GossipMenusMapBoundsNonConst
std::optional< T > Optional
Optional helper class to wrap optional values within.
@ EQUIPMENT_SLOT_MAINHAND
#define INVENTORY_SLOT_BAG_0
#define MAX_QUEST_LOG_SIZE
@ QUEST_STATUS_INCOMPLETE
int32 irand(int32 min, int32 max)
constexpr uint32 GetMaxLevelForExpansion(uint32 expansion)
@ CREATURE_TYPE_GAS_CLOUD
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY
@ SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
@ SPELL_EFFECT_APPLY_AURA_ON_PET
@ SPELL_EFFECT_APPLY_AREA_AURA_PET
@ SPELL_EFFECT_APPLY_AREA_AURA_RAID
@ SPELL_EFFECT_PERSISTENT_AREA_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
@ SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS
@ SPELL_EFFECT_APPLY_AREA_AURA_OWNER
#define CLASSMASK_ALL_PLAYABLE
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_COMPREHEND_LANGUAGE
@ TARGET_SELECT_CATEGORY_CONE
@ TARGET_SELECT_CATEGORY_AREA
@ TARGET_SELECT_CATEGORY_NEARBY
@ TARGET_SELECT_CATEGORY_LINE
@ TARGET_SELECT_CATEGORY_TRAJ
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
@ UNIT_STAND_STATE_SUBMERGED
@ MOVEMENTFLAG_STRAFE_LEFT
@ MOVEMENTFLAG_STRAFE_RIGHT
@ UNIT_FLAG_PLAYER_CONTROLLED
@ UNIT_STATE_ALL_STATE_SUPPORTED
bool CompareValues(ComparisionType type, T val1, T val2)
std::vector< uint8 > HexStrToByteVector(std::string_view str, bool reverse=false)
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
struct CStringSentinel_T CStringSentinel
uint32 GetEffectMask() const
AuraApplication const * GetApplicationOfTarget(ObjectGuid guid) const
SpellInfo const * GetSpellInfo() const
ObjectGuid const & GetGUID() const
bool HasToy(uint32 itemId) const
bool isConditionTypeValid(Condition *cond) const
bool IsSpellUsedInSpellClickConditions(uint32 spellId) const
std::unordered_set< uint32 > SpellsUsedInSpellClickConditions
void addToLootTemplate(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions, LootTemplate *loot) const
bool IsObjectMeetingPlayerChoiceResponseConditions(uint32 playerChoiceId, int32 playerChoiceResponseId, Player const *player) const
bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player const *player, Creature const *vendor) const
bool IsObjectMeetToConditions(WorldObject const *object, ConditionContainer const &conditions) const
bool isSourceTypeValid(Condition *cond) const
uint32 GetSearcherTypeMaskForConditionList(ConditionContainer const &conditions) const
bool IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, ConditionSourceInfo &sourceInfo) const
static ConditionMgr * instance()
static bool IsMeetingWorldStateExpression(Map const *map, WorldStateExpressionEntry const *expression)
void addToGraveyardData(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const
bool IsObjectMeetToConditionList(ConditionSourceInfo &sourceInfo, ConditionContainer const &conditions) const
bool IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject const *clicker, WorldObject const *target) const
static bool IsUnitMeetingCondition(Unit const *unit, Unit const *otherUnit, UnitConditionEntry const *condition)
bool HasConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const
static void LogUselessConditionValue(Condition const *cond, uint8 index, uint32 value)
bool IsMapMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, Map const *map) const
bool IsObjectMeetingTrainerSpellConditions(uint32 trainerId, uint32 spellId, Player *player) const
ConditionEntriesByTypeArray ConditionStore
ConditionContainer const * GetConditionsForAreaTrigger(uint32 areaTriggerId, bool isServerSide) const
void addToSpellImplicitTargetConditions(Condition const &cond) const
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
bool IsObjectMeetingVisibilityByObjectIdConditions(WorldObject const *obj, WorldObject const *seer) const
void addToPhases(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
bool IsObjectMeetingSmartEventConditions(int64 entryOrGuid, uint32 eventId, uint32 sourceType, Unit const *unit, WorldObject const *baseObject) const
static bool CanHaveSourceGroupSet(ConditionSourceType sourceType)
void addToGossipMenuItems(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
void addToGossipMenus(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
static char const *const StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED]
static uint32 GetPlayerConditionLfgValue(Player const *player, PlayerConditionLfgStatus status)
static bool CanHaveConditionType(ConditionSourceType sourceType, ConditionTypes conditionType)
static bool CanHaveSourceIdSet(ConditionSourceType sourceType)
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX]
bool IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player const *player, Unit const *vehicle) const
void LoadConditions(bool isReload=false)
bool HasLabel(int32 cretureLabel) const
static bool IsInArea(uint32 objectAreaId, uint32 areaId)
constexpr bool HasFlag(T flag) const
Class used to access individual fields of database query result.
bool GetBool() const noexcept
uint32 GetUInt32() const noexcept
uint8 GetUInt8() const noexcept
int32 GetInt32() const noexcept
std::string GetString() const noexcept
std::vector< GameEventData > GameEventDataMap
ItemTemplate const * GetTemplate() const
LootTemplate * GetLootForConditionFill(uint32 loot_id)
bool HaveLootFor(uint32 loot_id) const
bool LinkConditions(ConditionId const &id, ConditionsReference reference)
bool IsBattlegroundOrArena() const
BattlegroundMap * ToBattlegroundMap()
Difficulty GetDifficultyID() const
InstanceMap * ToInstanceMap()
WeatherState GetZoneWeather(uint32 zoneId) const
GameObject * ToGameObject()
static bool InDbPhaseShift(WorldObject const *object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId)
ChrSpecialization GetPrimarySpecialization() const
UF::UpdateField< UF::PlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_PLAYER > m_playerData
Gender GetNativeGender() const override
uint16 GetSkillValue(uint32 skill) const
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
uint16 FindQuestSlot(uint32 quest_id) const
bool IsQuestCompletedBitSet(uint32 questId) const
bool CanRewardQuest(Quest const *quest, bool msg) const
WorldSession * GetSession() const
Item * GetItemByPos(uint16 pos) const
bool ModifierTreeSatisfied(uint32 modifierTreeId) const
bool HasExploredZone(uint32 areaId) const
bool IsGameMaster() const
QuestStatus GetQuestStatus(uint32 quest_id) const
static bool IsValidGender(uint8 Gender)
ReputationRank GetReputationRank(uint32 faction_id) const
Item * GetWeaponForAttack(WeaponAttackType attackType, bool useable=false) const
bool HasSpell(uint32 spell) const override
Group * GetGroup(Optional< uint8 > partyIndex)
int32 GetQuestSlotObjectiveData(uint16 slot, QuestObjective const &objective) const
ChrSpecializationEntry const * GetPrimarySpecializationEntry() const
ReputationMgr & GetReputationMgr()
static DrunkenState GetDrunkenstateByValue(uint8 value)
uint32 GetCurrencyQuantity(uint32 id) const
QuestObjectives const & GetObjectives() const
ReputationRank const * GetForcedRankIfAny(FactionTemplateEntry const *factionTemplateEntry) const
::Difficulty const Difficulty
SpellSchoolMask GetSchoolMask() const
uint64 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
std::vector< SpellEffectInfo > const & GetEffects() const
size_t GetThreatListSize() const
Utility class to enable range for loop syntax for multimap.equal_range uses.
uint32 GetChannelSpellId() const
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
float GetHealthPct() const
uint32 GetUnitMovementFlags() const
ThreatManager & GetThreatManager()
bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const
std::array< ObjectGuid, MAX_SUMMON_SLOT > m_SummonSlot
uint32 GetClassMask() const
uint32 GetMountDisplayId() const
ObjectGuid GetOwnerGUID() const override
bool HasUnitFlag(UnitFlags flags) const
ObjectGuid GetCharmedGUID() const
float GetCombatReach() const override
int32 GetMaxPower(Powers power) const
ObjectGuid GetCharmerOrOwnerGUID() const override
virtual bool HasSpell(uint32) const
ObjectGuid GetCreatorGUID() const override
bool IsOnVehicle(Unit const *vehicle) const
uint32 GetCreatureType() const
bool HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid=ObjectGuid::Empty) const
uint32 GetVirtualItemId(uint32 slot) const
uint32 GetAuraCount(uint32 spellId) const
ObjectGuid GetMinionGUID() const
bool HasUnitMovementFlag(uint32 f) const
AttackerSet const & getAttackers() const
bool HasAuraType(AuraType auraType) const
ObjectGuid GetCritterGUID() const
uint32 GetExtraUnitMovementFlags() const
int32 GetPower(Powers power) const
uint8 GetEffectiveLevel() const
bool IsInRaidWith(Unit const *unit) const
float GetPowerPct(Powers power) const
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
ObjectGuid GetCharmerGUID() const
AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraApplication *except=nullptr) const
bool IsInPartyWith(Unit const *unit) const
ObjectGuid GetTarget() const
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
constexpr uint32 GetMapId() const
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
ReputationRank GetReactionTo(WorldObject const *target) const
bool IsValidAssistTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
float GetDistance(WorldObject const *obj) const
CollectionMgr * GetCollectionMgr() const
uint8 GetExpansion() const
void SetPackedTime(uint32 packedTime)
bool IsInRange(WowTime const &from, WowTime const &to) const
virtual uint32 GetData(uint32) const
virtual uint64 GetData64(uint32) const
static constexpr ObjectData creatureData[]
@ DEFAULT_MAX_BATTLE_PETS_PER_SPECIES
WowTime const * GetWowTime()
tm const * GetDateAndTime()
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
constexpr TypeMask ConvertLegacyTypeMask(uint32 legacyTypeMask)
constexpr ::TypeID ConvertLegacyTypeID(TypeID legacyTypeID)
TC_GAME_API WorldStateTemplate const * GetWorldStateTemplate(int32 worldStateId)
TC_GAME_API int32 GetValue(int32 worldStateId, Map const *map)
EnumFlag< AreaFlags > GetFlags() const
EnumFlag< ChrSpecializationFlag > GetFlags() const
ChrSpecializationRole GetRole() const
std::size_t GetHash() const
bool HasConditionStringValue1
ConditionSourceInfo(WorldObject const *target0, WorldObject const *target1=nullptr, WorldObject const *target2=nullptr)
Condition const * mLastFailedCondition
std::array< WorldObject const *, MAX_CONDITION_TARGETS > mConditionTargets
Map const * mConditionMap
ConditionTypes ConditionType
std::string ConditionStringValue1
uint32 GetSearcherTypeMaskForCondition() const
ConditionSourceType SourceType
uint32 GetMaxAvailableConditionTargets() const
bool Meets(ConditionSourceInfo &sourceInfo) const
uint32 GetSubClass() const
PlayerChoiceResponse const * GetResponse(int32 responseId) const
std::array< uint32, 4 > ItemCount
std::array< uint16, 4 > MaxSkill
uint32 CurrentCompletedQuestLogic
std::array< int32, 4 > CurrentCompletedQuestID
std::array< int32, 4 > PrevQuestID
std::array< int32, 4 > CurrQuestID
std::array< uint16, 4 > SkillID
int8 ChrSpecializationRole
std::array< int32, 2 > MovementFlags
std::array< uint32, 3 > MinFactionID
int8 ChrSpecializationIndex
std::array< uint16, 4 > MinSkill
EnumFlag< PlayerConditionFlags > GetFlags() const
std::array< uint8, 3 > MinReputation
std::array< int32, 4 > ItemID
Trinity::RaceMask< int64 > RaceMask
std::array< int32, 4 > SpellID
float GetExactDist(float x, float y, float z) const
constexpr float GetExactDistSq(float x, float y, float z) const
bool IsStoringFlag() const
SkillLineAbilityAcquireMethod GetAcquireMethod() const
constexpr void UpdateData(std::span< V, Extent > data) noexcept
constexpr bool IsEmpty() const
constexpr bool HasRace(uint32 raceId) const
EnumFlag< UnitConditionFlags > GetFlags() const
std::array< int32, MAX_UNIT_CONDITION_VALUES > Value
std::array< uint8, MAX_UNIT_CONDITION_VALUES > Variable
std::array< uint8, MAX_UNIT_CONDITION_VALUES > Op