Fix #32 do not reference ammo pointer after deleting item

This commit is contained in:
Emagi 2025-06-14 08:02:49 -04:00
parent 920ea11961
commit 8aae88ca4f
2 changed files with 20 additions and 11 deletions

View File

@ -355,10 +355,11 @@ void Entity::MeleeAttack(Spawn* victim, float distance, bool primary, bool multi
} }
} }
void Entity::RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo, bool multi_attack) { bool Entity::RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo, bool multi_attack) {
if(!victim) if(!victim)
return; return false;
bool item_deleted = false;
if(weapon && weapon->IsRanged() && ammo && ammo->IsAmmo() && ammo->IsThrown()) { if(weapon && weapon->IsRanged() && ammo && ammo->IsAmmo() && ammo->IsThrown()) {
if(weapon->ranged_info->range_low <= distance && (weapon->ranged_info->range_high + ammo->thrown_info->range) >= distance) { if(weapon->ranged_info->range_low <= distance && (weapon->ranged_info->range_high + ammo->thrown_info->range) >= distance) {
int8 hit_result = DetermineHit(victim, DAMAGE_PACKET_TYPE_RANGE_DAMAGE, ammo->thrown_info->damage_type, ammo->thrown_info->hit_bonus, false); int8 hit_result = DetermineHit(victim, DAMAGE_PACKET_TYPE_RANGE_DAMAGE, ammo->thrown_info->damage_type, ammo->thrown_info->hit_bonus, false);
@ -372,6 +373,9 @@ void Entity::RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo
else else
GetZone()->SendDamagePacket(this, victim, DAMAGE_PACKET_TYPE_RANGE_DAMAGE, hit_result, ammo->thrown_info->damage_type, 0, 0); GetZone()->SendDamagePacket(this, victim, DAMAGE_PACKET_TYPE_RANGE_DAMAGE, hit_result, ammo->thrown_info->damage_type, 0, 0);
bool inv_slot_incl = false;
if(ammo->details.inv_slot_id >= 6)
inv_slot_incl = true;
// If is a player subtract ammo // If is a player subtract ammo
if (IsPlayer()) { if (IsPlayer()) {
if (ammo->details.count > 1) { if (ammo->details.count > 1) {
@ -382,9 +386,12 @@ void Entity::RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo
if(ammo->details.inv_slot_id >= 6) { if(ammo->details.inv_slot_id >= 6) {
((Player*)this)->equipment_list.RemoveItem(ammo->details.slot_id, false); ((Player*)this)->equipment_list.RemoveItem(ammo->details.slot_id, false);
((Player*)this)->item_list.DestroyItem(ammo->details.index); ((Player*)this)->item_list.DestroyItem(ammo->details.index);
ammo = nullptr; // item is gone
item_deleted = true;
} }
else { else {
((Player*)this)->equipment_list.RemoveItem(ammo->details.slot_id, true); ((Player*)this)->equipment_list.RemoveItem(ammo->details.slot_id, true);
item_deleted = true;
} }
} }
@ -394,7 +401,7 @@ void Entity::RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo
if(outapp) if(outapp)
client->QueuePacket(outapp); client->QueuePacket(outapp);
if(ammo->details.inv_slot_id > 6) { if(inv_slot_incl) {
EQ2Packet* outapp = client->GetPlayer()->SendInventoryUpdate(client->GetVersion()); EQ2Packet* outapp = client->GetPlayer()->SendInventoryUpdate(client->GetVersion());
if (outapp) if (outapp)
client->QueuePacket(outapp); client->QueuePacket(outapp);
@ -437,26 +444,28 @@ void Entity::RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo
} }
} }
//Multi Attack roll //Multi Attack roll
if(!multi_attack){ if(!multi_attack && !item_deleted){
float multi_attack = info_struct.get_multi_attack(); float multi_attack = info_struct.get_multi_attack();
if(multi_attack > 0){ if(multi_attack > 0){
float chance = multi_attack; float chance = multi_attack;
if (multi_attack > 100){ if (multi_attack > 100){
int8 automatic_multi = (int8)floor((float)(multi_attack / 100)); int8 automatic_multi = (int8)floor((float)(multi_attack / 100));
chance = (multi_attack - (floor((float)(multi_attack / 100) * 100))); chance = (multi_attack - (floor((float)(multi_attack / 100) * 100)));
while(automatic_multi > 0){ while(!item_deleted && automatic_multi > 0){
RangeAttack(victim, 100, weapon, ammo, true); item_deleted = RangeAttack(victim, 100, weapon, ammo, true);
automatic_multi--; automatic_multi--;
} }
} }
if (MakeRandomFloat(0, 100) <= chance) if (!item_deleted && MakeRandomFloat(0, 100) <= chance)
RangeAttack(victim, 100, weapon, ammo, true); item_deleted = RangeAttack(victim, 100, weapon, ammo, true);
} }
} }
//Apply attack speed mods //Apply attack speed mods
if(!multi_attack) if(!multi_attack)
SetAttackDelay(false, true); SetAttackDelay(false, true);
return item_deleted;
} }
bool Entity::SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8 damage_type, int32 low_damage, int32 high_damage, int8 crit_mod, bool no_calcs, int8 override_packet_type, bool take_power){ bool Entity::SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8 damage_type, int32 low_damage, int32 high_damage, int8 crit_mod, bool no_calcs, int8 override_packet_type, bool take_power){

View File

@ -1551,7 +1551,7 @@ public:
bool SecondaryWeaponReady(); bool SecondaryWeaponReady();
bool RangeWeaponReady(); bool RangeWeaponReady();
void MeleeAttack(Spawn* victim, float distance, bool primary, bool multi_attack = false); void MeleeAttack(Spawn* victim, float distance, bool primary, bool multi_attack = false);
void RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo, bool multi_attack = false); bool RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo, bool multi_attack = false);
bool SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8 damage_type, int32 low_damage, int32 high_damage, int8 crit_mod = 0, bool no_calcs = false, int8 override_packet_type = 0, bool take_power = false); bool SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8 damage_type, int32 low_damage, int32 high_damage, int8 crit_mod = 0, bool no_calcs = false, int8 override_packet_type = 0, bool take_power = false);
bool ProcAttack(Spawn* victim, int8 damage_type, int32 low_damage, int32 high_damage, string name, string success_msg, string effect_msg); bool ProcAttack(Spawn* victim, int8 damage_type, int32 low_damage, int32 high_damage, string name, string success_msg, string effect_msg);
bool SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string heal_type, int32 low_heal, int32 high_heal, int8 crit_mod = 0, bool no_calcs = false, string custom_spell_name=""); bool SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string heal_type, int32 low_heal, int32 high_heal, int8 crit_mod = 0, bool no_calcs = false, string custom_spell_name="");