Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing damage sources kills and suicide to kills list #2092

Merged
4 changes: 2 additions & 2 deletions src/ballistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,10 +472,10 @@ dealt_projectile_attack projectile_attack( const projectile &proj_arg, const tri

drop_or_embed_projectile( attack );

apply_ammo_effects( tp, proj.get_ammo_effects() );
apply_ammo_effects( tp, proj.get_ammo_effects(), origin );
const auto &expl = proj.get_custom_explosion();
if( expl ) {
explosion_handler::explosion( tp, expl );
explosion_handler::explosion( tp, expl, origin );
}

// TODO: Move this outside now that we have hit point in return values?
Expand Down
4 changes: 2 additions & 2 deletions src/bionics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,8 +906,8 @@ bool Character::activate_bionic( int b, bool eff_only )
sw.force = 4;
sw.stun = 2;
sw.dam_mult = 8;

explosion_handler::shockwave( pos(), sw, "explosion" );
// affects_player is always false, so assuming the player is always the source of this
explosion_handler::shockwave( pos(), sw, "explosion", &get_player_character() );
add_msg_if_player( m_neutral, _( "You unleash a powerful shockwave!" ) );
mod_moves( -100 );
} else if( bio.id == bio_meteorologist ) {
Expand Down
13 changes: 9 additions & 4 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8444,6 +8444,15 @@ void Character::apply_damage( Creature *source, bodypart_id hurt, int dam,
on_hurt( source );
}

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() ) {
g->events().send<event_type::character_kills_character>( get_player_character().getID(), getID(),
get_name() );
}
set_killer( source );
}

if( !bypass_med ) {
// remove healing effects if damaged
int remove_med = roll_remainder( dam / 5.0f );
Expand Down Expand Up @@ -8707,10 +8716,6 @@ void Character::on_hurt( Creature *source, bool disturb /*= true*/ )
}
}
}

if( is_dead_state() ) {
set_killer( source );
}
}

