diff --git a/data/json/ammo_effects.json b/data/json/ammo_effects.json index 6bc29a7ee0b92..e2c4ee3f7b9f3 100644 --- a/data/json/ammo_effects.json +++ b/data/json/ammo_effects.json @@ -89,7 +89,8 @@ { "id": "PLASMA", "type": "ammo_effect", - "aoe": { "field_type": "fd_plasma", "intensity_min": 2, "intensity_max": 3, "chance": 2 } + "aoe": { "field_type": "fd_plasma", "intensity_min": 2, "intensity_max": 3, "chance": 2 }, + "trail": { "field_type": "fd_plasma", "intensity_min": 1, "intensity_max": 2, "chance": 50 } }, { "id": "EXPLOSIVE_HUGE", @@ -150,5 +151,45 @@ "id": "EMP", "type": "ammo_effect", "do_emp_blast": true + }, + { + "id": "TRAIL", + "type": "ammo_effect", + "trail": { "field_type": "fd_smoke", "intensity_min": 1, "intensity_max": 2, "chance": 75 } + }, + { + "id": "STREAM", + "type": "ammo_effect", + "trail": { "field_type": "fd_fire", "intensity_min": 1, "intensity_max": 2, "chance": 66 } + }, + { + "id": "STREAM_BIG", + "type": "ammo_effect", + "trail": { "field_type": "fd_fire", "intensity_min": 2, "intensity_max": 2, "chance": 75 } + }, + { + "id": "STREAM_GAS_FUNGICIDAL", + "type": "ammo_effect", + "trail": { "field_type": "fd_fungicidal_gas", "intensity_min": 1, "intensity_max": 2, "chance": 66 } + }, + { + "id": "STREAM_GAS_INSCENTICIDAL", + "type": "ammo_effect", + "trail": { "field_type": "fd_insecticidal_gas", "intensity_min": 1, "intensity_max": 2, "chance": 66 } + }, + { + "id": "LIGHTNING", + "type": "ammo_effect", + "trail": { "field_type": "fd_electricity", "intensity_min": 2, "intensity_max": 3 } + }, + { + "id": "LASER", + "type": "ammo_effect", + "trail": { "field_type": "fd_laser", "intensity_min": 2, "intensity_max": 2 } + }, + { + "id": "DRAW_LASER_BEAM", + "type": "ammo_effect", + "trail": { "field_type": "fd_laser", "intensity_min": 2, "intensity_max": 2 } } ] diff --git a/src/ammo_effect.cpp b/src/ammo_effect.cpp index edc8a5a74d244..15c5488b65f7c 100644 --- a/src/ammo_effect.cpp +++ b/src/ammo_effect.cpp @@ -73,6 +73,13 @@ void ammo_effect::load( const JsonObject &jo, const std::string & ) optional( joa, was_loaded, "check_sees", aoe_check_sees, false ); optional( joa, was_loaded, "check_sees_radius", aoe_check_sees_radius, 0 ); } + if( jo.has_member( "trail" ) ) { + JsonObject joa = jo.get_object( "trail" ); + optional( joa, was_loaded, "field_type", trail_field_type_name, "fd_null" ); + optional( joa, was_loaded, "intensity_min", trail_intensity_min, 0 ); + optional( joa, was_loaded, "intensity_max", trail_intensity_max, 0 ); + optional( joa, was_loaded, "chance", trail_chance, 1 ); + } if( jo.has_member( "explosion" ) ) { JsonObject joe = jo.get_object( "explosion" ); aoe_explosion_data = load_explosion_data( joe ); @@ -85,6 +92,7 @@ void ammo_effect::finalize() { for( const ammo_effect &ae : ammo_effects::get_all() ) { const_cast( ae ).aoe_field_type = field_type_id( ae.aoe_field_type_name ); + const_cast( ae ).trail_field_type = field_type_id( ae.trail_field_type_name ); } } @@ -112,6 +120,19 @@ void ammo_effect::check() const if( aoe_intensity_max < aoe_intensity_min ) { debugmsg( "Maximum intensity must be greater than or equal to minimum intensity" ); } + if( !trail_field_type.is_valid() ) { + debugmsg( "No such field type %s", trail_field_type_name ); + } + if( trail_chance > 100 || trail_chance <= 0 ) { + debugmsg( "Field chance divisor cannot be negative" ); + debugmsg( "Field chance of %s out of range (%d of min 1 max 100)", id.c_str(), trail_chance ); + } + if( trail_intensity_min < 0 ) { + debugmsg( "Field intensity cannot be negative" ); + } + if( trail_intensity_max < trail_intensity_min ) { + debugmsg( "Maximum intensity must be greater than or equal to minimum intensity" ); + } } size_t ammo_effect::count() diff --git a/src/ammo_effect.h b/src/ammo_effect.h index 50b13d53a096a..4cce863f77a0a 100644 --- a/src/ammo_effect.h +++ b/src/ammo_effect.h @@ -35,6 +35,13 @@ struct ammo_effect { bool do_flashbang = false; bool do_emp_blast = false; + field_type_id trail_field_type = fd_null; + /** used during JSON loading only */ + std::string trail_field_type_name = "fd_null"; + int trail_intensity_min = 0; + int trail_intensity_max = 0; + int trail_chance = 100; + public: // Used by generic_factory string_id id; diff --git a/src/map.cpp b/src/map.cpp index 55a5b8e260849..8d6fa50fb8c65 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -11,6 +11,7 @@ #include #include "ammo.h" +#include "ammo_effect.h" #include "artifact.h" #include "avatar.h" #include "calendar.h" @@ -3550,36 +3551,12 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) dam = 0; } - if( ammo_effects.count( "TRAIL" ) && !one_in( 4 ) ) { - add_field( p, fd_smoke, rng( 1, 2 ) ); - } - - if( ammo_effects.count( "STREAM" ) && !one_in( 3 ) ) { - add_field( p, fd_fire, rng( 1, 2 ) ); - } - - if( ammo_effects.count( "STREAM_GAS_FUNGICIDAL" ) && !one_in( 3 ) ) { - add_field( p, fd_fungicidal_gas, rng( 1, 2 ) ); - } - - if( ammo_effects.count( "STREAM_GAS_INSCENTICIDAL" ) && !one_in( 3 ) ) { - add_field( p, fd_insecticidal_gas, rng( 1, 2 ) ); - } - - if( ammo_effects.count( "STREAM_BIG" ) && !one_in( 4 ) ) { - add_field( p, fd_fire, 2 ); - } - - if( ammo_effects.count( "LIGHTNING" ) ) { - add_field( p, fd_electricity, rng( 2, 3 ) ); - } - - if( ammo_effects.count( "PLASMA" ) && one_in( 2 ) ) { - add_field( p, fd_plasma, rng( 1, 2 ) ); - } - - if( ammo_effects.count( "LASER" ) || ammo_effects.count( "DRAW_LASER_BEAM" ) ) { - add_field( p, fd_laser, 2 ); + for( const ammo_effect &ae : ammo_effects::get_all() ) { + if( ammo_effects.count( ae.id.str() ) > 0 ) { + if( x_in_y( ae.trail_chance, 100 ) ) { + g->m.add_field( p, ae.trail_field_type, rng( ae.trail_intensity_min, ae.trail_intensity_max ) ); + } + } } dam = std::max( 0.0f, dam );