diff --git a/data/json/ammo_effects.json b/data/json/ammo_effects.json new file mode 100644 index 0000000000000..6bc29a7ee0b92 --- /dev/null +++ b/data/json/ammo_effects.json @@ -0,0 +1,154 @@ +[ + { + "id": "AE_NULL", + "type": "ammo_effect", + "aoe": { + "field_type": "fd_null", + "intensity_min": 0, + "intensity_max": 0, + "radius": 0, + "radius_z": 0, + "chance": 1, + "size": 0, + "check_passable": false, + "check_sees": false, + "check_sees_radius": 0 + }, + "explosion": { + "power": 0, + "distance_factor": 0.8, + "fire": false, + "shrapnel": { "casing_mass": 0, "fragment_mass": 0.005, "recovery": 0, "drop": "null" } + }, + "do_flashbang": false, + "do_emp_blast": false + }, + { + "id": "FLAME", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fire", "intensity_min": 1, "intensity_max": 1, "size": 3 } + }, + { + "id": "NAPALM", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fire", "intensity_min": 1, "intensity_max": 1, "size": 3 }, + "explosion": { "power": 60, "distance_factor": 0.7, "fire": true } + }, + { + "id": "NAPALM_BIG", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fire", "intensity_min": 1, "intensity_max": 1, "radius": 3, "size": 4 }, + "explosion": { "power": 360, "distance_factor": 0.8, "fire": true } + }, + { + "id": "PYROPHORIC", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fire", "intensity_min": 2, "intensity_max": 2, "radius": 3 }, + "explosion": { "power": 360, "distance_factor": 0.8, "fire": true } + }, + { + "id": "ACIDBOMB", + "type": "ammo_effect", + "aoe": { "field_type": "fd_acid", "intensity_min": 3, "intensity_max": 3 } + }, + { + "id": "TOXICGAS", + "type": "ammo_effect", + "aoe": { "field_type": "fd_toxic_gas", "intensity_min": 3, "intensity_max": 3 } + }, + { + "id": "GAS_FUNGICIDAL", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fungicidal_gas", "intensity_min": 3, "intensity_max": 3 } + }, + { + "id": "GAS_INSECTICIDAL", + "type": "ammo_effect", + "aoe": { "field_type": "fd_insecticidal_gas", "intensity_min": 3, "intensity_max": 3 } + }, + { + "id": "SMOKE", + "type": "ammo_effect", + "aoe": { "field_type": "fd_smoke", "intensity_min": 3, "intensity_max": 3 } + }, + { + "id": "SMOKE_BIG", + "type": "ammo_effect", + "aoe": { "field_type": "fd_smoke", "intensity_min": 3, "intensity_max": 3, "radius": 6 } + }, + { + "id": "FLARE", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fire", "intensity_min": 1, "intensity_max": 1 } + }, + { + "id": "LIGHTNING", + "type": "ammo_effect", + "aoe": { "field_type": "fd_electricity", "intensity_min": 3, "intensity_max": 3 } + }, + { + "id": "PLASMA", + "type": "ammo_effect", + "aoe": { "field_type": "fd_plasma", "intensity_min": 2, "intensity_max": 3, "chance": 2 } + }, + { + "id": "EXPLOSIVE_HUGE", + "type": "ammo_effect", + "explosion": { "power": 1200 } + }, + { + "id": "EXPLOSIVE_BIG", + "type": "ammo_effect", + "explosion": { "power": 600 } + }, + { + "id": "EXPLOSIVE", + "type": "ammo_effect", + "explosion": { "power": 360 } + }, + { + "id": "EXPLOSIVE_SMALL", + "type": "ammo_effect", + "explosion": { "power": 360, "distance_factor": 0.4 } + }, + { + "id": "EXPLOSIVE_RAUFOSS", + "type": "ammo_effect", + "explosion": { + "power": 2.4, + "distance_factor": 0.6, + "fire": true, + "shrapnel": { "casing_mass": 28, "fragment_mass": 1.4, "recovery": 0, "drop": "null" } + } + }, + { + "id": "FRAG", + "type": "ammo_effect", + "explosion": { "power": 185, "shrapnel": { "casing_mass": 212, "fragment_mass": 0.05 } } + }, + { + "id": "MININUKE_MOD", + "type": "ammo_effect", + "aoe": { + "field_type": "fd_nuke_gas", + "intensity_min": 3, + "intensity_max": 3, + "radius": 18, + "size": 1, + "check_passable": true, + "check_sees": true, + "check_sees_radius": 3 + }, + "explosion": { "power": 72000000 } + }, + { + "id": "FLASHBANG", + "type": "ammo_effect", + "do_flashbang": true + }, + { + "id": "EMP", + "type": "ammo_effect", + "do_emp_blast": true + } +] diff --git a/data/json/items/classes/gun.json b/data/json/items/classes/gun.json index 64c8503cf63a2..35cf6d2f8c59e 100644 --- a/data/json/items/classes/gun.json +++ b/data/json/items/classes/gun.json @@ -16,7 +16,7 @@ "name": "base flamethrower", "skill": "launcher", "ammo": "flammable", - "ammo_effects": [ "NO_BOOM", "FLARE" ], + "ammo_effects": [ "FLARE" ], "reload": 4, "flags": [ "FIRE_100", "NEVER_JAMS", "FIRESTARTER" ], "faults": [ ] diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index a86e1ba5f0257..0b39b68abb37d 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -705,7 +705,6 @@ List of known flags, used in both `terrain.json` and `furniture.json`. - ```MECH_WEAPON``` A built-in mech weapon, cannot be removed or have mods added / removed. - ```MOUNTED_GUN``` Gun can only be used on terrain / furniture with the "MOUNTABLE" flag. - ```NEVER_JAMS``` Never malfunctions. -- ```NO_BOOM``` Cancels the ammo effect "FLAME". - ```NO_UNLOAD``` Cannot be unloaded. - ```PRIMITIVE_RANGED_WEAPON``` Allows using non-gunsmith tools to repair it (but not reinforce). - ```PUMP_ACTION``` Gun has a rails on its pump action, allowing to install only mods with PUMP_RAIL_COMPATIBLE flag on underbarrel slot. diff --git a/src/ammo_effect.cpp b/src/ammo_effect.cpp new file mode 100644 index 0000000000000..edc8a5a74d244 --- /dev/null +++ b/src/ammo_effect.cpp @@ -0,0 +1,150 @@ +#include "ammo_effect.h" + +#include "generic_factory.h" +#include "json.h" + +namespace +{ + +generic_factory all_ammo_effects( "ammo effects" ); + +} // namespace + +/** @relates int_id */ +template<> +bool int_id::is_valid() const +{ + return all_ammo_effects.is_valid( *this ); +} + +/** @relates int_id */ +template<> +const ammo_effect &int_id::obj() const +{ + return all_ammo_effects.obj( *this ); +} + +/** @relates int_id */ +template<> +const string_id &int_id::id() const +{ + return all_ammo_effects.convert( *this ); +} + +/** @relates string_id */ +template<> +bool string_id::is_valid() const +{ + return all_ammo_effects.is_valid( *this ); +} + +/** @relates string_id */ +template<> +const ammo_effect &string_id::obj() const +{ + return all_ammo_effects.obj( *this ); +} + +/** @relates string_id */ +template<> +int_id string_id::id() const +{ + return all_ammo_effects.convert( *this, AE_NULL ); +} + +/** @relates int_id */ +template<> +int_id::int_id( const string_id &id ) : _id( id.id() ) +{ +} + +void ammo_effect::load( const JsonObject &jo, const std::string & ) +{ + if( jo.has_member( "aoe" ) ) { + JsonObject joa = jo.get_object( "aoe" ); + optional( joa, was_loaded, "field_type", aoe_field_type_name, "fd_null" ); + optional( joa, was_loaded, "intensity_min", aoe_intensity_min, 0 ); + optional( joa, was_loaded, "intensity_max", aoe_intensity_max, 0 ); + optional( joa, was_loaded, "radius", aoe_radius, 1 ); + optional( joa, was_loaded, "radius_z", aoe_radius_z, 0 ); + optional( joa, was_loaded, "chance", aoe_chance, 1 ); + optional( joa, was_loaded, "size", aoe_size, 0 ); + optional( joa, was_loaded, "check_passable", aoe_check_passable, false ); + 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( "explosion" ) ) { + JsonObject joe = jo.get_object( "explosion" ); + aoe_explosion_data = load_explosion_data( joe ); + } + optional( jo, was_loaded, "do_flashbang", do_flashbang, false ); + optional( jo, was_loaded, "do_emp_blast", do_emp_blast, false ); +} + +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 ); + } + +} + +void ammo_effect::check() const +{ + if( !aoe_field_type.is_valid() ) { + debugmsg( "No such field type %s", aoe_field_type_name ); + } + if( aoe_check_sees_radius < 0 ) { + debugmsg( "Value of aoe_check_sees_radius cannot be negative" ); + } + if( aoe_size < 0 ) { + debugmsg( "Value of aoe_size cannot be negative" ); + } + if( aoe_chance < 0 ) { + debugmsg( "Field chance divisor cannot be negative" ); + } + if( aoe_radius_z < 0 || aoe_radius < 0 ) { + debugmsg( "Radius values cannot be negative" ); + } + if( aoe_intensity_min < 0 ) { + debugmsg( "Field intensity cannot be negative" ); + } + if( aoe_intensity_max < aoe_intensity_min ) { + debugmsg( "Maximum intensity must be greater than or equal to minimum intensity" ); + } +} + +size_t ammo_effect::count() +{ + return all_ammo_effects.size(); +} + +void ammo_effects::load( const JsonObject &jo, const std::string &src ) +{ + all_ammo_effects.load( jo, src ); +} + +void ammo_effects::finalize_all() +{ + all_ammo_effects.finalize(); + for( const ammo_effect &ae : all_ammo_effects.get_all() ) { + const_cast( ae ).finalize(); + } +} + +void ammo_effects::check_consistency() +{ + all_ammo_effects.check(); +} + +void ammo_effects::reset() +{ + all_ammo_effects.reset(); +} + +const std::vector &ammo_effects::get_all() +{ + return all_ammo_effects.get_all(); +} + +ammo_effect_id AE_NULL; diff --git a/src/ammo_effect.h b/src/ammo_effect.h new file mode 100644 index 0000000000000..50b13d53a096a --- /dev/null +++ b/src/ammo_effect.h @@ -0,0 +1,61 @@ +#pragma once +#ifndef AMMO_EFFECT_H +#define AMMO_EFFECT_H + +#include +#include + +#include "explosion.h" +#include "field_type.h" +#include "type_id.h" + +class JsonObject; + +struct ammo_effect { + public: + void load( const JsonObject &jo, const std::string &src ); + void finalize(); + void check() const; + + public: + field_type_id aoe_field_type = fd_null; + /** used during JSON loading only */ + std::string aoe_field_type_name = "fd_null"; + int aoe_intensity_min = 0; + int aoe_intensity_max = 0; + int aoe_radius = 1; + int aoe_radius_z = 0; + int aoe_chance = 1; + int aoe_size = 0; + explosion_data aoe_explosion_data; + bool aoe_check_passable = false; + + bool aoe_check_sees = false; + int aoe_check_sees_radius = 0; + bool do_flashbang = false; + bool do_emp_blast = false; + + public: + // Used by generic_factory + string_id id; + bool was_loaded = false; + + public: + static size_t count(); +}; + +namespace ammo_effects +{ + +void load( const JsonObject &jo, const std::string &src ); +void finalize_all(); +void check_consistency(); +void reset(); + +const std::vector &get_all(); + +} // namespace ammo_effects + +extern ammo_effect_id AE_NULL; + +#endif diff --git a/src/creature.cpp b/src/creature.cpp index c3f49a6c13aad..8b1bdea6bc4dd 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -697,13 +697,7 @@ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack add_effect( effect_stunned, rng( 3_turns, 8_turns ) ); } } - if( proj.proj_effects.count( "FLAME" ) ) { - if( made_of( material_id( "veggy" ) ) || made_of_any( cmat_flammable ) ) { - add_effect( effect_onfire, rng( 8_turns, 20_turns ), bp_hit ); - } else if( made_of_any( cmat_flesh ) ) { - add_effect( effect_onfire, rng( 5_turns, 10_turns ), bp_hit ); - } - } else if( proj.proj_effects.count( "INCENDIARY" ) ) { + if( proj.proj_effects.count( "INCENDIARY" ) ) { if( made_of( material_id( "veggy" ) ) || made_of_any( cmat_flammable ) ) { add_effect( effect_onfire, rng( 2_turns, 6_turns ), bp_hit ); } else if( made_of_any( cmat_flesh ) && one_in( 4 ) ) { diff --git a/src/explosion.h b/src/explosion.h index 18897b2024d6d..7196eeb60cef9 100644 --- a/src/explosion.h +++ b/src/explosion.h @@ -17,6 +17,15 @@ struct shrapnel_data { // Percentage int recovery = 0; itype_id drop = "null"; + + shrapnel_data() {} + shrapnel_data( int casing_mass, float fragment_mass = 0.005, int recovery = 0, + itype_id drop = "null" ) + : casing_mass( casing_mass ) + , fragment_mass( fragment_mass ) + , recovery( recovery ) + , drop( drop ) { + } }; struct explosion_data { @@ -31,6 +40,15 @@ struct explosion_data { float power_at_range( float dist ) const; /** Returns the distance at which the power drops below 1. */ int safe_range() const; + + explosion_data() {} + explosion_data( float power, float distance_factor = 0.8f, bool fire = false, + shrapnel_data shrapnel = {} ) + : power( power ) + , distance_factor( distance_factor ) + , fire( fire ) + , shrapnel( shrapnel ) { + } }; // handles explosion related functions diff --git a/src/init.cpp b/src/init.cpp index 9ac4d539ec4fb..fb478db2507b5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -82,6 +82,7 @@ #include "construction_category.h" #include "overmap.h" #include "clothing_mod.h" +#include "ammo_effect.h" DynamicDataLoader::DynamicDataLoader() { @@ -190,6 +191,7 @@ void DynamicDataLoader::initialize() add( "json_flag", &json_flag::load ); add( "fault", &fault::load_fault ); add( "field_type", &field_types::load ); + add( "ammo_effect", &ammo_effects::load ); add( "emit", &emit::load_emit ); add( "activity_type", &activity_type::load ); add( "vitamin", &vitamin::load_vitamin ); @@ -471,6 +473,7 @@ void DynamicDataLoader::unload_data() requirement_data::reset(); vitamin::reset(); field_types::reset(); + ammo_effects::reset(); emit::reset(); activity_type::reset(); fault::reset(); @@ -554,6 +557,7 @@ void DynamicDataLoader::finalize_loaded_data( loading_ui &ui ) const std::vector entries = {{ { _( "Body parts" ), &body_part_struct::finalize_all }, { _( "Field types" ), &field_types::finalize_all }, + { _( "Ammo effects" ), &ammo_effects::finalize_all }, { _( "Emissions" ), &emit::finalize }, { _( "Items" ), []() @@ -633,6 +637,7 @@ void DynamicDataLoader::check_consistency( loading_ui &ui ) }, { _( "Vitamins" ), &vitamin::check_consistency }, { _( "Field types" ), &field_types::check_consistency }, + { _( "Ammo effects" ), &ammo_effects::check_consistency }, { _( "Emissions" ), &emit::check_consistency }, { _( "Activities" ), &activity_type::check_consistency }, { diff --git a/src/map.cpp b/src/map.cpp index f497e4eef5657..b7efa1e22139b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3359,7 +3359,7 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) g->timed_events.add( TIMED_EVENT_WANTED, calendar::turn + 30_minutes, 0, abs ); } - const bool inc = ( ammo_effects.count( "INCENDIARY" ) || ammo_effects.count( "FLAME" ) ); + const bool inc = ammo_effects.count( "INCENDIARY" ); if( const optional_vpart_position vp = veh_at( p ) ) { dam = vp->vehicle().damage( vp->part_index(), dam, inc ? DT_HEAT : DT_STAB, hit_items ); } diff --git a/src/projectile.cpp b/src/projectile.cpp index 46f1b00b770f1..ba229a8862206 100644 --- a/src/projectile.cpp +++ b/src/projectile.cpp @@ -3,6 +3,7 @@ #include #include +#include "ammo_effect.h" #include "explosion.h" #include "field.h" #include "game.h" @@ -91,153 +92,37 @@ void projectile::unset_custom_explosion() void apply_ammo_effects( const tripoint &p, const std::set &effects ) { - if( effects.count( "EXPLOSIVE_RAUFOSS" ) > 0 ) { - // TODO: Make this actually fill a ~4m radius circle with fire and 20 shrapnel bits. Or better, a 30 deg, 15m long arc. - explosion_handler::explosion( p, 2.4, 0.6, true, 28, 1.4 ); - } - - if( effects.count( "EXPLOSIVE_SMALL" ) > 0 ) { - // TODO: double-check if this is sensible. - explosion_handler::explosion( p, 360, 0.4 ); - } - - if( effects.count( "EXPLOSIVE" ) > 0 ) { - // TODO: double-check if this is sensible. - explosion_handler::explosion( p, 360 ); - } - - if( effects.count( "FRAG" ) > 0 ) { - // Same as a standard thrown frag grenade. - explosion_handler::explosion( p, 185, 0.8, false, 212, 0.05 ); - } - - if( effects.count( "NAPALM" ) > 0 ) { - explosion_handler::explosion( p, 60, 0.7, true ); - // More intense fire near the center - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_fire, 1 ); - } - } - - if( effects.count( "NAPALM_BIG" ) > 0 ) { - explosion_handler::explosion( p, 360, 0.8, true ); - // More intense fire near the center - for( auto &pt : g->m.points_in_radius( p, 3, 0 ) ) { - g->m.add_field( pt, fd_fire, 1 ); - } - } - - if( effects.count( "PYROPHORIC" ) > 0 ) { - explosion_handler::explosion( p, 360, 0.8, true ); - // Extreme heat near the center of the explosion - for( auto &pt : g->m.points_in_radius( p, 3, 0 ) ) { - g->m.add_field( pt, fd_fire, 2 ); - } - } - - if( effects.count( "MININUKE_MOD" ) > 0 ) { - explosion_handler::explosion( p, 72000000 ); - for( auto &pt : g->m.points_in_radius( p, 18, 0 ) ) { - if( g->m.sees( p, pt, 3 ) && - g->m.passable( pt ) ) { - g->m.add_field( pt, fd_nuke_gas, 3 ); + for( const ammo_effect &ae : ammo_effects::get_all() ) { + if( effects.count( ae.id.str() ) > 0 ) { + for( auto &pt : g->m.points_in_radius( p, ae.aoe_radius, ae.aoe_radius_z ) ) { + if( one_in( ae.aoe_chance ) ) { + const bool check_sees = !ae.aoe_check_sees || g->m.sees( p, pt, ae.aoe_check_sees_radius ); + const bool check_passable = !ae.aoe_check_passable || g->m.passable( pt ); + if( check_sees && check_passable ) { + g->m.add_field( pt, ae.aoe_field_type, rng( ae.aoe_intensity_min, ae.aoe_intensity_max ) ); + } + } } - } - } - - if( effects.count( "ACIDBOMB" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_acid, 3 ); - } - } - - if( effects.count( "EXPLOSIVE_BIG" ) > 0 ) { - // TODO: double-check if this is sensible. - explosion_handler::explosion( p, 600 ); - } - - if( effects.count( "EXPLOSIVE_HUGE" ) > 0 ) { - // TODO: double-check if this is sensible. - explosion_handler::explosion( p, 1200 ); - } - - if( effects.count( "TOXICGAS" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_toxic_gas, 3 ); - } - } - if( effects.count( "GAS_FUNGICIDAL" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_fungicidal_gas, 3 ); - } - } - if( effects.count( "GAS_INSECTICIDAL" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_insecticidal_gas, 3 ); - } - } - if( effects.count( "SMOKE" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_smoke, 3 ); - } - } - if( effects.count( "SMOKE_BIG" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 6, 0 ) ) { - g->m.add_field( pt, fd_smoke, 3 ); - } - } - - if( effects.count( "FLASHBANG" ) ) { - explosion_handler::flashbang( p ); - } - - if( effects.count( "EMP" ) ) { - explosion_handler::emp_blast( p ); - } - - if( effects.count( "NO_BOOM" ) == 0 && effects.count( "FLAME" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_fire, 1 ); - } - } - - if( effects.count( "FLARE" ) > 0 ) { - g->m.add_field( p, fd_fire, 1 ); - } - - if( effects.count( "LIGHTNING" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - g->m.add_field( pt, fd_electricity, 3 ); - } - } - - if( effects.count( "PLASMA" ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, 1, 0 ) ) { - if( one_in( 2 ) ) { - g->m.add_field( pt, fd_plasma, rng( 2, 3 ) ); + if( ae.aoe_explosion_data.power > 0 ) { + explosion_handler::explosion( p, ae.aoe_explosion_data ); + } + if( ae.do_flashbang ) { + explosion_handler::flashbang( p ); + } + if( ae.do_emp_blast ) { + explosion_handler::emp_blast( p ); } } } } -int aoe_size( const std::set &tags ) +int max_aoe_size( const std::set &tags ) { - if( tags.count( "NAPALM_BIG" ) || - tags.count( "EXPLOSIVE_HUGE" ) ) { - return 4; - } else if( tags.count( "NAPALM" ) || - tags.count( "EXPLOSIVE_BIG" ) ) { - return 3; - } else if( tags.count( "EXPLOSIVE" ) || - tags.count( "EXPLOSIVE_SMALL" ) ) { - return 2; - } else if( tags.count( "FRAG" ) ) { - return 15; - } else if( tags.count( "ACIDBOMB" ) || - tags.count( "FLAME" ) ) { - return 1; + int aoe_size = 0; + for( const ammo_effect &aed : ammo_effects::get_all() ) { + if( tags.count( aed.id.str() ) > 0 ) { + aoe_size = std::max( aoe_size, aed.aoe_size ) ; + } } - - return 0; + return aoe_size; } - diff --git a/src/projectile.h b/src/projectile.h index a2b9dd0b0e295..6e287a1594bd9 100644 --- a/src/projectile.h +++ b/src/projectile.h @@ -58,6 +58,6 @@ struct dealt_projectile_attack { }; void apply_ammo_effects( const tripoint &p, const std::set &effects ); -int aoe_size( const std::set &tags ); +int max_aoe_size( const std::set &tags ); #endif diff --git a/src/string_id_null_ids.cpp b/src/string_id_null_ids.cpp index 9193f7c311cad..d6829813a2560 100644 --- a/src/string_id_null_ids.cpp +++ b/src/string_id_null_ids.cpp @@ -43,6 +43,7 @@ MAKE_NULL_ID2( oter_type_t, "", 0 ) MAKE_NULL_ID2( ter_t, "t_null", 0 ) MAKE_NULL_ID2( trap, "tr_null" ) MAKE_NULL_ID2( construction_category, "NULL", 0 ) +MAKE_NULL_ID2( ammo_effect, "AE_NULL", 0 ) MAKE_NULL_ID2( field_type, "fd_null", 0 ) MAKE_NULL_ID2( furn_t, "f_null", 0 ) MAKE_NULL_ID2( MonsterGroup, "GROUP_NULL" ) diff --git a/src/turret.cpp b/src/turret.cpp index 2bf125798372e..e4592be8a155b 100644 --- a/src/turret.cpp +++ b/src/turret.cpp @@ -548,7 +548,7 @@ int vehicle::automatic_fire_turret( vehicle_part &pt ) // Create the targeting computer's npc npc cpu = get_targeting_npc( pt ); - int area = aoe_size( gun.ammo_effects() ); + int area = max_aoe_size( gun.ammo_effects() ); if( area > 0 ) { // Pad a bit for less friendly fire area += area == 1 ? 1 : 2; diff --git a/src/type_id.h b/src/type_id.h index 09deb42cf8013..548512478ddc0 100644 --- a/src/type_id.h +++ b/src/type_id.h @@ -8,6 +8,10 @@ class ammunition_type; using ammotype = string_id; +struct ammo_effect; +using ammo_effect_id = int_id; +using ammo_effect_str_id = string_id; + struct bionic_data; using bionic_id = string_id;