bool Character::crossed_threshold() const
Expand Down
10 changes: 6 additions & 4 deletions src/computer_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ void computer_session::action_srcf_seal()
for( const tripoint &p : here.points_on_zlevel() ) {
if( here.ter( p ) == t_elevator || here.ter( p ) == t_vat ) {
here.make_rubble( p, f_rubble_rock, true );
explosion_handler::explosion( p, 40, 0.7, true );
explosion_handler::explosion( p, &g->u, 40, 0.7, true );
}
if( here.ter( p ) == t_wall_glass ) {
here.make_rubble( p, f_rubble_rock, true );
Expand All @@ -945,7 +945,7 @@ void computer_session::action_srcf_seal()
}
if( here.ter( p ) == t_sewage_pump ) {
here.make_rubble( p, f_rubble_rock, true );
explosion_handler::explosion( p, 50, 0.7, true );
explosion_handler::explosion( p, &g->u, 50, 0.7, true );
}
}
comp.options.clear(); // Disable the terminal.
Expand Down Expand Up @@ -1042,7 +1042,7 @@ void computer_session::action_irradiator()
// critical failure - radiation spike sets off electronic detonators
if( it->typeId() == itype_mininuke || it->typeId() == itype_mininuke_act ||
it->typeId() == itype_c4 ) {
explosion_handler::explosion( dest, 40 );
explosion_handler::explosion( dest, &g->u, 40 );
reset_terminal();
print_error( _( "WARNING [409]: Primary sensors offline!" ) );
print_error( _( " >> Initialize secondary sensors: Geiger profiling…" ) );
Expand Down Expand Up @@ -1367,7 +1367,7 @@ void computer_session::failure_pump_explode()
for( const tripoint &p : here.points_on_zlevel() ) {
if( here.ter( p ) == t_sewage_pump ) {
here.make_rubble( p );
explosion_handler::explosion( p, 10 );
explosion_handler::explosion( p, nullptr, 10 );
}
}
}
Expand Down Expand Up @@ -1408,9 +1408,11 @@ void computer_session::failure_amigara()
g->timed_events.add( TIMED_EVENT_AMIGARA, calendar::turn + 30_seconds );
g->u.add_effect( effect_amigara, 2_minutes );
explosion_handler::explosion( tripoint( rng( 0, MAPSIZE_X ), rng( 0, MAPSIZE_Y ), g->get_levz() ),
nullptr,
10,
0.7, false, 10 );
explosion_handler::explosion( tripoint( rng( 0, MAPSIZE_X ), rng( 0, MAPSIZE_Y ), g->get_levz() ),
nullptr,
10,
0.7, false, 10 );
comp.remove_option( COMPACT_AMIGARA_START );
Expand Down
53 changes: 28 additions & 25 deletions src/explosion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ namespace explosion_handler
{
// (C1001) Compiler Internal Error on Visual Studio 2015 with Update 2
static std::map<const Creature *, int> do_blast( const tripoint &p, const float power,
const float radius, const bool fire )
const float radius, const bool fire, Creature *source )
{
const float tile_dist = 1.0f;
const float diag_dist = trigdist ? M_SQRT2 * tile_dist : 1.0f * tile_dist;
Expand Down Expand Up @@ -296,10 +296,9 @@ static std::map<const Creature *, int> do_blast( const tripoint &p, const float

player *pl = dynamic_cast<player *>( critter );
if( pl == nullptr ) {
// TODO: player's fault?
const double dmg = std::max( force - critter->get_armor_bash( bodypart_id( "torso" ) ) / 3.0, 0.0 );
const int actual_dmg = rng_float( dmg, dmg * 2 );
critter->apply_damage( nullptr, bodypart_id( "torso" ), actual_dmg );
critter->apply_damage( source, bodypart_id( "torso" ), actual_dmg );
critter->check_dead_state();
blasted[critter] = actual_dmg;
continue;
Expand Down Expand Up @@ -330,7 +329,7 @@ static std::map<const Creature *, int> do_blast( const tripoint &p, const float
const int part_dam = rng( force * blp.low_mul, force * blp.high_mul );
const std::string hit_part_name = body_part_name_accusative( blp.bp->token );
const auto dmg_instance = damage_instance( DT_BASH, part_dam, 0, blp.armor_mul );
const auto result = pl->deal_damage( nullptr, blp.bp, dmg_instance );
const auto result = pl->deal_damage( source, blp.bp, dmg_instance );
const int res_dmg = result.total_damage();

add_msg( m_debug, "%s for %d raw, %d actual", hit_part_name, part_dam, res_dmg );
Expand All @@ -345,7 +344,7 @@ static std::map<const Creature *, int> do_blast( const tripoint &p, const float

static std::map<const Creature *, int> do_blast_new( const tripoint &blast_center,
const float raw_blast_force,
const float raw_blast_radius )
const float raw_blast_radius, Creature *source )
{
/*
Explosions are completed in 3 stages.
Expand Down Expand Up @@ -511,15 +510,15 @@ static std::map<const Creature *, int> do_blast_new( const tripoint &blast_cente
const int part_dam = rng( blast_force * blast_part.low_mul, blast_force * blast_part.high_mul );
const std::string hit_part_name = body_part_name_accusative( blast_part.bp->token );
const auto dmg_instance = damage_instance( DT_BASH, part_dam, 0, blast_part.armor_mul );
const auto result = player_ptr->deal_damage( nullptr, blast_part.bp, dmg_instance );
const auto result = player_ptr->deal_damage( source, blast_part.bp, dmg_instance );
const int res_dmg = result.total_damage();

if( res_dmg > 0 ) {
blasted[critter] += res_dmg;
}
}
} else {
critter->deal_damage( nullptr, bodypart_id( "torso" ), shockwave_dmg );
critter->deal_damage( source, bodypart_id( "torso" ), shockwave_dmg );
critter->check_dead_state();
blasted[critter] = blast_force;
}
Expand Down Expand Up @@ -609,7 +608,8 @@ static std::map<const Creature *, int> do_blast_new( const tripoint &blast_cente
}


static std::map<const Creature *, int> shrapnel( const tripoint &src, const projectile &fragment )
static std::map<const Creature *, int> shrapnel( const tripoint &src, const projectile &fragment,
Creature *source )
{
std::map<const Creature *, int> damaged;

Expand Down Expand Up @@ -668,13 +668,13 @@ static std::map<const Creature *, int> shrapnel( const tripoint &src, const proj
// Halve damage to be closer to what monsters take
damage_instance half_impact = proj.impact;
half_impact.mult_damage( 0.5f );
dealt_damage_instance dealt = critter->deal_damage( nullptr, bp, proj.impact );
dealt_damage_instance dealt = critter->deal_damage( source, bp, proj.impact );
if( dealt.total_damage() > 0 ) {
damage_taken += dealt.total_damage();
}
}
} else {
dealt_damage_instance dealt = critter->deal_damage( nullptr, bps[0], proj.impact );
dealt_damage_instance dealt = critter->deal_damage( source, bps[0], proj.impact );
if( dealt.total_damage() > 0 ) {
damage_taken += dealt.total_damage();
}
Expand All @@ -694,7 +694,8 @@ static std::map<const Creature *, int> shrapnel( const tripoint &src, const proj
return damaged;
}

void explosion( const tripoint &p, float power, float factor, bool fire, int legacy_casing_mass,
void explosion( const tripoint &p, Creature *source, float power, float factor, bool fire,
int legacy_casing_mass,
float )
{
if( factor >= 1.0f ) {
Expand All @@ -707,12 +708,12 @@ void explosion( const tripoint &p, float power, float factor, bool fire, int leg
if( legacy_casing_mass > 0 ) {
data.fragment = explosion_handler::shrapnel_from_legacy( power, data.radius );
}
explosion( p, data );
explosion( p, data, source );
}

void explosion( const tripoint &p, const explosion_data &ex )
void explosion( const tripoint &p, const explosion_data &ex, Creature *source )
{
queued_explosion qe( p, ExplosionType::Regular );
queued_explosion qe( p, ExplosionType::Regular, source );
qe.exp_data = ex;
get_explosion_queue().add( std::move( qe ) );
}
Expand All @@ -737,14 +738,14 @@ void explosion_funcs::regular( const queued_explosion &qe )
std::map<const Creature *, int> damaged_by_shrapnel;
const auto &shr = ex.fragment;
if( shr ) {
damaged_by_shrapnel = shrapnel( p, shr.value() );
damaged_by_shrapnel = shrapnel( p, shr.value(), qe.source );
}

if( ex.radius >= 0.0f && ex.damage > 0.0f ) {
if( get_option<bool>( "NEW_EXPLOSIONS" ) && !ex.fire ) {
damaged_by_blast = do_blast_new( p, ex.damage, ex.radius );
damaged_by_blast = do_blast_new( p, ex.damage, ex.radius, qe.source );
} else {
damaged_by_blast = do_blast( p, ex.damage, ex.radius, ex.fire );
damaged_by_blast = do_blast( p, ex.damage, ex.radius, ex.fire, qe.source );
}
}

Expand Down Expand Up @@ -804,7 +805,8 @@ void explosion_funcs::regular( const queued_explosion &qe )

void flashbang( const tripoint &p, bool player_immune, const std::string &exp_name )
{
queued_explosion qe( p, ExplosionType::Flashbang );
// flashbangs cannot kill, so skip the source
queued_explosion qe( p, ExplosionType::Flashbang, nullptr );
qe.affects_player = !player_immune;
qe.graphics_name = exp_name;
get_explosion_queue().add( std::move( qe ) );
Expand Down Expand Up @@ -861,9 +863,10 @@ void explosion_funcs::flashbang( const queued_explosion &qe )
// TODO: Blind/deafen NPC
}

void shockwave( const tripoint &p, const shockwave_data &sw, const std::string &exp_name )
void shockwave( const tripoint &p, const shockwave_data &sw, const std::string &exp_name,
Creature *source )
{
queued_explosion qe( p, ExplosionType::Shockwave );
queued_explosion qe( p, ExplosionType::Shockwave, source );
qe.swave_data = sw;
qe.graphics_name = exp_name;
get_explosion_queue().add( std::move( qe ) );
Expand All @@ -886,7 +889,7 @@ void explosion_funcs::shockwave( const queued_explosion &qe )
}
if( rl_dist( critter.pos(), p ) <= sw.radius ) {
add_msg( _( "%s is caught in the shockwave!" ), critter.name() );
g->knockback( p, critter.pos(), sw.force, sw.stun, sw.dam_mult );
g->knockback( p, critter.pos(), sw.force, sw.stun, sw.dam_mult, qe.source );
}
}
// TODO: combine the two loops and the case for g->u using all_creatures()
Expand All @@ -896,14 +899,14 @@ void explosion_funcs::shockwave( const queued_explosion &qe )
}
if( rl_dist( guy.pos(), p ) <= sw.radius ) {
add_msg( _( "%s is caught in the shockwave!" ), guy.name );
g->knockback( p, guy.pos(), sw.force, sw.stun, sw.dam_mult );
g->knockback( p, guy.pos(), sw.force, sw.stun, sw.dam_mult, qe.source );
}
}
if( rl_dist( g->u.pos(), p ) <= sw.radius && sw.affects_player &&
( !g->u.has_trait( trait_LEG_TENT_BRACE ) || g->u.footwear_factor() == 1 ||
( g->u.footwear_factor() == .5 && one_in( 2 ) ) ) ) {
add_msg( m_bad, _( "You're caught in the shockwave!" ) );
g->knockback( p, g->u.pos(), sw.force, sw.stun, sw.dam_mult );
g->knockback( p, g->u.pos(), sw.force, sw.stun, sw.dam_mult, qe.source );
}
}

Expand Down Expand Up @@ -1048,7 +1051,7 @@ void emp_blast( const tripoint &p )

void resonance_cascade( const tripoint &p )
{
get_explosion_queue().add( queued_explosion( p, ExplosionType::ResonanceCascade ) );
get_explosion_queue().add( queued_explosion( p, ExplosionType::ResonanceCascade, nullptr ) );
}

void explosion_funcs::resonance_cascade( const queued_explosion &qe )
Expand Down Expand Up @@ -1138,7 +1141,7 @@ void explosion_funcs::resonance_cascade( const queued_explosion &qe )
ex.radius = 1;
ex.damage = rng( 1, 10 );
ex.fire = one_in( 4 );
explosion( dest, ex );
explosion( dest, ex, qe.source );
break;
}
default:
Expand Down
7 changes: 4 additions & 3 deletions src/explosion.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ namespace explosion_handler
* If casing mass > 0, shrapnel is produced.
*/
void explosion(
const tripoint &p, float power, float factor = 0.8f,
const tripoint &p, Creature *source, float power, float factor = 0.8f,
bool fire = false, int legacy_casing_mass = 0, float legacy_frag_mass = 0.05
);

void explosion( const tripoint &p, const explosion_data &ex );
void explosion( const tripoint &p, const explosion_data &ex, Creature *source );

constexpr float power_to_dmg_mult = 2.0f / 15.0f;

Expand All @@ -57,7 +57,8 @@ void scrambler_blast( const tripoint &p );
/** Triggers an EMP blast at p. */
void emp_blast( const tripoint &p );
/** Shockwave applies knockback with given parameters to all targets within radius of p. */
void shockwave( const tripoint &p, const shockwave_data &sw, const std::string &exp_name );
void shockwave( const tripoint &p, const shockwave_data &sw, const std::string &exp_name,
Creature *source );

projectile shrapnel_from_legacy( int power, float blast_radius );
float blast_radius_from_legacy( int power, float distance_factor );
Expand Down
5 changes: 4 additions & 1 deletion src/explosion_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ enum class ExplosionType {

struct queued_explosion {
queued_explosion() = default;
queued_explosion( const tripoint &pos, ExplosionType type ) : pos( pos ), type( type ) {}
queued_explosion( const tripoint &pos, ExplosionType type,
Creature *source ) : pos( pos ), type( type ), source( source ) {}

/** Origin */
tripoint pos;
Expand All @@ -34,6 +35,8 @@ struct queued_explosion {
std::string graphics_name;
/** Whether it affects player */
bool affects_player = false;
/** Who's responsible of the explosion */
Creature *source;
};

namespace explosion_funcs
Expand Down
Loading