Skip to content

Commit

Permalink
fix: crash in ranged accuracy test related to dead NPC cleanup (#3309)
Browse files Browse the repository at this point in the history
Use weak_ptr for killer pointer
  • Loading branch information
olanti-p authored Oct 31, 2023
1 parent 20074e5 commit 55c436a
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8525,7 +8525,7 @@ void Character::apply_damage( Creature *source, bodypart_id hurt, int dam,

if( is_dead_state() ) {
// if the player killed himself, add it to the kill count list
if( !is_npc() && !killer && source == g->u.as_character() ) {
if( !is_npc() && !get_killer() && source == g->u.as_character() ) {
g->events().send<event_type::character_kills_character>( get_player_character().getID(), getID(),
get_name() );
}
Expand Down
10 changes: 5 additions & 5 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Creature::Creature()
{
moves = 0;
pain = 0;
killer = nullptr;
killer.reset();
speed_base = 100;
underwater = false;

Expand Down Expand Up @@ -1466,15 +1466,15 @@ bool Creature::in_sleep_state() const
*/
Creature *Creature::get_killer() const
{
return killer;
return killer.lock().get();
}

void Creature::set_killer( Creature *const killer )
void Creature::set_killer( Creature *nkiller )
{
// Only the first killer will be stored, calling set_killer again with a different
// killer would mean it's called on a dead creature and therefore ignored.
if( killer != nullptr && !killer->is_fake() && this->killer == nullptr ) {
this->killer = killer;
if( !get_killer() && nkiller && !nkiller->is_fake() ) {
killer = g->shared_from( *nkiller );
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "units.h"
#include "cached_options.h"
#include "enums.h"
#include "memory_fast.h"

enum game_message_type : int;
class nc_color;
Expand Down Expand Up @@ -809,8 +810,8 @@ class Creature
effects_map get_all_effects() const;

protected:
Creature *killer = nullptr; // whoever killed us. this should be NULL unless we are dead
void set_killer( Creature *killer );
weak_ptr_fast<Creature> killer; // whoever killed us. this should be NULL unless we are dead
void set_killer( Creature *nkiller );

/**
* Processes one effect on the Creature.
Expand Down
8 changes: 4 additions & 4 deletions src/npc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2517,11 +2517,11 @@ void npc::die( Creature *nkiller )
add_msg( _( "%s dies!" ), name );
}

if( Character *ch = dynamic_cast<Character *>( killer ) ) {
if( Character *ch = dynamic_cast<Character *>( get_killer() ) ) {
g->events().send<event_type::character_kills_character>( ch->getID(), getID(), get_name() );
}

if( killer == &g->u && ( !guaranteed_hostile() || hit_by_player ) ) {
if( get_killer() == &g->u && ( !guaranteed_hostile() || hit_by_player ) ) {
bool cannibal = g->u.has_trait( trait_CANNIBAL );
bool psycho = g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait( trait_KILLER );
if( g->u.has_trait( trait_SAPIOVORE ) || psycho ) {
Expand All @@ -2533,14 +2533,14 @@ void npc::die( Creature *nkiller )
}
}

if( killer == &g->u && g->u.has_trait( trait_KILLER ) ) {
if( get_killer() == &g->u && g->u.has_trait( trait_KILLER ) ) {
const translation snip = SNIPPET.random_from_category( "killer_on_kill" ).value_or( translation() );
g->u.add_msg_if_player( m_good, "%s", snip );
g->u.add_morale( MORALE_KILLER_HAS_KILLED, 5, 10, 6_hours, 4_hours );
g->u.rem_morale( MORALE_KILLER_NEED_TO_KILL );
}

if( killer == &g->u && g->u.has_trait( trait_PROF_FERAL ) ) {
if( get_killer() == &g->u && g->u.has_trait( trait_PROF_FERAL ) ) {
if( !g->u.has_effect( effect_feral_killed_recently ) ) {
g->u.add_msg_if_player( m_good, _( "The voices in your head quiet down a bit." ) );
}
Expand Down
2 changes: 1 addition & 1 deletion src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3081,7 +3081,7 @@ void Creature::load( const JsonObject &jsin )
jsin.read( "moves", moves );
jsin.read( "pain", pain );

killer = nullptr; // see Creature::load
killer.reset();

if( jsin.has_object( "effects" ) ) {
// Because JSON requires string keys we need to convert back to our bp keys
Expand Down

0 comments on commit 55c436a

Please sign in to comment.