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

This commit is contained in:
Shauren
2024-01-11 20:56:24 +01:00
parent 913d769b80
commit 0b5406dd88
17 changed files with 368 additions and 548 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,7 @@
#include "Define.h"
#include "Hash.h"
#include <array>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
@@ -183,7 +184,10 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_TRAINER_SPELL = 31,
CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY = 32,
CONDITION_SOURCE_TYPE_SPAWN_GROUP = 33,
CONDITION_SOURCE_TYPE_MAX = 34 // MAX
CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED,
CONDITION_SOURCE_TYPE_REFERENCE_CONDITION = CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED, // internal, not set in db
CONDITION_SOURCE_TYPE_MAX // MAX
};
enum RelationType
@@ -219,6 +223,23 @@ struct TC_GAME_API ConditionSourceInfo
ConditionSourceInfo(Map const* map);
};
struct TC_GAME_API ConditionId
{
uint32 SourceGroup = 0;
int32 SourceEntry = 0;
uint32 SourceId = 0;
std::size_t GetHash() const;
bool operator==(ConditionId const& right) const = default;
std::strong_ordering operator<=>(ConditionId const& right) const = default;
};
template<>
struct std::hash<ConditionId>
{
std::size_t operator()(ConditionId const& id) const noexcept { return id.GetHash(); }
};
struct TC_GAME_API Condition
{
ConditionSourceType SourceType; //SourceTypeOrReferenceId
@@ -264,13 +285,9 @@ struct TC_GAME_API Condition
std::string ToString(bool ext = false) const; /// For logging purpose
};
typedef std::vector<Condition*> ConditionContainer;
typedef std::unordered_map<uint32 /*SourceEntry*/, ConditionContainer> ConditionsByEntryMap;
typedef std::vector<Condition> ConditionContainer;
typedef std::unordered_map<ConditionId, std::shared_ptr<ConditionContainer>> ConditionsByEntryMap; // stored as shared_ptr to give out weak_ptrs to hold by other code (ownership not shared)
typedef std::array<ConditionsByEntryMap, CONDITION_SOURCE_TYPE_MAX> ConditionEntriesByTypeArray;
typedef std::unordered_map<uint32, ConditionsByEntryMap> ConditionEntriesByCreatureIdMap;
typedef std::unordered_map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionsByEntryMap> SmartEventConditionContainer;
typedef std::unordered_map<uint32, ConditionContainer> ConditionReferenceContainer;//only used for references
typedef std::unordered_map<std::pair<int32, bool>, ConditionContainer> ConditionEntriesByAreaTriggerIdMap;
class TC_GAME_API ConditionMgr
{
@@ -296,7 +313,7 @@ class TC_GAME_API ConditionMgr
bool IsMapMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, Map const* map) const;
bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const;
bool IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject const* clicker, WorldObject const* target) const;
ConditionContainer const* GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const;
bool HasConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const;
bool IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player const* player, Unit const* vehicle) const;
bool IsObjectMeetingSmartEventConditions(int64 entryOrGuid, uint32 eventId, uint32 sourceType, Unit const* unit, WorldObject const* baseObject) const;
bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player const* player, Creature const* vendor) const;
@@ -319,37 +336,61 @@ class TC_GAME_API ConditionMgr
bool HasConditionValue2;
bool HasConditionValue3;
};
static char const* const StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX];
static char const* const StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED];
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX];
private:
bool isSourceTypeValid(Condition* cond) const;
bool addToLootTemplate(Condition* cond, LootTemplate* loot) const;
bool addToGossipMenus(Condition* cond) const;
bool addToGossipMenuItems(Condition* cond) const;
bool addToSpellImplicitTargetConditions(Condition* cond) const;
bool addToPhases(Condition* cond) const;
bool addToGraveyardData(Condition* cond) const;
void addToLootTemplate(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions, LootTemplate* loot) const;
void addToGossipMenus(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const;
void addToGossipMenuItems(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const;
void addToSpellImplicitTargetConditions(Condition const& cond) const;
void addToPhases(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const;
void addToGraveyardData(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const;
bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionContainer const& conditions) const;
static void LogUselessConditionValue(Condition* cond, uint8 index, uint32 value);
void Clean(); // free up resources
std::vector<Condition*> AllocatedMemoryStore; // some garbage collection :)
ConditionEntriesByTypeArray ConditionStore;
ConditionReferenceContainer ConditionReferenceStore;
ConditionEntriesByCreatureIdMap VehicleSpellConditionStore;
ConditionEntriesByCreatureIdMap SpellClickEventConditionStore;
ConditionEntriesByCreatureIdMap NpcVendorConditionContainerStore;
SmartEventConditionContainer SmartEventConditionStore;
std::unordered_set<uint32> SpellsUsedInSpellClickConditions;
ConditionEntriesByAreaTriggerIdMap AreaTriggerConditionContainerStore;
ConditionEntriesByCreatureIdMap TrainerSpellConditionContainerStore;
std::unordered_map<std::pair<uint32 /*object type*/, uint32 /*object id*/>, ConditionContainer> ObjectVisibilityConditionStore;
};
#define sConditionMgr ConditionMgr::instance()
struct ConditionsReference
{
bool Meets(WorldObject const* object) const
{
if (std::shared_ptr<std::vector<Condition>> conditions = Conditions.lock())
return sConditionMgr->IsObjectMeetToConditions(object, *conditions);
return true;
}
bool Meets(WorldObject const* object1, WorldObject const* object2) const
{
if (std::shared_ptr<std::vector<Condition>> conditions = Conditions.lock())
return sConditionMgr->IsObjectMeetToConditions(object1, object2, *conditions);
return true;
}
bool Meets(ConditionSourceInfo& sourceInfo) const
{
if (std::shared_ptr<std::vector<Condition>> conditions = Conditions.lock())
return sConditionMgr->IsObjectMeetToConditions(sourceInfo, *conditions);
return true;
}
bool IsEmpty() const
{
if (std::shared_ptr<std::vector<Condition>> conditions = Conditions.lock())
return conditions->empty();
return true;
}
std::weak_ptr<ConditionContainer> Conditions;
};
#endif

View File

@@ -14000,7 +14000,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId, bool showQues
for (auto const& [_, gossipMenuItem] : menuItemBounds)
{
if (!sConditionMgr->IsObjectMeetToConditions(this, source, gossipMenuItem.Conditions))
if (!gossipMenuItem.Conditions.Meets(this, source))
continue;
bool canTalk = true;
@@ -14326,7 +14326,7 @@ uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source)
if (!itr->second.TextID)
continue;
if (sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions))
if (itr->second.Conditions.Meets(this, source))
textId = itr->second.TextID;
}
@@ -14352,7 +14352,7 @@ uint32 Player::GetGossipMenuForSource(WorldObject* source)
for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr)
{
if (!sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions))
if (!itr->second.Conditions.Meets(this, source))
continue;
menuIdToShow = menuId;
@@ -25130,7 +25130,7 @@ void Player::UpdateVisibleGameobjectsOrSpellClicks()
auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
for (auto const& clickPair : clickBounds)
{
if (sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), clickPair.second.spellId))
if (sConditionMgr->HasConditionsForSpellClickEvent(obj->GetEntry(), clickPair.second.spellId))
{
UF::ObjectData::Base objMask;
UF::UnitData::Base unitMask;

View File

@@ -6900,7 +6900,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveyardInZone(WorldLocation con
if (conditionObject)
{
if (!sConditionMgr->IsObjectMeetToConditions(conditionSource, data.Conditions))
if (!data.Conditions.Meets(conditionSource))
continue;
if (int16(entry->Loc.GetMapId()) == mapEntry->ParentMapID && !conditionObject->GetPhaseShift().HasVisibleMapId(entry->Loc.GetMapId()))
@@ -6909,15 +6909,18 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveyardInZone(WorldLocation con
else if (team != 0)
{
bool teamConditionMet = true;
for (Condition const* cond : data.Conditions)
if (std::shared_ptr<std::vector<Condition>> conditions = data.Conditions.Conditions.lock())
{
if (cond->ConditionType != CONDITION_TEAM)
continue;
for (Condition const& cond : *conditions)
{
if (cond.ConditionType != CONDITION_TEAM)
continue;
if (cond->ConditionValue1 == team)
continue;
if (cond.ConditionValue1 == team)
continue;
teamConditionMet = false;
teamConditionMet = false;
}
}
if (!teamConditionMet)

View File

@@ -755,14 +755,14 @@ struct GossipMenuItems
uint32 BoxBroadcastTextID;
Optional<int32> SpellID;
Optional<int32> OverrideIconID;
ConditionContainer Conditions;
ConditionsReference Conditions;
};
struct GossipMenus
{
uint32 MenuID;
uint32 TextID;
ConditionContainer Conditions;
ConditionsReference Conditions;
};
struct GossipMenuAddon
@@ -836,7 +836,7 @@ struct WorldSafeLocsEntry
struct GraveyardData
{
uint32 safeLocId;
ConditionContainer Conditions;
ConditionsReference Conditions;
};
typedef std::multimap<uint32, GraveyardData> GraveyardContainer;

View File

@@ -369,7 +369,7 @@ void WorldSession::HandleRequestCemeteryList(WorldPackets::Misc::RequestCemetery
for (auto it = range.first; it != range.second && graveyardIds.size() < 16; ++it) // client max
{
ConditionSourceInfo conditionSource(_player);
if (!sConditionMgr->IsObjectMeetToConditions(conditionSource, it->second.Conditions))
if (!it->second.Conditions.Meets(conditionSource))
continue;
graveyardIds.push_back(it->first);

View File

@@ -75,10 +75,10 @@ bool LootItem::AllowedForPlayer(Player const* player, Loot const* loot) const
}
bool LootItem::AllowedForPlayer(Player const* player, Loot const* loot, uint32 itemid, bool needs_quest, bool follow_loot_rules, bool strictUsabilityCheck,
ConditionContainer const& conditions)
ConditionsReference const& conditions)
{
// DB conditions check
if (!sConditionMgr->IsObjectMeetToConditions(player, conditions))
if (!conditions.Meets(player))
return false;
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
@@ -956,7 +956,7 @@ bool Loot::hasItemForAll() const
return true;
for (LootItem const& item : 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 false;
}

View File

@@ -179,7 +179,7 @@ struct TC_GAME_API LootItem
ItemRandomBonusListId randomBonusListId;
std::vector<int32> BonusListIDs;
ItemContext context;
ConditionContainer conditions; // additional loot condition
ConditionsReference conditions; // additional loot condition
GuidSet allowedGUIDs;
ObjectGuid rollWinnerGUID; // Stores the guid of person who won loot, if his bags are full only he can see the item in loot list!
uint8 count : 8;
@@ -208,7 +208,7 @@ struct TC_GAME_API LootItem
// Basic checks for player/item compatibility - if false no chance to see the item in the loot - used only for loot generation
bool AllowedForPlayer(Player const* player, Loot const* loot) const;
static bool AllowedForPlayer(Player const* player, Loot const* loot, uint32 itemid, bool needs_quest, bool follow_loot_rules, bool strictUsabilityCheck,
ConditionContainer const& conditions);
ConditionsReference const& conditions);
void AddAllowedLooter(Player const* player);
GuidSet const& GetAllowedLooters() const { return allowedGUIDs; }
bool HasAllowedLooter(ObjectGuid const& looter) const;

View File

@@ -101,7 +101,6 @@ class LootTemplate::LootGroup // A set of loot def
void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
LootStoreItemList* GetExplicitlyChancedItemList() { return &ExplicitlyChanced; }
LootStoreItemList* GetEqualChancedItemList() { return &EqualChanced; }
void CopyConditions(ConditionContainer conditions);
private:
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
@@ -217,15 +216,6 @@ bool LootStore::HaveQuestLootForPlayer(uint32 loot_id, Player const* player) con
return false;
}
void LootStore::ResetConditions()
{
for (LootTemplateMap::iterator itr = m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr)
{
ConditionContainer empty;
itr->second->CopyConditions(empty);
}
}
LootTemplate const* LootStore::GetLootFor(uint32 loot_id) const
{
LootTemplateMap::const_iterator tab = m_LootTemplates.find(loot_id);
@@ -453,15 +443,6 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const* player) const
return false;
}
void LootTemplate::LootGroup::CopyConditions(ConditionContainer /*conditions*/)
{
for (LootStoreItemList::iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
(*i)->conditions.clear();
for (LootStoreItemList::iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
(*i)->conditions.clear();
}
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode, Player const* personalLooter /*= nullptr*/) const
{
@@ -558,16 +539,6 @@ void LootTemplate::AddEntry(LootStoreItem* item)
Entries.push_back(item);
}
void LootTemplate::CopyConditions(ConditionContainer const& conditions)
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
(*i)->conditions.clear();
for (LootGroups::iterator i = Groups.begin(); i != Groups.end(); ++i)
if (LootGroup* group = *i)
group->CopyConditions(conditions);
}
void LootTemplate::CopyConditions(LootItem* li) const
{
// Copies the conditions list from a template item to a LootItemData
@@ -880,21 +851,15 @@ void LootTemplate::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_se
group->CheckLootRefs(store, ref_set);
}
bool LootTemplate::addConditionItem(Condition* cond)
bool LootTemplate::LinkConditions(ConditionId const& id, ConditionsReference reference)
{
if (!cond || !cond->isLoaded())//should never happen, checked at loading
{
TC_LOG_ERROR("loot", "LootTemplate::addConditionItem: condition is null");
return false;
}
if (!Entries.empty())
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
for (LootStoreItem* item : Entries)
{
if ((*i)->itemid == uint32(cond->SourceEntry))
if (item->itemid == uint32(id.SourceEntry))
{
(*i)->conditions.push_back(cond);
item->conditions = std::move(reference);
return true;
}
}
@@ -902,20 +867,19 @@ bool LootTemplate::addConditionItem(Condition* cond)
if (!Groups.empty())
{
for (LootGroups::iterator groupItr = Groups.begin(); groupItr != Groups.end(); ++groupItr)
for (LootGroup* group : Groups)
{
LootGroup* group = *groupItr;
if (!group)
continue;
LootStoreItemList* itemList = group->GetExplicitlyChancedItemList();
if (!itemList->empty())
{
for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
for (LootStoreItem* item : *itemList)
{
if ((*i)->itemid == uint32(cond->SourceEntry))
if (item->itemid == uint32(id.SourceEntry))
{
(*i)->conditions.push_back(cond);
item->conditions = std::move(reference);
return true;
}
}
@@ -924,11 +888,11 @@ bool LootTemplate::addConditionItem(Condition* cond)
itemList = group->GetEqualChancedItemList();
if (!itemList->empty())
{
for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
for (LootStoreItem* item : *itemList)
{
if ((*i)->itemid == uint32(cond->SourceEntry))
if (item->itemid == uint32(id.SourceEntry))
{
(*i)->conditions.push_back(cond);
item->conditions = std::move(reference);
return true;
}
}

View File

@@ -46,7 +46,7 @@ struct TC_GAME_API LootStoreItem
uint8 groupid;
uint8 mincount; // mincount for drop items
uint8 maxcount; // max drop count for the item mincount or Ref multiplicator
ConditionContainer conditions; // additional loot condition
ConditionsReference conditions; // additional loot condition
// Constructor
// displayid is filled in IsValid() which must be called after
@@ -85,7 +85,6 @@ class TC_GAME_API LootStore
bool HaveQuestLootForPlayer(uint32 loot_id, Player const* player) const;
LootTemplate const* GetLootFor(uint32 loot_id) const;
void ResetConditions();
LootTemplate* GetLootForConditionFill(uint32 loot_id);
char const* GetName() const { return m_name; }
@@ -115,7 +114,6 @@ class TC_GAME_API LootTemplate
// Rolls for every item in the template and adds the rolled items the the loot
void Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId, Player const* personalLooter = nullptr) const;
void ProcessPersonalLoot(std::unordered_map<Player*, std::unique_ptr<Loot>>& personalLoot, bool rate, uint16 lootMode) const;
void CopyConditions(ConditionContainer const& conditions);
void CopyConditions(LootItem* li) const;
// True if template includes at least 1 drop for the player
@@ -128,7 +126,7 @@ class TC_GAME_API LootTemplate
// Checks integrity of the template
void Verify(LootStore const& store, uint32 Id) const;
void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
bool addConditionItem(Condition* cond);
bool LinkConditions(ConditionId const& id, ConditionsReference reference);
bool isReference(uint32 id);
private:

View File

@@ -25,7 +25,7 @@ PhaseShift& PhaseShift::operator=(PhaseShift const& right) = default;
PhaseShift& PhaseShift::operator=(PhaseShift&& right) noexcept = default;
PhaseShift::~PhaseShift() = default;
bool PhaseShift::AddPhase(uint32 phaseId, PhaseFlags flags, std::vector<Condition*> const* areaConditions, int32 references /*= 1*/)
bool PhaseShift::AddPhase(uint32 phaseId, PhaseFlags flags, std::vector<Condition> const* areaConditions, int32 references /*= 1*/)
{
auto insertResult = Phases.emplace(phaseId, flags, nullptr);
ModifyPhasesReferences(insertResult.first, references);

View File

@@ -56,13 +56,13 @@ class TC_GAME_API PhaseShift
public:
struct PhaseRef
{
PhaseRef(uint32 id, PhaseFlags flags, std::vector<Condition*> const* conditions)
PhaseRef(uint32 id, PhaseFlags flags, std::vector<Condition> const* conditions)
: Id(id), Flags(flags), References(0), AreaConditions(conditions) { }
uint16 Id;
EnumFlag<PhaseFlags> Flags;
int32 References;
std::vector<Condition*> const* AreaConditions;
std::vector<Condition> const* AreaConditions;
std::strong_ordering operator<=>(PhaseRef const& right) const { return Id <=> right.Id; }
bool operator==(PhaseRef const& right) const { return Id == right.Id; }
bool IsPersonal() const { return Flags.HasFlag(PhaseFlags::Personal); }
@@ -95,7 +95,7 @@ public:
ObjectGuid GetPersonalGuid() const { return PersonalGuid; }
bool AddPhase(uint32 phaseId, PhaseFlags flags, std::vector<Condition*> const* areaConditions, int32 references = 1);
bool AddPhase(uint32 phaseId, PhaseFlags flags, std::vector<Condition> const* areaConditions, int32 references = 1);
EraseResult<PhaseContainer> RemovePhase(uint32 phaseId);
bool HasPhase(uint32 phaseId) const { return Phases.find(PhaseRef(phaseId, PhaseFlags::None, nullptr)) != Phases.end(); }
PhaseContainer const& GetPhases() const { return Phases; }

View File

@@ -2525,7 +2525,7 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c
continue;
std::vector<WorldObject*> units;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
float radius = spellEffectInfo.CalcRadius(ref);
float extraSearchRadius = 0.0f;
@@ -2647,7 +2647,7 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit*
selectionType = spellEffectInfo.TargetB.GetCheckType();
std::vector<Unit*> units;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetDynobjOwner(), dynObjOwnerCaster, dynObjOwnerCaster, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
Trinity::UnitListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetDynobjOwner(), units, check);

View File

@@ -1129,7 +1129,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo,
break;
}
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
// handle emergency case - try to use other provided targets if no conditions provided
if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty()))
@@ -1313,7 +1313,7 @@ void Spell::SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, Sp
std::list<WorldObject*> targets;
SpellTargetObjectTypes objectType = targetType.GetObjectType();
SpellTargetCheckTypes selectionType = targetType.GetCheckType();
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
float radius = spellEffectInfo.CalcRadius(m_caster, targetIndex) * m_spellValue->RadiusMod;
if (uint32 containerTypeMask = GetSearcherTypeMask(m_spellInfo, spellEffectInfo, objectType, condList))
@@ -1417,15 +1417,15 @@ void Spell::SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, Sp
if (!m_caster->IsUnit() || !m_caster->ToUnit()->IsInRaidWith(targetedUnit))
targets.push_back(m_targets.GetUnitTarget());
else
SearchAreaTargets(targets, spellEffectInfo, radius, targetedUnit, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions);
SearchAreaTargets(targets, spellEffectInfo, radius, targetedUnit, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions.get());
}
break;
case TARGET_UNIT_CASTER_AND_SUMMONS:
targets.push_back(m_caster);
SearchAreaTargets(targets, spellEffectInfo, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions);
SearchAreaTargets(targets, spellEffectInfo, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions.get());
break;
default:
SearchAreaTargets(targets, spellEffectInfo, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions);
SearchAreaTargets(targets, spellEffectInfo, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions.get());
break;
}
@@ -1872,7 +1872,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, Sp
float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - srcPos.m_positionZ;
std::list<WorldObject*> targets;
Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions, TARGET_OBJECT_TYPE_NONE);
Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions.get(), TARGET_OBJECT_TYPE_NONE);
Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL);
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, &srcPos, dist2d);
if (targets.empty())
@@ -1969,7 +1969,7 @@ void Spell::SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, Sp
return;
}
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
float radius = spellEffectInfo.CalcRadius(m_caster, targetIndex) * m_spellValue->RadiusMod;
if (uint32 containerTypeMask = GetSearcherTypeMask(m_spellInfo, spellEffectInfo, objectType, condList))
@@ -2240,7 +2240,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
WorldObject* chainSource = m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) ? m_caster : target;
std::list<WorldObject*> tempTargets;
SearchAreaTargets(tempTargets, spellEffectInfo, searchRadius, chainSource, m_caster, objectType, selectType, spellEffectInfo.ImplicitTargetConditions);
SearchAreaTargets(tempTargets, spellEffectInfo, searchRadius, chainSource, m_caster, objectType, selectType, spellEffectInfo.ImplicitTargetConditions.get());
tempTargets.remove(target);
// remove targets which are always invalid for chain spells

