1
0

Fix #23 - Wards deleted while in use causing crash

This commit is contained in:
Emagi 2025-06-03 10:01:25 -04:00
parent 8cd6008ba6
commit 4e43c73f9c
3 changed files with 43 additions and 16 deletions

View File

@ -2221,30 +2221,46 @@ float Entity::CalculateDPSMultiplier(){
}
void Entity::AddWard(int32 spellID, WardInfo* ward) {
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;
}
}
WardInfo* Entity::GetWard(int32 spellID) {
WardInfo* ret = 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];
return ret;
}
void Entity::RemoveWard(int32 spellID) {
if(MWardList.try_lock()) {
if (m_wardList.count(spellID) > 0) {
// Delete the ward info
safe_delete(m_wardList[spellID]);
// Remove from the ward list
m_wardList.erase(spellID);
WardInfo* info = m_wardList[spellID];
info->DeleteWard = true;
}
MWardList.unlock();
}
else if (m_wardList.count(spellID) > 0) {
m_wardList[spellID]->DeleteWard = true;
}
}
int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
std::unique_lock lock(MWardList);
map<int32, WardInfo*>::iterator itr;
WardInfo* ward = 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) {
// Get the ward with the lowest base damage
for (itr = m_wardList.begin(); itr != m_wardList.end(); itr++) {
if(itr->second->RoundTriggered)
if(itr->second->RoundTriggered || itr->second->DeleteWard)
continue;
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());
if (!ward->keepWard) {
ward->DeleteWard = true;
hasSpellBeenRemoved = true;
RemoveWard(spell->spell->GetSpellID());
GetZone()->GetSpellProcess()->DeleteCasterSpell(spell, "purged");
}
}
else {
@ -2379,16 +2394,24 @@ int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
if (shouldRemoveSpell && !hasSpellBeenRemoved)
{
RemoveWard(spell->spell->GetSpellID());
GetZone()->GetSpellProcess()->DeleteCasterSpell(spell, "purged");
ward->DeleteWard = true;
}
// Reset ward pointer
ward = 0;
}
for (itr = m_wardList.begin(); itr != m_wardList.end(); itr++) {
for (itr = m_wardList.begin(); itr != m_wardList.end();) {
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;

View File

@ -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 RoundTriggered;
bool DeleteWard; // removal after process CheckWard while loop
};
#define WARD_TYPE_ALL 0
@ -2111,6 +2113,7 @@ private:
// int32 = spell id, WardInfo* = pointer to ward info
map<int32, WardInfo*> m_wardList;
mutable std::shared_mutex MWardList;
// int8 = type, vector<Proc*> = list of pointers to proc info
map <int8, vector<Proc*> > m_procList;

View File

@ -6578,6 +6578,7 @@ int EQ2Emu_lua_AddWard(lua_State* state) {
if (wardType == WARD_TYPE_MAGICAL)
ward->DamageType = damageTypes;
ward->DeleteWard = false;
// Add the ward to the entity
((Entity*)target)->AddWard(spell->spell->GetSpellID(), ward);
ward_was_added = true;