Core/Conditions: Refactor ConditionMgr internals to get rid of separate containers for some condition source types

Port From (https://github.com/TrinityCore/TrinityCore/commit/0b5406dd882c6d96bc1be6fd0a78375c3b316415)
This commit is contained in:
hondacrx
2024-02-06 09:39:26 -05:00
parent ebcad7dbc5
commit 80936edeab
12 changed files with 292 additions and 383 deletions
@@ -102,6 +102,9 @@ namespace Framework.Constants
TrainerSpell = 31, TrainerSpell = 31,
ObjectIdVisibility = 32, ObjectIdVisibility = 32,
SpawnGroup = 33, SpawnGroup = 33,
MaxDbAllowed,
ReferenceCondition = MaxDbAllowed,
Max Max
} }
+1 -1
View File
@@ -334,7 +334,7 @@ namespace Game.Chat
{ {
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count); handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count);
foreach (LootItem item in loot.items) foreach (LootItem item in loot.items)
if (!item.is_looted && !item.freeforall && item.conditions.Empty()) if (!item.is_looted && !item.freeforall && item.conditions.IsEmpty())
_ShowLootEntry(handler, item.itemid, item.count); _ShowLootEntry(handler, item.itemid, item.count);
if (!loot.GetPlayerFFAItems().Empty()) if (!loot.GetPlayerFFAItems().Empty())
+49 -1
View File
@@ -619,8 +619,10 @@ namespace Game.Conditions
{ {
StringBuilder ss = new(); StringBuilder ss = new();
ss.AppendFormat("[Condition SourceType: {0}", SourceType); ss.AppendFormat("[Condition SourceType: {0}", SourceType);
if (SourceType < ConditionSourceType.Max) if (SourceType < ConditionSourceType.MaxDbAllowed)
ss.AppendFormat(" ({0})", Global.ConditionMgr.StaticSourceTypeData[(int)SourceType]); ss.AppendFormat(" ({0})", Global.ConditionMgr.StaticSourceTypeData[(int)SourceType]);
else if (SourceType == ConditionSourceType.ReferenceCondition)
ss.Append(" (Reference)");
else else
ss.Append(" (Unknown)"); ss.Append(" (Unknown)");
if (Global.ConditionMgr.CanHaveSourceGroupSet(SourceType)) if (Global.ConditionMgr.CanHaveSourceGroupSet(SourceType))
@@ -659,6 +661,52 @@ namespace Game.Conditions
public bool NegativeCondition; public bool NegativeCondition;
} }
public struct ConditionId
{
public uint SourceGroup;
public int SourceEntry;
public uint SourceId;
public ConditionId(uint sourceGroup, int sourceEntry, uint sourceId)
{
SourceGroup = sourceGroup;
SourceEntry = sourceEntry;
SourceId = sourceId;
}
public override int GetHashCode()
{
return SourceGroup.GetHashCode() ^ SourceEntry.GetHashCode() ^ SourceId.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is ConditionId)
return (ConditionId)obj == this;
return false;
}
public static bool operator ==(ConditionId left, ConditionId right)
{
if (left.SourceGroup != right.SourceGroup)
return false;
if (left.SourceEntry != right.SourceEntry)
return false;
if (left.SourceId != right.SourceId)
return false;
return true;
}
public static bool operator !=(ConditionId left, ConditionId right)
{
return !(left == right);
}
}
public class ConditionSourceInfo public class ConditionSourceInfo
{ {
public ConditionSourceInfo(WorldObject target0, WorldObject target1 = null, WorldObject target2 = null) public ConditionSourceInfo(WorldObject target0, WorldObject target1 = null, WorldObject target2 = null)
+198 -300
View File
@@ -41,7 +41,7 @@ namespace Game
if (i.ReferenceId != 0) // handle reference if (i.ReferenceId != 0) // handle reference
{ {
var refe = conditionReferenceStorage.LookupByKey(i.ReferenceId); var refe = ConditionStorage[ConditionSourceType.ReferenceCondition].LookupByKey(new ConditionId(i.ReferenceId, 0, 0));
Cypher.Assert(refe.Empty(), "ConditionMgr.GetSearcherTypeMaskForConditionList - incorrect reference"); Cypher.Assert(refe.Empty(), "ConditionMgr.GetSearcherTypeMaskForConditionList - incorrect reference");
elseGroupSearcherTypeMasks[i.ElseGroup] &= GetSearcherTypeMaskForConditionList(refe); elseGroupSearcherTypeMasks[i.ElseGroup] &= GetSearcherTypeMaskForConditionList(refe);
} }
@@ -71,15 +71,13 @@ namespace Game
if (condition.IsLoaded()) if (condition.IsLoaded())
{ {
//! Find ElseGroup in ElseGroupStore //! Find ElseGroup in ElseGroupStore
//! If not found, add an entry in the store and set to true (placeholder) var added = elseGroupStore.TryAdd(condition.ElseGroup, true);
if (!elseGroupStore.ContainsKey(condition.ElseGroup)) if (!added) //! If another condition in this group was unmatched before this, don't bother checking (the group is false anyway)
elseGroupStore[condition.ElseGroup] = true;
else if (!elseGroupStore[condition.ElseGroup]) //! If another condition in this group was unmatched before this, don't bother checking (the group is false anyway)
continue; continue;
if (condition.ReferenceId != 0)//handle reference if (condition.ReferenceId != 0)//handle reference
{ {
var refe = conditionReferenceStorage.LookupByKey(condition.ReferenceId); var refe = ConditionStorage[ConditionSourceType.ReferenceCondition].LookupByKey(new ConditionId(condition.ReferenceId, 0, 0));
if (!refe.Empty()) if (!refe.Empty())
{ {
if (!IsObjectMeetToConditionList(sourceInfo, refe)) if (!IsObjectMeetToConditionList(sourceInfo, refe))
@@ -152,7 +150,8 @@ namespace Game
sourceType == ConditionSourceType.Graveyard || sourceType == ConditionSourceType.Graveyard ||
sourceType == ConditionSourceType.AreaTrigger || sourceType == ConditionSourceType.AreaTrigger ||
sourceType == ConditionSourceType.TrainerSpell || sourceType == ConditionSourceType.TrainerSpell ||
sourceType == ConditionSourceType.ObjectIdVisibility; sourceType == ConditionSourceType.ObjectIdVisibility ||
sourceType == ConditionSourceType.ReferenceCondition;
} }
public bool CanHaveSourceIdSet(ConditionSourceType sourceType) public bool CanHaveSourceIdSet(ConditionSourceType sourceType)
@@ -189,7 +188,7 @@ namespace Game
{ {
if (sourceType > ConditionSourceType.None && sourceType < ConditionSourceType.Max) if (sourceType > ConditionSourceType.None && sourceType < ConditionSourceType.Max)
{ {
var conditions = conditionStorage[sourceType].LookupByKey(entry); var conditions = ConditionStorage[sourceType].LookupByKey(new ConditionId(0, (int)entry, 0));
if (!conditions.Empty()) if (!conditions.Empty())
{ {
Log.outDebug(LogFilter.Condition, "GetConditionsForNotGroupedEntry: found conditions for type {0} and entry {1}", sourceType, entry); Log.outDebug(LogFilter.Condition, "GetConditionsForNotGroupedEntry: found conditions for type {0} and entry {1}", sourceType, entry);
@@ -215,88 +214,71 @@ namespace Game
public bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint entry) public bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint entry)
{ {
if (sourceType > ConditionSourceType.None && sourceType < ConditionSourceType.Max) if (sourceType > ConditionSourceType.None && sourceType < ConditionSourceType.Max)
if (conditionStorage[sourceType].ContainsKey(entry)) return ConditionStorage[sourceType].ContainsKey(new ConditionId(0, (int)entry, 0));
return true;
return false; return false;
} }
public bool IsObjectMeetingSpellClickConditions(uint creatureId, uint spellId, WorldObject clicker, WorldObject target) public bool IsObjectMeetingSpellClickConditions(uint creatureId, uint spellId, WorldObject clicker, WorldObject target)
{ {
var multiMap = spellClickEventConditionStorage.LookupByKey(creatureId); var conditions = ConditionStorage[ConditionSourceType.SpellClickEvent].LookupByKey(new ConditionId(creatureId, (int)spellId, 0));
if (multiMap != null) if (!conditions.Empty())
{ {
var conditions = multiMap.LookupByKey(spellId); Log.outDebug(LogFilter.Condition, "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {0} spell {1}", creatureId, spellId);
if (!conditions.Empty()) ConditionSourceInfo sourceInfo = new(clicker, target);
{ return IsObjectMeetToConditions(sourceInfo, conditions);
Log.outDebug(LogFilter.Condition, "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {0} spell {1}", creatureId, spellId);
ConditionSourceInfo sourceInfo = new(clicker, target);
return IsObjectMeetToConditions(sourceInfo, conditions);
}
} }
return true; return true;
} }
public List<Condition> GetConditionsForSpellClickEvent(uint creatureId, uint spellId) public bool HasConditionsForSpellClickEvent(uint creatureId, uint spellId)
{ {
var multiMap = spellClickEventConditionStorage.LookupByKey(creatureId); if (ConditionStorage[ConditionSourceType.SpellClickEvent].ContainsKey(new ConditionId(creatureId, (int)spellId, 0)))
if (multiMap != null)
{ {
var conditions = multiMap.LookupByKey(spellId); Log.outDebug(LogFilter.Condition, "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {0} spell {1}", creatureId, spellId);
if (!conditions.Empty()) return true;
{
Log.outDebug(LogFilter.Condition, "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {0} spell {1}", creatureId, spellId);
return conditions;
}
} }
return null;
return false;
} }
public bool IsObjectMeetingVehicleSpellConditions(uint creatureId, uint spellId, Player player, Unit vehicle) public bool IsObjectMeetingVehicleSpellConditions(uint creatureId, uint spellId, Player player, Unit vehicle)
{ {
var multiMap = vehicleSpellConditionStorage.LookupByKey(creatureId); var conditions = ConditionStorage[ConditionSourceType.VehicleSpell].LookupByKey(new ConditionId(creatureId, (int)spellId, 0));
if (multiMap != null) if (conditions != null)
{ {
var conditions = multiMap.LookupByKey(spellId); Log.outDebug(LogFilter.Condition, "GetConditionsForVehicleSpell: found conditions for Vehicle entry {0} spell {1}", creatureId, spellId);
if (!conditions.Empty()) ConditionSourceInfo sourceInfo = new(player, vehicle);
{ return IsObjectMeetToConditions(sourceInfo, conditions);
Log.outDebug(LogFilter.Condition, "GetConditionsForVehicleSpell: found conditions for Vehicle entry {0} spell {1}", creatureId, spellId);
ConditionSourceInfo sourceInfo = new(player, vehicle);
return IsObjectMeetToConditions(sourceInfo, conditions);
}
} }
return true; return true;
} }
public bool IsObjectMeetingSmartEventConditions(long entryOrGuid, uint eventId, SmartScriptType sourceType, Unit unit, WorldObject baseObject) public bool IsObjectMeetingSmartEventConditions(long entryOrGuid, uint eventId, SmartScriptType sourceType, Unit unit, WorldObject baseObject)
{ {
var multiMap = smartEventConditionStorage.LookupByKey(Tuple.Create((int)entryOrGuid, (uint)sourceType)); var conditions = ConditionStorage[ConditionSourceType.SmartEvent].LookupByKey(new ConditionId(eventId + 1, (int)entryOrGuid, (uint)sourceType));
if (multiMap != null) if (!conditions.Empty())
{ {
var conditions = multiMap.LookupByKey(eventId + 1); Log.outDebug(LogFilter.Condition, "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid {0} eventId {1}", entryOrGuid, eventId);
if (!conditions.Empty()) ConditionSourceInfo sourceInfo = new(unit, baseObject);
{ return IsObjectMeetToConditions(sourceInfo, conditions);
Log.outDebug(LogFilter.Condition, "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid {0} eventId {1}", entryOrGuid, eventId);
ConditionSourceInfo sourceInfo = new(unit, baseObject);
return IsObjectMeetToConditions(sourceInfo, conditions);
}
} }
return true; return true;
} }
public bool IsObjectMeetingVendorItemConditions(uint creatureId, uint itemId, Player player, Creature vendor) public bool IsObjectMeetingVendorItemConditions(uint creatureId, uint itemId, Player player, Creature vendor)
{ {
var multiMap = npcVendorConditionContainerStorage.LookupByKey(creatureId); var conditions = ConditionStorage[ConditionSourceType.NpcVendor].LookupByKey(new ConditionId(creatureId, (int)itemId, 0));
if (multiMap != null) if (!conditions.Empty())
{ {
var conditions = multiMap.LookupByKey(itemId); Log.outDebug(LogFilter.Condition, "GetConditionsForNpcVendor: found conditions for creature entry {0} item {1}", creatureId, itemId);
if (!conditions.Empty()) ConditionSourceInfo sourceInfo = new(player, vendor);
{ return IsObjectMeetToConditions(sourceInfo, conditions);
Log.outDebug(LogFilter.Condition, "GetConditionsForNpcVendor: found conditions for creature entry {0} item {1}", creatureId, itemId);
ConditionSourceInfo sourceInfo = new(player, vendor);
return IsObjectMeetToConditions(sourceInfo, conditions);
}
} }
return true; return true;
} }
@@ -307,28 +289,25 @@ namespace Game
public List<Condition> GetConditionsForAreaTrigger(uint areaTriggerId, bool isServerSide) public List<Condition> GetConditionsForAreaTrigger(uint areaTriggerId, bool isServerSide)
{ {
return areaTriggerConditionContainerStorage.LookupByKey(Tuple.Create(areaTriggerId, isServerSide)); return ConditionStorage[ConditionSourceType.AreaTrigger].LookupByKey(new ConditionId(areaTriggerId, isServerSide ? 1 : 0, 0));
} }
public bool IsObjectMeetingTrainerSpellConditions(uint trainerId, uint spellId, Player player) public bool IsObjectMeetingTrainerSpellConditions(uint trainerId, uint spellId, Player player)
{ {
var multiMap = trainerSpellConditionContainerStorage.LookupByKey(trainerId); var conditions = ConditionStorage[ConditionSourceType.NpcVendor].LookupByKey(new ConditionId(trainerId, (int)spellId, 0));
if (multiMap != null) if (!conditions.Empty())
{ {
var conditionList = multiMap.LookupByKey(spellId); Log.outDebug(LogFilter.Condition, $"GetConditionsForTrainerSpell: found conditions for trainer id {trainerId} spell {spellId}");
if (!conditionList.Empty()) return IsObjectMeetToConditions(player, conditions);
{
Log.outDebug(LogFilter.Condition, $"GetConditionsForTrainerSpell: found conditions for trainer id {trainerId} spell {spellId}");
return IsObjectMeetToConditions(player, conditionList);
}
} }
return true; return true;
} }
public bool IsObjectMeetingVisibilityByObjectIdConditions(uint objectType, uint entry, WorldObject seer) public bool IsObjectMeetingVisibilityByObjectIdConditions(uint objectType, uint entry, WorldObject seer)
{ {
var conditions = objectVisibilityConditionStorage.LookupByKey((objectType, entry)); var conditions = ConditionStorage[ConditionSourceType.ObjectIdVisibility].LookupByKey(new ConditionId(objectType, (int)entry, 0));
if (conditions != null) if (!conditions.Empty())
{ {
Log.outDebug(LogFilter.Condition, $"IsObjectMeetingVisibilityByObjectIdConditions: found conditions for objectType {objectType} entry {entry}"); Log.outDebug(LogFilter.Condition, $"IsObjectMeetingVisibilityByObjectIdConditions: found conditions for objectType {objectType} entry {entry}");
return IsObjectMeetToConditions(seer, conditions); return IsObjectMeetToConditions(seer, conditions);
@@ -345,25 +324,6 @@ namespace Game
//must clear all custom handled cases (groupped types) before reload //must clear all custom handled cases (groupped types) before reload
if (isReload) if (isReload)
{ {
Log.outInfo(LogFilter.Server, "Reseting Loot Conditions...");
LootStorage.Creature.ResetConditions();
LootStorage.Fishing.ResetConditions();
LootStorage.Gameobject.ResetConditions();
LootStorage.Items.ResetConditions();
LootStorage.Mail.ResetConditions();
LootStorage.Milling.ResetConditions();
LootStorage.Pickpocketing.ResetConditions();
LootStorage.Reference.ResetConditions();
LootStorage.Skinning.ResetConditions();
LootStorage.Disenchant.ResetConditions();
LootStorage.Prospecting.ResetConditions();
LootStorage.Spell.ResetConditions();
Log.outInfo(LogFilter.Server, "Re-Loading `gossip_menu` Table for Conditions!");
Global.ObjectMgr.LoadGossipMenu();
Log.outInfo(LogFilter.Server, "Re-Loading `gossip_menu_option` Table for Conditions!");
Global.ObjectMgr.LoadGossipMenuItems();
Global.SpellMgr.UnloadSpellInfoImplicitTargetConditionLists(); Global.SpellMgr.UnloadSpellInfoImplicitTargetConditionLists();
Global.ObjectMgr.UnloadPhaseConditions(); Global.ObjectMgr.UnloadPhaseConditions();
@@ -379,6 +339,7 @@ namespace Game
} }
uint count = 0; uint count = 0;
do do
{ {
Condition cond = new(); Condition cond = new();
@@ -410,6 +371,7 @@ namespace Game
Log.outError(LogFilter.Sql, "Condition reference {1} is referencing self, skipped", iSourceTypeOrReferenceId); Log.outError(LogFilter.Sql, "Condition reference {1} is referencing self, skipped", iSourceTypeOrReferenceId);
continue; continue;
} }
cond.ReferenceId = (uint)Math.Abs(iConditionTypeOrReference); cond.ReferenceId = (uint)Math.Abs(iConditionTypeOrReference);
string rowType = "reference template"; string rowType = "reference template";
@@ -426,8 +388,6 @@ namespace Game
Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in value3 ({2})!", rowType, iSourceTypeOrReferenceId, cond.ConditionValue3); Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in value3 ({2})!", rowType, iSourceTypeOrReferenceId, cond.ConditionValue3);
if (cond.NegativeCondition) if (cond.NegativeCondition)
Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in NegativeCondition ({2})!", rowType, iSourceTypeOrReferenceId, cond.NegativeCondition); Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in NegativeCondition ({2})!", rowType, iSourceTypeOrReferenceId, cond.NegativeCondition);
if (cond.SourceGroup != 0 && iSourceTypeOrReferenceId < 0)
Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in SourceGroup ({2})!", rowType, iSourceTypeOrReferenceId, cond.SourceGroup);
if (cond.SourceEntry != 0 && iSourceTypeOrReferenceId < 0) if (cond.SourceEntry != 0 && iSourceTypeOrReferenceId < 0)
Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in SourceEntry ({2})!", rowType, iSourceTypeOrReferenceId, cond.SourceEntry); Log.outError(LogFilter.Sql, "Condition {0} {1} has useless data in SourceEntry ({2})!", rowType, iSourceTypeOrReferenceId, cond.SourceEntry);
} }
@@ -436,13 +396,17 @@ namespace Game
if (iSourceTypeOrReferenceId < 0)//it is a reference template if (iSourceTypeOrReferenceId < 0)//it is a reference template
{ {
conditionReferenceStorage.Add((uint)Math.Abs(iSourceTypeOrReferenceId), cond);//add to reference storage if (cond.SourceGroup != 0)
count++; Log.outError(LogFilter.Sql, $"Condition reference template {iSourceTypeOrReferenceId} has useless data in SourceGroup ({cond.SourceGroup})!");
continue; if (cond.SourceEntry != 0)
}//end of reference templates Log.outError(LogFilter.Sql, $"Condition reference template {iSourceTypeOrReferenceId} has useless data in SourceEntry ({cond.SourceEntry})!");
if (cond.SourceId != 0)
Log.outError(LogFilter.Sql, $"Condition reference template {iSourceTypeOrReferenceId} has useless data in SourceId ({cond.SourceId})!");
//if not a reference and SourceType is invalid, skip cond.SourceType = ConditionSourceType.ReferenceCondition;
if (iConditionTypeOrReference >= 0 && !IsSourceTypeValid(cond)) cond.SourceGroup = (uint)-iSourceTypeOrReferenceId;
}
else if (!IsSourceTypeValid(cond)) //if not a reference and SourceType is invalid, skip
continue; continue;
//Grouping is only allowed for some types (loot templates, gossip menus, gossip items) //Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
@@ -469,197 +433,127 @@ namespace Game
cond.ErrorTextId = 0; cond.ErrorTextId = 0;
} }
if (cond.SourceGroup != 0) var key = new ConditionId(cond.SourceGroup, cond.SourceEntry, cond.SourceId);
{ if (!ConditionStorage[cond.SourceType].ContainsKey(key))
bool valid = false; ConditionStorage[cond.SourceType][key] = new List<Condition>();
// handle grouped conditions
switch (cond.SourceType)
{
case ConditionSourceType.CreatureLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Creature.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.DisenchantLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Disenchant.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.FishingLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Fishing.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.GameobjectLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Gameobject.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.ItemLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Items.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.MailLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Mail.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.MillingLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Milling.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.PickpocketingLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Pickpocketing.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.ProspectingLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Prospecting.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.ReferenceLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Reference.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.SkinningLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Skinning.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.SpellLootTemplate:
valid = AddToLootTemplate(cond, LootStorage.Spell.GetLootForConditionFill(cond.SourceGroup));
break;
case ConditionSourceType.GossipMenu:
valid = AddToGossipMenus(cond);
break;
case ConditionSourceType.GossipMenuOption:
valid = AddToGossipMenuItems(cond);
break;
case ConditionSourceType.SpellClickEvent:
{
if (!spellClickEventConditionStorage.ContainsKey(cond.SourceGroup))
spellClickEventConditionStorage[cond.SourceGroup] = new MultiMap<uint, Condition>();
spellClickEventConditionStorage[cond.SourceGroup].Add((uint)cond.SourceEntry, cond); ConditionStorage[cond.SourceType][key].Add(cond);
if (cond.ConditionType == ConditionTypes.Aura)
spellsUsedInSpellClickConditions.Add(cond.ConditionValue1);
++count;
continue; // do not add to m_AllocatedMemory to avoid double deleting
}
case ConditionSourceType.SpellImplicitTarget:
valid = AddToSpellImplicitTargetConditions(cond);
break;
case ConditionSourceType.VehicleSpell:
{
if (!vehicleSpellConditionStorage.ContainsKey(cond.SourceGroup))
vehicleSpellConditionStorage[cond.SourceGroup] = new MultiMap<uint, Condition>();
vehicleSpellConditionStorage[cond.SourceGroup].Add((uint)cond.SourceEntry, cond);
++count;
continue; // do not add to m_AllocatedMemory to avoid double deleting
}
case ConditionSourceType.SmartEvent:
{
//! TODO: PAIR_32 ?
var key = Tuple.Create(cond.SourceEntry, cond.SourceId);
if (!smartEventConditionStorage.ContainsKey(key))
smartEventConditionStorage[key] = new MultiMap<uint, Condition>();
smartEventConditionStorage[key].Add(cond.SourceGroup, cond);
++count;
continue;
}
case ConditionSourceType.NpcVendor:
{
if (!npcVendorConditionContainerStorage.ContainsKey(cond.SourceGroup))
npcVendorConditionContainerStorage[cond.SourceGroup] = new MultiMap<uint, Condition>();
npcVendorConditionContainerStorage[cond.SourceGroup].Add((uint)cond.SourceEntry, cond);
++count;
continue;
}
case ConditionSourceType.Phase:
valid = AddToPhases(cond);
break;
case ConditionSourceType.Graveyard:
valid = AddToGraveyardData(cond);
break;
case ConditionSourceType.AreaTrigger:
areaTriggerConditionContainerStorage.Add(Tuple.Create(cond.SourceGroup, cond.SourceEntry != 0), cond);
++count;
continue;
case ConditionSourceType.TrainerSpell:
{
if (!trainerSpellConditionContainerStorage.ContainsKey(cond.SourceGroup))
trainerSpellConditionContainerStorage[cond.SourceGroup] = new MultiMap<uint, Condition>();
trainerSpellConditionContainerStorage[cond.SourceGroup].Add((uint)cond.SourceEntry, cond);
++count;
continue;
}
case ConditionSourceType.ObjectIdVisibility:
{
objectVisibilityConditionStorage.Add((cond.SourceGroup, (uint)cond.SourceEntry), cond);
valid = true;
++count;
continue;
}
default:
break;
}
if (!valid)
Log.outError(LogFilter.Sql, "{0} Not handled grouped condition.", cond.ToString());
else
++count;
continue;
}
//add new Condition to storage based on Type/Entry
if (cond.SourceType == ConditionSourceType.SpellClickEvent && cond.ConditionType == ConditionTypes.Aura)
spellsUsedInSpellClickConditions.Add(cond.ConditionValue1);
conditionStorage[cond.SourceType].Add((uint)cond.SourceEntry, cond);
++count; ++count;
} }
while (result.NextRow()); while (result.NextRow());
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.CreatureLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Creature.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.DisenchantLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Disenchant.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.FishingLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Fishing.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.GameobjectLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Gameobject.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.ItemLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Items.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.MailLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Mail.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.MillingLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Milling.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.PickpocketingLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Pickpocketing.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.ProspectingLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Prospecting.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.ReferenceLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Reference.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.SkinningLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Skinning.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.SpellLootTemplate])
AddToLootTemplate(id, conditions, LootStorage.Spell.GetLootForConditionFill(id.SourceGroup));
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.GossipMenu])
AddToGossipMenus(id, conditions);
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.GossipMenuOption])
AddToGossipMenuItems(id, conditions);
spellsUsedInSpellClickConditions.Clear();
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.SpellClickEvent])
foreach (Condition condition in conditions)
if (condition.ConditionType == ConditionTypes.Aura)
spellsUsedInSpellClickConditions.Add(condition.ConditionValue1);
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.SpellImplicitTarget])
foreach (Condition condition in conditions)
AddToSpellImplicitTargetConditions(condition);
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.Phase])
AddToPhases(id, conditions);
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.Graveyard])
AddToGraveyardData(id, conditions);
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} conditions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} conditions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
} }
bool AddToLootTemplate(Condition cond, LootTemplate loot) void AddToLootTemplate(ConditionId id, List<Condition> conditions, LootTemplate loot)
{ {
if (loot == null) if (loot == null)
{ {
Log.outError(LogFilter.Sql, "{0} LootTemplate {1} not found.", cond.ToString(), cond.SourceGroup); foreach (Condition condition in conditions)
return false; Log.outError(LogFilter.Sql, $"{condition} LootTemplate {condition.SourceGroup} not found.");
return;
} }
if (loot.AddConditionItem(cond)) if (loot.LinkConditions(id, new ConditionsReference(conditions)))
return true; return;
Log.outError(LogFilter.Sql, "{0} Item {1} not found in LootTemplate {2}.", cond.ToString(), cond.SourceEntry, cond.SourceGroup); foreach (Condition condition in conditions)
return false; Log.outError(LogFilter.Sql, $"{condition} Item {condition.SourceEntry} not found in LootTemplate {condition.SourceGroup}.");
} }
bool AddToGossipMenus(Condition cond) void AddToGossipMenus(ConditionId id, List<Condition> conditions)
{ {
var pMenuBounds = Global.ObjectMgr.GetGossipMenusMapBounds(cond.SourceGroup); var pMenuBounds = Global.ObjectMgr.GetGossipMenusMapBounds(id.SourceGroup);
if (!pMenuBounds.Empty()) if (!pMenuBounds.Empty())
{ {
foreach (var menu in pMenuBounds) foreach (var menu in pMenuBounds)
{ {
if (menu.MenuId == cond.SourceGroup && (menu.TextId == cond.SourceEntry || cond.SourceEntry == 0)) if (menu.MenuId == id.SourceGroup && (menu.TextId == id.SourceEntry || id.SourceEntry == 0))
menu.Conditions.Add(cond); menu.Conditions = new(conditions);
} }
return true; return;
} }
Log.outError(LogFilter.Sql, $"{cond} GossipMenu {cond.SourceGroup} not found."); foreach (Condition condition in conditions)
return false; Log.outError(LogFilter.Sql, $"{condition} GossipMenu {condition.SourceGroup} not found.");
} }
bool AddToGossipMenuItems(Condition cond) void AddToGossipMenuItems(ConditionId id, List<Condition> conditions)
{ {
var pMenuItemBounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(cond.SourceGroup); var pMenuItemBounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(id.SourceGroup);
foreach (var gossipMenuItem in pMenuItemBounds) foreach (var gossipMenuItem in pMenuItemBounds)
{ {
if (gossipMenuItem.MenuID == cond.SourceGroup && gossipMenuItem.OrderIndex == cond.SourceEntry) if (gossipMenuItem.MenuID == id.SourceGroup && gossipMenuItem.OrderIndex == id.SourceEntry)
{ {
gossipMenuItem.Conditions.Add(cond); gossipMenuItem.Conditions = new(conditions);
return true; return;
} }
} }
Log.outError(LogFilter.Sql, "{0} GossipMenuId {1} Item {2} not found.", cond.ToString(), cond.SourceGroup, cond.SourceEntry); foreach (Condition condition in conditions)
return false; Log.outError(LogFilter.Sql, $"{condition} GossipMenuId {condition.SourceGroup} Item {condition.SourceEntry} not found.");
} }
bool AddToSpellImplicitTargetConditions(Condition cond) void AddToSpellImplicitTargetConditions(Condition cond)
{ {
Global.SpellMgr.ForEachSpellInfoDifficulty((uint)cond.SourceEntry, spellInfo => Global.SpellMgr.ForEachSpellInfoDifficulty((uint)cond.SourceEntry, spellInfo =>
{ {
@@ -705,9 +599,8 @@ namespace Game
// build new shared mask with found effect // build new shared mask with found effect
uint sharedMask = (uint)(1 << (int)spellEffectInfo.EffectIndex); uint sharedMask = (uint)(1 << (int)spellEffectInfo.EffectIndex);
List<Condition> cmp = spellEffectInfo.ImplicitTargetConditions;
for (uint effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo.GetEffects().Count; ++effIndex) for (uint effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo.GetEffects().Count; ++effIndex)
if (spellInfo.GetEffect(effIndex).ImplicitTargetConditions == cmp) if (spellInfo.GetEffect(effIndex).ImplicitTargetConditions == spellEffectInfo.ImplicitTargetConditions)
sharedMask |= (uint)(1 << (int)effIndex); sharedMask |= (uint)(1 << (int)effIndex);
sharedMasks.Add(sharedMask); sharedMasks.Add(sharedMask);
@@ -764,14 +657,13 @@ namespace Game
} }
} }
}); });
return true;
} }
bool AddToPhases(Condition cond) void AddToPhases(ConditionId id, List<Condition> conditions)
{ {
if (cond.SourceEntry == 0) if (id.SourceEntry == 0)
{ {
PhaseInfoStruct phaseInfo = Global.ObjectMgr.GetPhaseInfo(cond.SourceGroup); PhaseInfoStruct phaseInfo = Global.ObjectMgr.GetPhaseInfo(id.SourceGroup);
if (phaseInfo != null) if (phaseInfo != null)
{ {
bool found = false; bool found = false;
@@ -782,9 +674,9 @@ namespace Game
{ {
foreach (PhaseAreaInfo phase in phases) foreach (PhaseAreaInfo phase in phases)
{ {
if (phase.PhaseInfo.Id == cond.SourceGroup) if (phase.PhaseInfo.Id == id.SourceGroup)
{ {
phase.Conditions.Add(cond); phase.Conditions.AddRange(conditions);
found = true; found = true;
} }
} }
@@ -792,37 +684,37 @@ namespace Game
} }
if (found) if (found)
return true; return;
} }
} }
else else
{ {
var phases = Global.ObjectMgr.GetPhasesForArea((uint)cond.SourceEntry); var phases = Global.ObjectMgr.GetPhasesForArea((uint)id.SourceEntry);
foreach (PhaseAreaInfo phase in phases) foreach (PhaseAreaInfo phase in phases)
{ {
if (phase.PhaseInfo.Id == cond.SourceGroup) if (phase.PhaseInfo.Id == id.SourceGroup)
{ {
phase.Conditions.Add(cond); phase.Conditions.AddRange(conditions);
return true; return;
} }
} }
} }
Log.outError(LogFilter.Sql, $"{cond} Area {cond.SourceEntry} does not have phase {cond.SourceGroup}."); foreach (Condition condition in conditions)
return false; Log.outError(LogFilter.Sql, $"{condition} Area {condition.SourceEntry} does not have phase {condition.SourceGroup}.");
} }
bool AddToGraveyardData(Condition cond) void AddToGraveyardData(ConditionId id, List<Condition> conditions)
{ {
GraveyardData graveyard = Global.ObjectMgr.FindGraveyardData((uint)cond.SourceEntry, cond.SourceGroup); GraveyardData graveyard = Global.ObjectMgr.FindGraveyardData((uint)id.SourceEntry, id.SourceGroup);
if (graveyard != null) if (graveyard != null)
{ {
graveyard.Conditions.Add(cond); graveyard.Conditions = new(conditions);
return true; return;
} }
Log.outError(LogFilter.Sql, $"{cond}, Graveyard {cond.SourceEntry} does not have ghostzone {cond.SourceGroup}."); foreach (Condition condition in conditions)
return false; Log.outError(LogFilter.Sql, $"{condition}, Graveyard {condition.SourceEntry} does not have ghostzone {condition.SourceGroup}.");
} }
bool IsSourceTypeValid(Condition cond) bool IsSourceTypeValid(Condition cond)
@@ -1206,7 +1098,7 @@ namespace Game
Log.outError(LogFilter.Sql, $"{cond.ToString()} in `condition` table, unexpected SourceEntry value (expected 0 or 1), ignoring."); Log.outError(LogFilter.Sql, $"{cond.ToString()} in `condition` table, unexpected SourceEntry value (expected 0 or 1), ignoring.");
return false; return false;
} }
if (Global.AreaTriggerDataStorage.GetAreaTriggerTemplate(new AreaTriggerId(cond.SourceGroup, cond.SourceEntry != 0)) == null) if (Global.AreaTriggerDataStorage.GetAreaTriggerTemplate(new AreaTriggerId(cond.SourceGroup, cond.SourceEntry == 1)) == null)
{ {
Log.outError(LogFilter.Sql, $"{cond.ToString()} in `condition` table, does not exist in `areatrigger_template`, ignoring."); Log.outError(LogFilter.Sql, $"{cond.ToString()} in `condition` table, does not exist in `areatrigger_template`, ignoring.");
return false; return false;
@@ -1883,26 +1775,10 @@ namespace Game
void Clean() void Clean()
{ {
conditionReferenceStorage.Clear(); foreach (var (_, conditionsMap) in ConditionStorage)
conditionsMap.Clear();
conditionStorage.Clear();
for (ConditionSourceType i = 0; i < ConditionSourceType.Max; ++i)
conditionStorage[i] = new MultiMap<uint, Condition>();//add new empty list for SourceType
vehicleSpellConditionStorage.Clear();
smartEventConditionStorage.Clear();
spellClickEventConditionStorage.Clear();
spellsUsedInSpellClickConditions.Clear(); spellsUsedInSpellClickConditions.Clear();
npcVendorConditionContainerStorage.Clear();
areaTriggerConditionContainerStorage.Clear();
trainerSpellConditionContainerStorage.Clear();
objectVisibilityConditionStorage.Clear();
} }
static bool PlayerConditionCompare(int comparisonType, int value1, int value2) static bool PlayerConditionCompare(int comparisonType, int value1, int value2)
@@ -2619,7 +2495,7 @@ namespace Game
case UnitConditionVariable.InCombat: case UnitConditionVariable.InCombat:
return unit.IsInCombat() ? 1 : 0; return unit.IsInCombat() ? 1 : 0;
case UnitConditionVariable.IsMoving: case UnitConditionVariable.IsMoving:
return unit.HasUnitMovementFlag(MovementFlag.Forward | MovementFlag.Backward | MovementFlag.StrafeLeft | MovementFlag.StrafeRight) ? 1:0; return unit.HasUnitMovementFlag(MovementFlag.Forward | MovementFlag.Backward | MovementFlag.StrafeLeft | MovementFlag.StrafeRight) ? 1 : 0;
case UnitConditionVariable.IsCasting: case UnitConditionVariable.IsCasting:
case UnitConditionVariable.IsCastingSpell: // this is supposed to return spell id by client code but data always has 0 or 1 case UnitConditionVariable.IsCastingSpell: // this is supposed to return spell id by client code but data always has 0 or 1
return unit.GetCurrentSpell(CurrentSpellTypes.Generic) != null ? 1 : 0; return unit.GetCurrentSpell(CurrentSpellTypes.Generic) != null ? 1 : 0;
@@ -2635,7 +2511,7 @@ namespace Game
return unit.GetExactDistSq(attacker) < distance * distance; return unit.GetExactDistSq(attacker) < distance * distance;
}); });
case UnitConditionVariable.IsAttackingMe: case UnitConditionVariable.IsAttackingMe:
return (otherUnit != null && unit.GetTarget() == otherUnit.GetGUID()) ? 1:0; return (otherUnit != null && unit.GetTarget() == otherUnit.GetGUID()) ? 1 : 0;
case UnitConditionVariable.Range: case UnitConditionVariable.Range:
return otherUnit != null ? (int)unit.GetExactDist(otherUnit) : 0; return otherUnit != null ? (int)unit.GetExactDist(otherUnit) : 0;
case UnitConditionVariable.InMeleeRange: case UnitConditionVariable.InMeleeRange:
@@ -3024,16 +2900,8 @@ namespace Game
return false; return false;
} }
Dictionary<ConditionSourceType, MultiMap<uint, Condition>> conditionStorage = new(); Dictionary<ConditionSourceType, Dictionary<ConditionId, List<Condition>>> ConditionStorage = new();
MultiMap<uint, Condition> conditionReferenceStorage = new();
Dictionary<uint, MultiMap<uint, Condition>> vehicleSpellConditionStorage = new();
Dictionary<uint, MultiMap<uint, Condition>> spellClickEventConditionStorage = new();
List<uint> spellsUsedInSpellClickConditions = new(); List<uint> spellsUsedInSpellClickConditions = new();
Dictionary<uint, MultiMap<uint, Condition>> npcVendorConditionContainerStorage = new();
Dictionary<Tuple<int, uint>, MultiMap<uint, Condition>> smartEventConditionStorage = new();
MultiMap<Tuple<uint, bool>, Condition> areaTriggerConditionContainerStorage = new();
Dictionary<uint, MultiMap<uint, Condition>> trainerSpellConditionContainerStorage = new();
MultiMap<(uint objectType, uint objectId), Condition> objectVisibilityConditionStorage = new();
public string[] StaticSourceTypeData = public string[] StaticSourceTypeData =
{ {
@@ -3150,4 +3018,34 @@ namespace Game
public bool HasConditionValue3; public bool HasConditionValue3;
} }
} }
public struct ConditionsReference
{
public List<Condition> Conditions = new();
public ConditionsReference(List<Condition> conditions)
{
Conditions = conditions;
}
public bool Meets(WorldObject obj)
{
return Global.ConditionMgr.IsObjectMeetToConditions(obj, Conditions);
}
public bool Meets(WorldObject obj1, WorldObject obj2)
{
return Global.ConditionMgr.IsObjectMeetToConditions(obj1, obj2, Conditions);
}
public bool Meets(ConditionSourceInfo sourceInfo)
{
return Global.ConditionMgr.IsObjectMeetToConditions(sourceInfo, Conditions);
}
public bool IsEmpty()
{
return Conditions.Empty();
}
}
} }
+2 -2
View File
@@ -789,7 +789,7 @@ namespace Game.Misc
public uint BoxBroadcastTextId; public uint BoxBroadcastTextId;
public int? SpellID; public int? SpellID;
public int? OverrideIconID; public int? OverrideIconID;
public List<Condition> Conditions = new(); public ConditionsReference Conditions;
} }
public class GossipMenuAddon public class GossipMenuAddon
@@ -817,6 +817,6 @@ namespace Game.Misc
{ {
public uint MenuId; public uint MenuId;
public uint TextId; public uint TextId;
public List<Condition> Conditions = new(); public ConditionsReference Conditions;
} }
} }
+1 -2
View File
@@ -3301,8 +3301,7 @@ namespace Game.Entities
var clickBounds = Global.ObjectMgr.GetSpellClickInfoMapBounds(obj.GetEntry()); var clickBounds = Global.ObjectMgr.GetSpellClickInfoMapBounds(obj.GetEntry());
foreach (var spellClickInfo in clickBounds) foreach (var spellClickInfo in clickBounds)
{ {
List<Condition> conds = Global.ConditionMgr.GetConditionsForSpellClickEvent(obj.GetEntry(), spellClickInfo.spellId); if (Global.ConditionMgr.HasConditionsForSpellClickEvent(obj.GetEntry(), spellClickInfo.spellId))
if (conds != null)
{ {
ObjectFieldData objMask = new(); ObjectFieldData objMask = new();
UnitData unitMask = new(); UnitData unitMask = new();
+4 -4
View File
@@ -2564,7 +2564,7 @@ namespace Game.Entities
foreach (var gossipMenuItem in menuItemBounds) foreach (var gossipMenuItem in menuItemBounds)
{ {
if (!ConditionMgr.IsObjectMeetToConditions(this, source, gossipMenuItem.Conditions)) if (!gossipMenuItem.Conditions.Meets(this, source))
continue; continue;
bool canTalk = true; bool canTalk = true;
@@ -2889,7 +2889,7 @@ namespace Game.Entities
if (menu.TextId == 0) if (menu.TextId == 0)
continue; continue;
if (ConditionMgr.IsObjectMeetToConditions(this, source, menu.Conditions)) if (menu.Conditions.Meets(this, source))
textId = menu.TextId; textId = menu.TextId;
} }
@@ -2913,9 +2913,9 @@ namespace Game.Entities
{ {
var menuBounds = ObjectMgr.GetGossipMenusMapBounds(menuId); var menuBounds = ObjectMgr.GetGossipMenusMapBounds(menuId);
foreach (var itr in menuBounds) foreach (var menu in menuBounds)
{ {
if (!ConditionMgr.IsObjectMeetToConditions(this, source, itr.Conditions)) if (!menu.Conditions.Meets(this, source))
continue; continue;
menuIdToShow = menuId; menuIdToShow = menuId;
+3 -3
View File
@@ -901,7 +901,7 @@ namespace Game
if (conditionObject != null) if (conditionObject != null)
{ {
if (!Global.ConditionMgr.IsObjectMeetToConditions(conditionSource, data.Conditions)) if (!data.Conditions.Meets(conditionSource))
continue; continue;
if (entry.Loc.GetMapId() == mapEntry.ParentMapID && !conditionObject.GetPhaseShift().HasVisibleMapId(entry.Loc.GetMapId())) if (entry.Loc.GetMapId() == mapEntry.ParentMapID && !conditionObject.GetPhaseShift().HasVisibleMapId(entry.Loc.GetMapId()))
@@ -910,7 +910,7 @@ namespace Game
else if (team != 0) else if (team != 0)
{ {
bool teamConditionMet = true; bool teamConditionMet = true;
foreach (Condition cond in data.Conditions) foreach (Condition cond in data.Conditions.Conditions)
{ {
if (cond.ConditionType != ConditionTypes.Team) if (cond.ConditionType != ConditionTypes.Team)
continue; continue;
@@ -11309,7 +11309,7 @@ namespace Game
public class GraveyardData public class GraveyardData
{ {
public uint SafeLocId; public uint SafeLocId;
public List<Condition> Conditions = new(); public ConditionsReference Conditions;
} }
public class QuestPOIBlobData public class QuestPOIBlobData
+1 -1
View File
@@ -2436,7 +2436,7 @@ namespace Game
{ {
var gYard = range[(int)i]; var gYard = range[(int)i];
ConditionSourceInfo conditionSource = new(_player); ConditionSourceInfo conditionSource = new(_player);
if (!Global.ConditionMgr.IsObjectMeetToConditions(conditionSource, gYard.Conditions)) if (!gYard.Conditions.Meets(conditionSource))
continue; continue;
graveyardIds.Add(i); graveyardIds.Add(i);
+4 -4
View File
@@ -42,10 +42,10 @@ namespace Game.Loots
return AllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules, false, conditions); return AllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules, false, conditions);
} }
public static bool AllowedForPlayer(Player player, Loot loot, uint itemid, bool needs_quest, bool follow_loot_rules, bool strictUsabilityCheck, List<Condition> conditions) public static bool AllowedForPlayer(Player player, Loot loot, uint itemid, bool needs_quest, bool follow_loot_rules, bool strictUsabilityCheck, ConditionsReference conditions)
{ {
// DB conditions check // DB conditions check
if (!Global.ConditionMgr.IsObjectMeetToConditions(player, conditions)) if (!conditions.Meets(player))
return false; return false;
ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(itemid); ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(itemid);
@@ -180,7 +180,7 @@ namespace Game.Loots
public uint randomBonusListId; public uint randomBonusListId;
public List<uint> BonusListIDs = new(); public List<uint> BonusListIDs = new();
public ItemContext context; public ItemContext context;
public List<Condition> conditions = new(); // additional loot condition public ConditionsReference conditions; // additional loot condition
public List<ObjectGuid> allowedGUIDs = new(); public List<ObjectGuid> allowedGUIDs = new();
public ObjectGuid rollWinnerGUID; // Stores the guid of person who won loot, if his bags are full only he can see the item in loot list! public ObjectGuid rollWinnerGUID; // Stores the guid of person who won loot, if his bags are full only he can see the item in loot list!
public byte count; public byte count;
@@ -999,7 +999,7 @@ namespace Game.Loots
return true; return true;
foreach (LootItem item in items) foreach (LootItem item in items)
if (!item.is_looted && item.follow_loot_rules && !item.freeforall && item.conditions.Empty()) if (!item.is_looted && item.follow_loot_rules && !item.freeforall && item.conditions.IsEmpty())
return true; return true;
return false; return false;
+17 -45
View File
@@ -490,7 +490,7 @@ namespace Game.Loots
public byte groupid; public byte groupid;
public byte mincount; // mincount for drop items public byte mincount; // mincount for drop items
public byte maxcount; // max drop count for the item mincount or Ref multiplicator public byte maxcount; // max drop count for the item mincount or Ref multiplicator
public List<Condition> conditions; // additional loot condition public ConditionsReference conditions; // additional loot condition
public LootStoreItem(uint _itemid, uint _reference, float _chance, bool _needs_quest, ushort _lootmode, byte _groupid, byte _mincount, byte _maxcount) public LootStoreItem(uint _itemid, uint _reference, float _chance, bool _needs_quest, ushort _lootmode, byte _groupid, byte _mincount, byte _maxcount)
{ {
@@ -502,7 +502,6 @@ namespace Game.Loots
groupid = _groupid; groupid = _groupid;
mincount = _mincount; mincount = _mincount;
maxcount = _maxcount; maxcount = _maxcount;
conditions = new List<Condition>();
} }
public bool Roll(bool rate) public bool Roll(bool rate)
@@ -614,11 +613,11 @@ namespace Game.Loots
{ {
// all still listed ids isn't referenced // all still listed ids isn't referenced
foreach (var id in lootIdSet) foreach (var id in lootIdSet)
Log.outError( LogFilter.Sql, "Table '{0}' entry {1} isn't {2} and not referenced from loot, and then useless.", GetName(), id, GetEntryName()); Log.outError(LogFilter.Sql, "Table '{0}' entry {1} isn't {2} and not referenced from loot, and then useless.", GetName(), id, GetEntryName());
} }
public void ReportNonExistingId(uint lootId, uint ownerId) public void ReportNonExistingId(uint lootId, uint ownerId)
{ {
Log.outError( LogFilter.Sql, "Table '{0}' Entry {1} does not exist but it is used by {2} {3}", GetName(), lootId, GetEntryName(), ownerId); Log.outError(LogFilter.Sql, "Table '{0}' Entry {1} does not exist but it is used by {2} {3}", GetName(), lootId, GetEntryName(), ownerId);
} }
public bool HaveLootFor(uint loot_id) { return m_LootTemplates.LookupByKey(loot_id) != null; } public bool HaveLootFor(uint loot_id) { return m_LootTemplates.LookupByKey(loot_id) != null; }
@@ -650,14 +649,7 @@ namespace Game.Loots
return tab; return tab;
} }
public void ResetConditions()
{
foreach (var pair in m_LootTemplates)
{
List<Condition> empty = new();
pair.Value.CopyConditions(empty);
}
}
public LootTemplate GetLootForConditionFill(uint loot_id) public LootTemplate GetLootForConditionFill(uint loot_id)
{ {
var tab = m_LootTemplates.LookupByKey(loot_id); var tab = m_LootTemplates.LookupByKey(loot_id);
@@ -928,14 +920,6 @@ namespace Game.Loots
return false; return false;
} }
public void CopyConditions(List<Condition> conditions)
{
foreach (var i in Entries)
i.conditions.Clear();
foreach (var group in Groups.Values)
group.CopyConditions(conditions);
}
public void CopyConditions(LootItem li) public void CopyConditions(LootItem li)
{ {
// Copies the conditions list from a template item to a LootItem // Copies the conditions list from a template item to a LootItem
@@ -1044,21 +1028,16 @@ namespace Game.Loots
foreach (var group in Groups.Values) foreach (var group in Groups.Values)
group.CheckLootRefs(store, ref_set); group.CheckLootRefs(store, ref_set);
} }
public bool AddConditionItem(Condition cond)
{
if (cond == null || !cond.IsLoaded())//should never happen, checked at loading
{
Log.outError(LogFilter.Loot, "LootTemplate.addConditionItem: condition is null");
return false;
}
public bool LinkConditions(ConditionId id, ConditionsReference reference)
{
if (!Entries.Empty()) if (!Entries.Empty())
{ {
foreach (var i in Entries) foreach (var item in Entries)
{ {
if (i.itemid == cond.SourceEntry) if (item.itemid == id.SourceEntry)
{ {
i.conditions.Add(cond); item.conditions = reference;
return true; return true;
} }
} }
@@ -1066,7 +1045,7 @@ namespace Game.Loots
if (!Groups.Empty()) if (!Groups.Empty())
{ {
foreach (var group in Groups.Values) foreach (var (_, group) in Groups)
{ {
if (group == null) if (group == null)
continue; continue;
@@ -1074,11 +1053,11 @@ namespace Game.Loots
LootStoreItemList itemList = group.GetExplicitlyChancedItemList(); LootStoreItemList itemList = group.GetExplicitlyChancedItemList();
if (!itemList.Empty()) if (!itemList.Empty())
{ {
foreach (var i in itemList) foreach (var item in itemList)
{ {
if (i.itemid == cond.SourceEntry) if (item.itemid == id.SourceEntry)
{ {
i.conditions.Add(cond); item.conditions = reference;
return true; return true;
} }
} }
@@ -1087,11 +1066,11 @@ namespace Game.Loots
itemList = group.GetEqualChancedItemList(); itemList = group.GetEqualChancedItemList();
if (!itemList.Empty()) if (!itemList.Empty())
{ {
foreach (var i in itemList) foreach (var item in itemList)
{ {
if (i.itemid == cond.SourceEntry) if (item.itemid == id.SourceEntry)
{ {
i.conditions.Add(cond); item.conditions = reference;
return true; return true;
} }
} }
@@ -1100,6 +1079,7 @@ namespace Game.Loots
} }
return false; return false;
} }
public bool IsReference(uint id) public bool IsReference(uint id)
{ {
foreach (var storeItem in Entries) foreach (var storeItem in Entries)
@@ -1210,14 +1190,6 @@ namespace Game.Loots
} }
public LootStoreItemList GetExplicitlyChancedItemList() { return ExplicitlyChanced; } public LootStoreItemList GetExplicitlyChancedItemList() { return ExplicitlyChanced; }
public LootStoreItemList GetEqualChancedItemList() { return EqualChanced; } public LootStoreItemList GetEqualChancedItemList() { return EqualChanced; }
public void CopyConditions(List<Condition> conditions)
{
foreach (var i in ExplicitlyChanced)
i.conditions.Clear();
foreach (var i in EqualChanced)
i.conditions.Clear();
}
LootStoreItemList ExplicitlyChanced = new(); // Entries with chances defined in DB LootStoreItemList ExplicitlyChanced = new(); // Entries with chances defined in DB
LootStoreItemList EqualChanced = new(); // Zero chances - every entry takes the same chance LootStoreItemList EqualChanced = new(); // Zero chances - every entry takes the same chance
+2 -13
View File
@@ -3883,19 +3883,8 @@ namespace Game.Spells
public void _UnloadImplicitTargetConditionLists() public void _UnloadImplicitTargetConditionLists()
{ {
// find the same instances of ConditionList and delete them. // find the same instances of ConditionList and delete them.
foreach (var effectInfo in _effects) foreach (SpellEffectInfo effect in _effects)
{ effect.ImplicitTargetConditions = null;
var cur = effectInfo.ImplicitTargetConditions;
if (cur == null)
continue;
for (int j = (int)effectInfo.EffectIndex; j < _effects.Count; ++j)
{
SpellEffectInfo eff = _effects[j];
if (eff.ImplicitTargetConditions == cur)
eff.ImplicitTargetConditions = null;
}
}
} }
public bool MeetsFutureSpellPlayerCondition(Player player) public bool MeetsFutureSpellPlayerCondition(Player player)