View File

@@ -5059,18 +5059,8 @@ void SpellInfo::_InitializeSpellPositivity()
void SpellInfo::_UnloadImplicitTargetConditionLists()
{
// find the same instances of ConditionList and delete them.
for (SpellEffectInfo const& effect : _effects)
{
ConditionContainer* cur = effect.ImplicitTargetConditions;
if (!cur)
continue;
for (size_t j = effect.EffectIndex; j < _effects.size(); ++j)
if (_effects[j].ImplicitTargetConditions == cur)
_effects[j].ImplicitTargetConditions = nullptr;
delete cur;
}
for (SpellEffectInfo& effect : _effects)
effect.ImplicitTargetConditions = nullptr;
}
bool SpellInfo::MeetsFutureSpellPlayerCondition(Player const* player) const

View File

@@ -237,7 +237,7 @@ public:
uint32 TriggerSpell;
flag128 SpellClassMask;
float BonusCoefficientFromAP;
std::vector<Condition*>* ImplicitTargetConditions;
std::shared_ptr<std::vector<Condition>> ImplicitTargetConditions;
EnumFlag<SpellEffectAttributes> EffectAttributes;
// SpellScalingEntry
struct ScalingInfo

View File

@@ -1225,7 +1225,7 @@ public:
{
handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_LABEL, "Standard items", loot->items.size());
for (LootItem const& item : 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);
if (!loot->GetPlayerFFAItems().empty())