Fix memory leaks in ConditionManager.
--HG-- branch : trunk
This commit is contained in:
@@ -201,6 +201,7 @@ ConditionMgr::ConditionMgr()
|
|||||||
|
|
||||||
ConditionMgr::~ConditionMgr()
|
ConditionMgr::~ConditionMgr()
|
||||||
{
|
{
|
||||||
|
Clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionList ConditionMgr::GetConditionReferences(uint32 refId)
|
ConditionList ConditionMgr::GetConditionReferences(uint32 refId)
|
||||||
@@ -236,7 +237,7 @@ bool ConditionMgr::IsPlayerMeetToConditionList(Player* player,const ConditionLis
|
|||||||
}else{
|
}else{
|
||||||
sLog.outDebug("IsPlayerMeetToConditionList: Reference template -%u not found", (*i)->mReferenceId);//checked at loading, should never happen
|
sLog.outDebug("IsPlayerMeetToConditionList: Reference template -%u not found", (*i)->mReferenceId);//checked at loading, should never happen
|
||||||
}
|
}
|
||||||
|
|
||||||
} else//handle normal condition
|
} else//handle normal condition
|
||||||
{
|
{
|
||||||
if (!(*i)->Meets(player, targetOverride))
|
if (!(*i)->Meets(player, targetOverride))
|
||||||
@@ -273,7 +274,7 @@ ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType
|
|||||||
{
|
{
|
||||||
ConditionMap::const_iterator itr = m_ConditionMap.find(sType);
|
ConditionMap::const_iterator itr = m_ConditionMap.find(sType);
|
||||||
if (itr != m_ConditionMap.end())
|
if (itr != m_ConditionMap.end())
|
||||||
{
|
{
|
||||||
ConditionTypeMap::const_iterator i = (*itr).second.find(uEntry);
|
ConditionTypeMap::const_iterator i = (*itr).second.find(uEntry);
|
||||||
if (i != (*itr).second.end())
|
if (i != (*itr).second.end())
|
||||||
{
|
{
|
||||||
@@ -287,8 +288,8 @@ ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType
|
|||||||
|
|
||||||
void ConditionMgr::LoadConditions(bool isReload)
|
void ConditionMgr::LoadConditions(bool isReload)
|
||||||
{
|
{
|
||||||
m_ConditionMap.clear(); // for reload case
|
Clean();
|
||||||
m_ConditionReferenceMap.clear(); // for reload case
|
|
||||||
//must clear all custom handled cases (groupped types) before reload
|
//must clear all custom handled cases (groupped types) before reload
|
||||||
if (isReload)
|
if (isReload)
|
||||||
{
|
{
|
||||||
@@ -336,11 +337,11 @@ void ConditionMgr::LoadConditions(bool isReload)
|
|||||||
Field *fields = result->Fetch();
|
Field *fields = result->Fetch();
|
||||||
|
|
||||||
Condition* cond = new Condition();
|
Condition* cond = new Condition();
|
||||||
int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
|
int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
|
||||||
cond->mSourceGroup = fields[1].GetUInt32();
|
cond->mSourceGroup = fields[1].GetUInt32();
|
||||||
cond->mSourceEntry = fields[2].GetUInt32();
|
cond->mSourceEntry = fields[2].GetUInt32();
|
||||||
cond->mElseGroup = fields[3].GetUInt32();
|
cond->mElseGroup = fields[3].GetUInt32();
|
||||||
int32 iConditionTypeOrReference = fields[4].GetInt32();
|
int32 iConditionTypeOrReference = fields[4].GetInt32();
|
||||||
cond->mConditionValue1 = fields[5].GetUInt32();
|
cond->mConditionValue1 = fields[5].GetUInt32();
|
||||||
cond->mConditionValue2 = fields[6].GetUInt32();
|
cond->mConditionValue2 = fields[6].GetUInt32();
|
||||||
cond->mConditionValue3 = fields[7].GetUInt32();
|
cond->mConditionValue3 = fields[7].GetUInt32();
|
||||||
@@ -354,6 +355,7 @@ void ConditionMgr::LoadConditions(bool isReload)
|
|||||||
if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skip
|
if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skip
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Condition reference %i is referencing self, skipped", iSourceTypeOrReferenceId);
|
sLog.outErrorDb("Condition reference %i is referencing self, skipped", iSourceTypeOrReferenceId);
|
||||||
|
delete cond;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cond->mReferenceId = uint32(abs(iConditionTypeOrReference));
|
cond->mReferenceId = uint32(abs(iConditionTypeOrReference));
|
||||||
@@ -373,8 +375,10 @@ void ConditionMgr::LoadConditions(bool isReload)
|
|||||||
if (cond->mSourceEntry && iSourceTypeOrReferenceId < 0)
|
if (cond->mSourceEntry && iSourceTypeOrReferenceId < 0)
|
||||||
sLog.outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceEntry);
|
sLog.outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceEntry);
|
||||||
}else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType
|
}else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType
|
||||||
continue;
|
{
|
||||||
|
delete cond;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (iSourceTypeOrReferenceId < 0)//it is a reference template
|
if (iSourceTypeOrReferenceId < 0)//it is a reference template
|
||||||
{
|
{
|
||||||
@@ -390,15 +394,19 @@ void ConditionMgr::LoadConditions(bool isReload)
|
|||||||
}//end of reference templates
|
}//end of reference templates
|
||||||
|
|
||||||
cond->mSourceType = ConditionSourceType(iSourceTypeOrReferenceId);
|
cond->mSourceType = ConditionSourceType(iSourceTypeOrReferenceId);
|
||||||
|
|
||||||
//if not a reference and SourceType is invalid, skip
|
//if not a reference and SourceType is invalid, skip
|
||||||
if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond))
|
if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond))
|
||||||
|
{
|
||||||
|
delete cond;
|
||||||
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)
|
||||||
if (cond->mSourceGroup && !isGroupable(cond->mSourceType))
|
if (cond->mSourceGroup && !isGroupable(cond->mSourceType))
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->mSourceType), cond->mSourceGroup);
|
sLog.outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->mSourceType), cond->mSourceGroup);
|
||||||
|
delete cond;
|
||||||
continue;
|
continue;
|
||||||
}else if (cond->mSourceGroup)
|
}else if (cond->mSourceGroup)
|
||||||
{
|
{
|
||||||
@@ -450,9 +458,15 @@ void ConditionMgr::LoadConditions(bool isReload)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!bIsDone)
|
if (!bIsDone)
|
||||||
|
{
|
||||||
sLog.outErrorDb("Not handled grouped condition, SourceGroup %u", cond->mSourceGroup);
|
sLog.outErrorDb("Not handled grouped condition, SourceGroup %u", cond->mSourceGroup);
|
||||||
|
delete cond;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
m_AllocatedMemory.push_back(cond);
|
||||||
++count;
|
++count;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +523,7 @@ bool ConditionMgr::addToGossipMenus(Condition* cond)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sLog.outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->mSourceGroup);
|
sLog.outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->mSourceGroup);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -591,7 +605,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE:
|
case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE:
|
||||||
{
|
{
|
||||||
if (!LootTemplates_Gameobject.HaveLootFor(cond->mSourceGroup))
|
if (!LootTemplates_Gameobject.HaveLootFor(cond->mSourceGroup))
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->mSourceGroup);
|
sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->mSourceGroup);
|
||||||
@@ -607,7 +621,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE:
|
case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE:
|
||||||
{
|
{
|
||||||
if (!LootTemplates_Item.HaveLootFor(cond->mSourceGroup))
|
if (!LootTemplates_Item.HaveLootFor(cond->mSourceGroup))
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->mSourceGroup);
|
sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->mSourceGroup);
|
||||||
@@ -1043,10 +1057,10 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
|
|||||||
{
|
{
|
||||||
sLog.outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->mConditionValue1);
|
sLog.outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->mConditionValue1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch(cond->mConditionValue1)
|
switch(cond->mConditionValue1)
|
||||||
{
|
{
|
||||||
case SPELL_TARGET_TYPE_GAMEOBJECT:
|
case SPELL_TARGET_TYPE_GAMEOBJECT:
|
||||||
{
|
{
|
||||||
if (cond->mConditionValue2 && !sGOStorage.LookupEntry<GameObjectInfo>(cond->mConditionValue2))
|
if (cond->mConditionValue2 && !sGOStorage.LookupEntry<GameObjectInfo>(cond->mConditionValue2))
|
||||||
{
|
{
|
||||||
@@ -1143,3 +1157,31 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConditionMgr::Clean()
|
||||||
|
{
|
||||||
|
for (ConditionReferenceMap::iterator itr = m_ConditionReferenceMap.begin(); itr != m_ConditionReferenceMap.end(); ++itr)
|
||||||
|
{
|
||||||
|
for (ConditionList::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
|
||||||
|
delete *it;
|
||||||
|
itr->second.clear();
|
||||||
|
}
|
||||||
|
m_ConditionReferenceMap.clear();
|
||||||
|
|
||||||
|
for (ConditionMap::iterator itr = m_ConditionMap.begin(); itr != m_ConditionMap.end(); ++itr)
|
||||||
|
{
|
||||||
|
for (ConditionTypeMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
|
||||||
|
{
|
||||||
|
for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
|
||||||
|
delete *i;
|
||||||
|
it->second.clear();
|
||||||
|
}
|
||||||
|
itr->second.clear();
|
||||||
|
}
|
||||||
|
m_ConditionMap.clear();
|
||||||
|
|
||||||
|
// this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
|
||||||
|
for (std::list<Condition*>::const_iterator itr = m_AllocatedMemory.begin(); itr != m_AllocatedMemory.end(); ++itr)
|
||||||
|
delete *itr;
|
||||||
|
m_AllocatedMemory.clear();
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ enum ConditionType
|
|||||||
CONDITION_CLASS = 15, // class 0 +referenceID true if player's class is equal to class
|
CONDITION_CLASS = 15, // class 0 +referenceID true if player's class is equal to class
|
||||||
CONDITION_RACE = 16, // race 0 +referenceID true if player's race is equal to race
|
CONDITION_RACE = 16, // race 0 +referenceID true if player's race is equal to race
|
||||||
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 +referenceID true if achievement is complete
|
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 +referenceID true if achievement is complete
|
||||||
CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0
|
CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0
|
||||||
CONDITION_CREATURE_TARGET = 19, // creature entry 0 +referenceID true if current target is creature with value1 entry
|
CONDITION_CREATURE_TARGET = 19, // creature entry 0 +referenceID true if current target is creature with value1 entry
|
||||||
CONDITION_TARGET_HEALTH_BELOW_PCT = 20, // 0-100 0 +referenceID true if target's health is below value1 percent, false if over or no target
|
CONDITION_TARGET_HEALTH_BELOW_PCT = 20, // 0-100 0 +referenceID true if target's health is below value1 percent, false if over or no target
|
||||||
CONDITION_TARGET_RANGE = 21, // minDistance maxDist +referenceID true if target is closer then minDist and further then maxDist or if max is 0 then max dist is infinit
|
CONDITION_TARGET_RANGE = 21, // minDistance maxDist +referenceID true if target is closer then minDist and further then maxDist or if max is 0 then max dist is infinit
|
||||||
@@ -84,7 +84,7 @@ enum ConditionSourceType
|
|||||||
#define MAX_CONDITIONSOURCETYPE 19
|
#define MAX_CONDITIONSOURCETYPE 19
|
||||||
|
|
||||||
struct Condition
|
struct Condition
|
||||||
{
|
{
|
||||||
ConditionSourceType mSourceType; //SourceTypeOrReferenceId
|
ConditionSourceType mSourceType; //SourceTypeOrReferenceId
|
||||||
uint32 mSourceGroup;
|
uint32 mSourceGroup;
|
||||||
uint32 mSourceEntry;
|
uint32 mSourceEntry;
|
||||||
@@ -128,7 +128,7 @@ class ConditionMgr
|
|||||||
void LoadConditions(bool isReload = false);
|
void LoadConditions(bool isReload = false);
|
||||||
bool isConditionTypeValid(Condition* cond);
|
bool isConditionTypeValid(Condition* cond);
|
||||||
ConditionList GetConditionReferences(uint32 refId);
|
ConditionList GetConditionReferences(uint32 refId);
|
||||||
|
|
||||||
bool IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride = NULL);
|
bool IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride = NULL);
|
||||||
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry);
|
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry);
|
||||||
|
|
||||||
@@ -160,6 +160,9 @@ class ConditionMgr
|
|||||||
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
|
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
|
||||||
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION);
|
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clean(); // free up resources
|
||||||
|
std::list<Condition*> m_AllocatedMemory; // some garbage collection :)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sConditionMgr Trinity::Singleton<ConditionMgr>::Instance()
|
#define sConditionMgr Trinity::Singleton<ConditionMgr>::Instance()
|
||||||
|
|||||||
Reference in New Issue
Block a user