Fix #23 - Wards deleted while in use causing crash
This commit is contained in:
parent
8cd6008ba6
commit
4e43c73f9c
@ -2221,7 +2221,13 @@ float Entity::CalculateDPSMultiplier(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entity::AddWard(int32 spellID, WardInfo* ward) {
|
void Entity::AddWard(int32 spellID, WardInfo* ward) {
|
||||||
if (m_wardList.count(spellID) == 0) {
|
if(MWardList.try_lock()) {
|
||||||
|
if (m_wardList.count(spellID) == 0) {
|
||||||
|
m_wardList[spellID] = ward;
|
||||||
|
}
|
||||||
|
MWardList.unlock();
|
||||||
|
}
|
||||||
|
else if (m_wardList.count(spellID) == 0) {
|
||||||
m_wardList[spellID] = ward;
|
m_wardList[spellID] = ward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2229,22 +2235,32 @@ void Entity::AddWard(int32 spellID, WardInfo* ward) {
|
|||||||
WardInfo* Entity::GetWard(int32 spellID) {
|
WardInfo* Entity::GetWard(int32 spellID) {
|
||||||
WardInfo* ret = 0;
|
WardInfo* ret = 0;
|
||||||
|
|
||||||
if (m_wardList.count(spellID) > 0)
|
if (MWardList.try_lock_shared()) {
|
||||||
|
if (m_wardList.count(spellID) > 0)
|
||||||
|
ret = m_wardList[spellID];
|
||||||
|
MWardList.unlock_shared();
|
||||||
|
}
|
||||||
|
else if (m_wardList.count(spellID) > 0)
|
||||||
ret = m_wardList[spellID];
|
ret = m_wardList[spellID];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::RemoveWard(int32 spellID) {
|
void Entity::RemoveWard(int32 spellID) {
|
||||||
if (m_wardList.count(spellID) > 0) {
|
if(MWardList.try_lock()) {
|
||||||
// Delete the ward info
|
if (m_wardList.count(spellID) > 0) {
|
||||||
safe_delete(m_wardList[spellID]);
|
WardInfo* info = m_wardList[spellID];
|
||||||
// Remove from the ward list
|
info->DeleteWard = true;
|
||||||
m_wardList.erase(spellID);
|
}
|
||||||
|
MWardList.unlock();
|
||||||
|
}
|
||||||
|
else if (m_wardList.count(spellID) > 0) {
|
||||||
|
m_wardList[spellID]->DeleteWard = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
|
int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
|
||||||
|
std::unique_lock lock(MWardList);
|
||||||
map<int32, WardInfo*>::iterator itr;
|
map<int32, WardInfo*>::iterator itr;
|
||||||
WardInfo* ward = 0;
|
WardInfo* ward = 0;
|
||||||
LuaSpell* spell = 0;
|
LuaSpell* spell = 0;
|
||||||
@ -2252,7 +2268,7 @@ int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
|
|||||||
while (m_wardList.size() > 0 && damage > 0) {
|
while (m_wardList.size() > 0 && damage > 0) {
|
||||||
// Get the ward with the lowest base damage
|
// Get the ward with the lowest base damage
|
||||||
for (itr = m_wardList.begin(); itr != m_wardList.end(); itr++) {
|
for (itr = m_wardList.begin(); itr != m_wardList.end(); itr++) {
|
||||||
if(itr->second->RoundTriggered)
|
if(itr->second->RoundTriggered || itr->second->DeleteWard)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ward || itr->second->BaseDamage < ward->BaseDamage) {
|
if (!ward || itr->second->BaseDamage < ward->BaseDamage) {
|
||||||
@ -2319,9 +2335,8 @@ int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
|
|||||||
GetZone()->SendHealPacket(spell->caster, this, HEAL_PACKET_TYPE_ABSORB, ward->DamageLeft, spell->spell->GetName());
|
GetZone()->SendHealPacket(spell->caster, this, HEAL_PACKET_TYPE_ABSORB, ward->DamageLeft, spell->spell->GetName());
|
||||||
|
|
||||||
if (!ward->keepWard) {
|
if (!ward->keepWard) {
|
||||||
|
ward->DeleteWard = true;
|
||||||
hasSpellBeenRemoved = true;
|
hasSpellBeenRemoved = true;
|
||||||
RemoveWard(spell->spell->GetSpellID());
|
|
||||||
GetZone()->GetSpellProcess()->DeleteCasterSpell(spell, "purged");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2379,16 +2394,24 @@ int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
|
|||||||
|
|
||||||
if (shouldRemoveSpell && !hasSpellBeenRemoved)
|
if (shouldRemoveSpell && !hasSpellBeenRemoved)
|
||||||
{
|
{
|
||||||
RemoveWard(spell->spell->GetSpellID());
|
ward->DeleteWard = true;
|
||||||
GetZone()->GetSpellProcess()->DeleteCasterSpell(spell, "purged");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset ward pointer
|
// Reset ward pointer
|
||||||
ward = 0;
|
ward = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (itr = m_wardList.begin(); itr != m_wardList.end(); itr++) {
|
for (itr = m_wardList.begin(); itr != m_wardList.end();) {
|
||||||
itr->second->RoundTriggered = false;
|
if(itr->second->DeleteWard) {
|
||||||
|
WardInfo* info = itr->second;
|
||||||
|
itr = m_wardList.erase(itr);
|
||||||
|
GetZone()->GetSpellProcess()->DeleteCasterSpell(info->Spell, "purged");
|
||||||
|
safe_delete(info);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
itr->second->RoundTriggered = false;
|
||||||
|
itr++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return damage;
|
return damage;
|
||||||
|
@ -1308,6 +1308,8 @@ struct WardInfo {
|
|||||||
bool AbsorbAllDamage; // damage is always absorbed, usually spells based on hits, when we pass damage in AddWard as 0 this will be set to true
|
bool AbsorbAllDamage; // damage is always absorbed, usually spells based on hits, when we pass damage in AddWard as 0 this will be set to true
|
||||||
|
|
||||||
bool RoundTriggered;
|
bool RoundTriggered;
|
||||||
|
|
||||||
|
bool DeleteWard; // removal after process CheckWard while loop
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WARD_TYPE_ALL 0
|
#define WARD_TYPE_ALL 0
|
||||||
@ -2111,6 +2113,7 @@ private:
|
|||||||
|
|
||||||
// int32 = spell id, WardInfo* = pointer to ward info
|
// int32 = spell id, WardInfo* = pointer to ward info
|
||||||
map<int32, WardInfo*> m_wardList;
|
map<int32, WardInfo*> m_wardList;
|
||||||
|
mutable std::shared_mutex MWardList;
|
||||||
|
|
||||||
// int8 = type, vector<Proc*> = list of pointers to proc info
|
// int8 = type, vector<Proc*> = list of pointers to proc info
|
||||||
map <int8, vector<Proc*> > m_procList;
|
map <int8, vector<Proc*> > m_procList;
|
||||||
|
@ -6577,7 +6577,8 @@ int EQ2Emu_lua_AddWard(lua_State* state) {
|
|||||||
|
|
||||||
if (wardType == WARD_TYPE_MAGICAL)
|
if (wardType == WARD_TYPE_MAGICAL)
|
||||||
ward->DamageType = damageTypes;
|
ward->DamageType = damageTypes;
|
||||||
|
|
||||||
|
ward->DeleteWard = false;
|
||||||
// Add the ward to the entity
|
// Add the ward to the entity
|
||||||
((Entity*)target)->AddWard(spell->spell->GetSpellID(), ward);
|
((Entity*)target)->AddWard(spell->spell->GetSpellID(), ward);
|
||||||
ward_was_added = true;
|
ward_was_added = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user