From 8496b269f5440b996f3d96d1688da5cf480e1832 Mon Sep 17 00:00:00 2001 From: John Candlebury Date: Sat, 11 Mar 2023 09:04:29 -0600 Subject: [PATCH] Aftershock laser cannons (#64123) * Ammo effects can activate based on chance * Aftershock Heavy Lasers * Description corrections * Correctly spell millisecond --- data/mods/Aftershock/ammo_effects.json | 12 ++++ .../itemgroups/loot_corpse_groups.json | 2 +- .../itemgroups/weapons/energy_gun_groups.json | 22 ++++++- .../mods/Aftershock/items/ammo/flashbulb.json | 24 ++++++++ data/mods/Aftershock/items/ammo_type.json | 6 ++ data/mods/Aftershock/items/gun/laser.json | 57 +++++++++++++++++++ doc/JSON_INFO.md | 14 +++++ src/ammo_effect.cpp | 2 + src/ammo_effect.h | 2 + src/projectile.cpp | 3 + 10 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 data/mods/Aftershock/items/ammo/flashbulb.json diff --git a/data/mods/Aftershock/ammo_effects.json b/data/mods/Aftershock/ammo_effects.json index e327a55537a63..0b1147acabb2e 100644 --- a/data/mods/Aftershock/ammo_effects.json +++ b/data/mods/Aftershock/ammo_effects.json @@ -4,6 +4,12 @@ "type": "ammo_effect", "explosion": { "power": 12000, "max_noise": 25, "distance_factor": 0.2 } }, + { + "id": "PUMP_LASER", + "type": "ammo_effect", + "aoe": { "field_type": "fd_fire", "intensity_min": 1, "intensity_max": 1, "radius": 3, "size": 4, "chance": 50 }, + "explosion": { "power": 5000, "max_noise": 35, "distance_factor": 0.5 } + }, { "id": "FRAG_25mm", "type": "ammo_effect", @@ -14,6 +20,12 @@ "type": "ammo_effect", "aoe": { "field_type": "fd_elect_anomaly", "intensity_min": 2, "intensity_max": 3, "radius": 0 } }, + { + "id": "TACTICAL_LASER_EXPLOSION", + "type": "ammo_effect", + "trigger_chance": 5, + "explosion": { "power": 500, "max_noise": 35, "distance_factor": 0.2 } + }, { "id": "DAZZLE_BEAM", "type": "ammo_effect", diff --git a/data/mods/Aftershock/itemgroups/loot_corpse_groups.json b/data/mods/Aftershock/itemgroups/loot_corpse_groups.json index 21136e11bd5af..d02f52a32610a 100644 --- a/data/mods/Aftershock/itemgroups/loot_corpse_groups.json +++ b/data/mods/Aftershock/itemgroups/loot_corpse_groups.json @@ -27,7 +27,7 @@ "entries": [ { "group": "afs_any_makeshift_gun", "prob": 5 }, { "group": "afs_any_ballistic_s_gun", "prob": 10 }, - { "group": "afs_any_laser_gun", "prob": 10 } + { "group": "afs_any_laser_s_gun", "prob": 10 } ] } ] diff --git a/data/mods/Aftershock/itemgroups/weapons/energy_gun_groups.json b/data/mods/Aftershock/itemgroups/weapons/energy_gun_groups.json index 525ee93f4e331..f5e9070846b17 100644 --- a/data/mods/Aftershock/itemgroups/weapons/energy_gun_groups.json +++ b/data/mods/Aftershock/itemgroups/weapons/energy_gun_groups.json @@ -3,10 +3,14 @@ "id": "afs_any_energy_gun", "type": "item_group", "subtype": "distribution", - "items": [ { "group": "afs_any_laser_gun", "prob": 10 }, { "group": "afs_any_plasma_gun", "prob": 5 } ] + "items": [ + { "group": "afs_any_laser_s_gun", "prob": 10 }, + { "group": "afs_any_laser_h_gun", "prob": 2 }, + { "group": "afs_any_plasma_gun", "prob": 5 } + ] }, { - "id": "afs_any_laser_gun", + "id": "afs_any_laser_s_gun", "type": "item_group", "subtype": "distribution", "ammo": 100, @@ -17,6 +21,20 @@ { "item": "afs_archeotech_laspistol", "charges": 15000, "ammo-item": "afs_battery_plus", "prob": 1 } ] }, + { + "id": "afs_any_laser_h_gun", + "type": "item_group", + "subtype": "distribution", + "ammo": 100, + "magazine": 100, + "items": [ [ "afs_heavy_tactical_laser", 40 ], { "group": "afs_explosive_pumped_laser_s", "prob": 20 } ] + }, + { + "type": "item_group", + "id": "afs_explosive_pumped_laser_s", + "subtype": "collection", + "entries": [ { "item": "afs_explosive_pumped_laser" }, { "item": "afs_82mm_flashbulb", "prob": 90, "count": [ 2, 9 ] } ] + }, { "id": "afs_any_plasma_gun", "type": "item_group", diff --git a/data/mods/Aftershock/items/ammo/flashbulb.json b/data/mods/Aftershock/items/ammo/flashbulb.json new file mode 100644 index 0000000000000..98c1b3902208e --- /dev/null +++ b/data/mods/Aftershock/items/ammo/flashbulb.json @@ -0,0 +1,24 @@ +[ + { + "type": "AMMO", + "id": "afs_82mm_flashbulb", + "price": 70000, + "price_postapoc": 12000, + "name": { "str": "82x225mm flashbulb" }, + "symbol": "=", + "color": "dark_gray", + "description": "Pyrotechnic flash lamps designed to emit and focus a millisecond pulse laser through controlled detonation.", + "material": [ "steel", "powder" ], + "volume": "1250 ml", + "longest_side": "246 mm", + "weight": "3200 g", + "ammo_type": "afs_82mm_flashbulb", + "damage": [ { "damage_type": "pure", "amount": 15 }, { "damage_type": "heat", "amount": 220 } ], + "range": 120, + "dispersion": 15, + "recoil": 45, + "count": 4, + "stack_size": 1, + "effects": [ "COOKOFF", "NEVER_MISFIRES", "LASER", "INCENDIARY", "DAZZLE_BEAM", "PUMP_LASER", "PLASMA_BUBBLE" ] + } +] diff --git a/data/mods/Aftershock/items/ammo_type.json b/data/mods/Aftershock/items/ammo_type.json index cbfd321db6934..22d14fbbfeb82 100644 --- a/data/mods/Aftershock/items/ammo_type.json +++ b/data/mods/Aftershock/items/ammo_type.json @@ -53,6 +53,12 @@ "name": "7.50mm", "default": "afs_7.50mm_caseless" }, + { + "type": "ammunition_type", + "id": "afs_82mm_flashbulb", + "name": "82x225mm flashbulb", + "default": "afs_82mm_flashbulb" + }, { "type": "ammunition_type", "id": "metal_rail", diff --git a/data/mods/Aftershock/items/gun/laser.json b/data/mods/Aftershock/items/gun/laser.json index 7bd211f04e2f7..eeace5f7144c8 100644 --- a/data/mods/Aftershock/items/gun/laser.json +++ b/data/mods/Aftershock/items/gun/laser.json @@ -198,6 +198,63 @@ } ] }, + { + "id": "afs_explosive_pumped_laser", + "looks_like": "m79", + "type": "GUN", + "reload_noise_volume": 10, + "symbol": "(", + "color": "green", + "name": { "str": "Izhevsk PLC-75" }, + "description": "Straight from the bureaus of the old Soviet Union the PLC-75 is the crude and brutal answer to the constraints posed by the design of heavy laser ordnance. Its use of antiquated flashtube pumped laser technology makes it unwieldy and wholly incompatible with modern equipment, whether this offers any consolation to downrange targets remains a matter of contentious dispute.", + "material": [ "steel" ], + "flags": [ "RELOAD_ONE", "BACKBLAST", "NEVER_JAMS" ], + "range": 55, + "skill": "launcher", + "ammo": [ "afs_82mm_flashbulb" ], + "price": "500 USD", + "price_postapoc": "500 USD", + "weight": "10 kg", + "longest_side": "1065 mm", + "volume": "6730 ml", + "bashing": 8, + "to_hit": -3, + "dispersion": 10, + "durability": 8, + "clip_size": 1, + "reload": 300, + "loudness": 200, + "valid_mod_locations": [ [ "accessories", 4 ], [ "grip", 1 ], [ "sights", 1 ] ], + "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "afs_82mm_flashbulb": 1 } } ] + }, + { + "id": "afs_heavy_tactical_laser", + "type": "GUN", + "name": { "str": "Shikishma A-82 tactical laser" }, + "copy-from": "afs_a7", + "description": "Crown jewel of Shikishma armories, and possible product of unsanctioned data scavenging, the A-82 is the undisputed market leader when it comes to man portable laser weaponry. Sustained fire is likely to cause secondary explosions as target layers are vaporized.", + "price": "2 kUSD", + "price_postapoc": "2 kUSD", + "ammo": [ "battery" ], + "ranged_damage": { "damage_type": "heat", "amount": 35 }, + "volume": "3 L", + "range": 37, + "modes": [ [ "DEFAULT", "pulse", 1 ], [ "BURST", "2s sequence", 2 ], [ "AUTO", "3s sequence", 3 ] ], + "extend": { "ammo_effects": [ "TACTICAL_LASER_EXPLOSION" ] }, + "ammo_to_fire": 50, + "valid_mod_locations": [ [ "accessories", 4 ], [ "emitter", 1 ], [ "grip", 1 ], [ "lens", 1 ], [ "rail", 1 ], [ "sights", 1 ], [ "stock", 1 ] ], + "default_mods": [ "red_dot_sight" ], + "pocket_data": [ + { + "pocket_type": "MAGAZINE_WELL", + "holster": true, + "max_contains_volume": "20 L", + "max_contains_weight": "20 kg", + "magazine_well": "75 ml", + "item_restriction": [ "afs_cartridge", "afs_archeotech_cartridge" ] + } + ] + }, { "id": "afs_v29", "type": "GUN", diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 5d4776f5ba016..74aacfbf1eb38 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -3010,6 +3010,20 @@ See [GAME_BALANCE.md](GAME_BALANCE.md)'s `MELEE_WEAPONS` section for the criteri "effects" : ["COOKOFF", "SHOT"] ``` +### Ammo Effects + +```C++ + "id": "TACTICAL_LASER_EXPLOSION", // Defines this as some generic item + "type": "ammo_effect", // Defines this as an ammo_effect + "trigger_chance": 5, // Option one in X chances for the rest of json defined ammo_effect properties to trigger at the hit location. Defaults to 1 + "explosion": { } // (Optional) Creates an explosion at the hit location. See "explosion" for details. + "aoe": { }, // (Optional) Spawn a square of specified fields on the hit location. + "trail": { } // (Optional) Spawn a line of fields on the projectiles path. Not affected by trigger_chance. + "foamcrete_build": true // (Optional) Creates foamcrete fields and walls on the hit location. + "do_flashbang": true // (Optional) Creates a hardcoded Flashbang explosion. + "do_emp_blast": true // (Optional) Creates a one tile radious EMP explosion at the hit location. +``` + ### Magazine ```C++ diff --git a/src/ammo_effect.cpp b/src/ammo_effect.cpp index 62297f1ddb61b..38af790965a27 100644 --- a/src/ammo_effect.cpp +++ b/src/ammo_effect.cpp @@ -62,6 +62,8 @@ int_id::int_id( const string_id &id ) : _id( id.id() ) void ammo_effect::load( const JsonObject &jo, const std::string & ) { + optional( jo, was_loaded, "trigger_chance", trigger_chance, 1 ); + if( jo.has_member( "aoe" ) ) { JsonObject joa = jo.get_object( "aoe" ); optional( joa, was_loaded, "field_type", aoe_field_type_name, "fd_null" ); diff --git a/src/ammo_effect.h b/src/ammo_effect.h index a7500ce3fc6a9..b0f51b0744884 100644 --- a/src/ammo_effect.h +++ b/src/ammo_effect.h @@ -23,6 +23,8 @@ struct ammo_effect { field_type_id aoe_field_type = fd_null.id_or( INVALID_FIELD_TYPE_ID ); /** used during JSON loading only */ + int trigger_chance = 1; + std::string aoe_field_type_name = "fd_null"; int aoe_intensity_min = 0; int aoe_intensity_max = 0; diff --git a/src/projectile.cpp b/src/projectile.cpp index 0fc399cf16e42..28c715d14576b 100644 --- a/src/projectile.cpp +++ b/src/projectile.cpp @@ -145,6 +145,9 @@ void apply_ammo_effects( const Creature *source, const tripoint &p, Character &player_character = get_player_character(); for( const ammo_effect &ae : ammo_effects::get_all() ) { + if( !one_in( ae.trigger_chance ) ) { + continue; + } if( effects.count( ae.id.str() ) > 0 ) { for( const tripoint &pt : here.points_in_radius( p, ae.aoe_radius, ae.aoe_radius_z ) ) { if( x_in_y( ae.aoe_chance, 100 ) ) {