From 9a6edb999fc22a29e8688b07b6eaaf518bc7d281 Mon Sep 17 00:00:00 2001 From: Cody Brittain Date: Mon, 4 Sep 2023 04:22:14 -0400 Subject: [PATCH] Cleanup and expand suppressors (#17173) * Cleanup and expand suppressors Suicide uses suppressed sounds too Fix CL Added the suppressor to the antagonist uplink Fix CL escape characters Fix random list Resolve issues from code review Split the suppressor into its own file * Bayonets and ammo displays now add their weight to their attached weapon * Balloon alerts for weapon mods * Fix lint --- aurorastation.dme | 1 + .../highly visible and dangerous weapons.dm | 23 +++- .../items/weapons/grenades/fragmentation.dm | 2 +- .../items/weapons/storage/uplink_kits.dm | 5 - .../crates_lockers/crates/gear_loadout.dm | 12 +- code/game/objects/structures/janicart.dm | 2 +- code/modules/custom_ka/core.dm | 2 +- code/modules/item_worth/worths_list.dm | 2 +- code/modules/projectiles/ammo_display.dm | 3 +- code/modules/projectiles/gun.dm | 110 ++++++++++++------ .../projectiles/guns/energy/modular.dm | 2 +- code/modules/projectiles/guns/energy/stun.dm | 3 +- code/modules/projectiles/guns/projectile.dm | 61 +++++++++- .../projectiles/guns/projectile/automatic.dm | 21 ++++ .../projectiles/guns/projectile/dartgun.dm | 3 +- .../projectiles/guns/projectile/pistol.dm | 68 +++-------- .../projectiles/guns/projectile/sniper.dm | 3 +- code/modules/projectiles/projectile.dm | 12 +- code/modules/projectiles/suppressor.dm | 8 ++ .../GeneralCamo - Suppressor Rework.yml | 49 ++++++++ icons/obj/guns/suppressor.dmi | Bin 0 -> 422 bytes maps/away/ships/einstein/ee_spy_ship.dmm | 2 +- 22 files changed, 273 insertions(+), 121 deletions(-) create mode 100644 code/modules/projectiles/suppressor.dm create mode 100644 html/changelogs/GeneralCamo - Suppressor Rework.yml create mode 100644 icons/obj/guns/suppressor.dmi diff --git a/aurorastation.dme b/aurorastation.dme index 397cfdb4344..9bc01d49c3f 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -2863,6 +2863,7 @@ #include "code\modules\projectiles\gun.dm" #include "code\modules\projectiles\pins.dm" #include "code\modules\projectiles\projectile.dm" +#include "code\modules\projectiles\suppressor.dm" #include "code\modules\projectiles\ammunition\ammo_pile.dm" #include "code\modules\projectiles\ammunition\boxes.dm" #include "code\modules\projectiles\ammunition\bullets.dm" diff --git a/code/datums/uplink/highly visible and dangerous weapons.dm b/code/datums/uplink/highly visible and dangerous weapons.dm index 86a82e4fa89..da02566e956 100644 --- a/code/datums/uplink/highly visible and dangerous weapons.dm +++ b/code/datums/uplink/highly visible and dangerous weapons.dm @@ -25,16 +25,23 @@ telecrystal_cost = 4 path = /obj/item/melee/energy/sword -/datum/uplink_item/item/visible_weapons/g9mm - name = "Silenced 9mm" - telecrystal_cost = 2 - path = /obj/item/storage/box/syndie_kit/g9mm - /datum/uplink_item/item/visible_weapons/hammer name = "Kneebreaker Hammer" telecrystal_cost = 3 path = /obj/item/melee/hammer +/datum/uplink_item/item/visible_weapons/suppressor + name = "Suppressor" + desc = "A suppressor that can be attached to most pistol-caliber weaponry. Will prevent sound from passing through walls." + telecrystal_cost = 1 + bluecrystal_cost = 1 + path = /obj/item/suppressor + +/datum/uplink_item/item/visible_weapons/g9mm + name = "9mm Pistol" + telecrystal_cost = 1 + path = /obj/item/gun/projectile/pistol + /datum/uplink_item/item/visible_weapons/revolver name = "Revolver" telecrystal_cost = 4 @@ -141,6 +148,12 @@ telecrystal_cost = 2 path = /obj/item/gun/projectile/colt +/datum/uplink_item/item/visible_weapons/suppressed_pistol + name = "Suppressed .45 Pistol" + desc = "A .45 pistol that comes with a suppressor integrated into the barrel. The suppressor cannot be removed." + telecrystal_cost = 2 + path = /obj/item/gun/projectile/silenced + /datum/uplink_item/item/visible_weapons/custom_ka name = "Kinetic Laser Assembly" telecrystal_cost = 3 diff --git a/code/game/objects/items/weapons/grenades/fragmentation.dm b/code/game/objects/items/weapons/grenades/fragmentation.dm index 3bc97312d84..70bdc676889 100644 --- a/code/game/objects/items/weapons/grenades/fragmentation.dm +++ b/code/game/objects/items/weapons/grenades/fragmentation.dm @@ -36,7 +36,7 @@ base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone spread_step = 20 - silenced = 1 //embedding messages are still produced so it's kind of weird when enabled. + suppressed = TRUE //embedding messages are still produced so it's kind of weird when enabled. no_attack_log = 1 muzzle_type = null diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 6e4eda40cde..629b49efbe6 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -110,11 +110,6 @@ icon_state = "box" item_state = "box" -/obj/item/storage/box/syndie_kit/g9mm - name = "smooth operator" - desc = "9mm with silencer kit." - starts_with = list(/obj/item/gun/projectile/pistol = 1, /obj/item/silencer = 1) - /obj/item/storage/box/syndie_kit/toxin name = "toxin kit" desc = "An apple will not be enough to keep the doctor away after this." diff --git a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm index 90c7528affb..2e06cb06b8d 100644 --- a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm +++ b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm @@ -521,10 +521,10 @@ new /obj/item/gun/projectile/pistol(src) new /obj/item/gun/projectile/pistol(src) new /obj/item/gun/projectile/pistol(src) - new /obj/item/silencer(src) - new /obj/item/silencer(src) - new /obj/item/silencer(src) - new /obj/item/silencer(src) + new /obj/item/suppressor(src) + new /obj/item/suppressor(src) + new /obj/item/suppressor(src) + new /obj/item/suppressor(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) @@ -539,7 +539,7 @@ new /obj/item/clothing/suit/space/void/einstein(src) new /obj/item/gun/energy/rifle(src) new /obj/item/gun/projectile/pistol(src) - new /obj/item/silencer(src) + new /obj/item/suppressor(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) @@ -770,7 +770,7 @@ /obj/structure/closet/crate/secure/gear_loadout/ninja/stealth/fill() ..() new /obj/item/gun/projectile/pistol(src) - new /obj/item/silencer(src) + new /obj/item/suppressor(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 3cab8e0e2c3..e9dcf34069f 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -424,4 +424,4 @@ if(istype(mover, /obj/item/projectile)) return prob(30) else - return !density \ No newline at end of file + return !density diff --git a/code/modules/custom_ka/core.dm b/code/modules/custom_ka/core.dm index b282ddc3749..28bc80dd30d 100644 --- a/code/modules/custom_ka/core.dm +++ b/code/modules/custom_ka/core.dm @@ -20,7 +20,7 @@ fire_sound = 'sound/weapons/kinetic_accel.ogg' fire_sound_text = "blast" recoil = 0 - silenced = 0 + suppressed = FALSE muzzle_flash = 3 accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment. scoped_accuracy = null diff --git a/code/modules/item_worth/worths_list.dm b/code/modules/item_worth/worths_list.dm index b1bbdef17d2..baf0b56cc9d 100644 --- a/code/modules/item_worth/worths_list.dm +++ b/code/modules/item_worth/worths_list.dm @@ -242,7 +242,7 @@ var/list/worths = list( /obj/item/tracker_electronics = 150, /obj/item/am_containment = 5000, /obj/item/syringe_cartridge = 20, - /obj/item/silencer = 60, + /obj/item/suppressor = 60, /obj/item/fossil = 100, /obj/item/vampiric = 666, /obj/item/anobattery = 1800, diff --git a/code/modules/projectiles/ammo_display.dm b/code/modules/projectiles/ammo_display.dm index 810ff843314..96ce979d2c4 100644 --- a/code/modules/projectiles/ammo_display.dm +++ b/code/modules/projectiles/ammo_display.dm @@ -1,7 +1,8 @@ /obj/item/ammo_display name = "holographic ammo display" desc = "A device that can be attached to most firearms, providing a holographic display of the remaining ammunition to the user." + desc_info = "Holographic ammo displays can be attached to firearms to give an ammo readout on the HUD. Click on a weapon adjacent to you or in your hand to attach it. Use a screwdriver on the weapon to remove it." icon = 'icons/obj/weapons.dmi' icon_state = "ammo_display" origin_tech = list(TECH_BLUESPACE = 3, TECH_MATERIAL = 4, TECH_DATA = 4) - w_class = ITEMSIZE_SMALL \ No newline at end of file + w_class = ITEMSIZE_TINY diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 1409765d504..8de397b790e 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -62,15 +62,51 @@ attack_verb = list("struck", "hit", "bashed") zoomdevicename = "scope" +/* + * Suppression vars + */ + + ///Does the gun have a suppressor attached, or should it be suppressed? This will modify firing messages to obscure their source, and change the firing sound to use suppressed_sound + var/suppressed = FALSE + ///The suppressor item currently attached to the gun + var/obj/item/suppressor/suppressor + ///Whether the weapon can have a suppressor attached + var/can_suppress = FALSE + ///Whether the weapon can have a suppressor unattached + var/can_unsuppress = TRUE + +/* + * Sound vars + */ + + ///Sound of the gun firing + var/fire_sound = 'sound/weapons/gunshot/gunshot1.ogg' + ///Whether to vary the frequency of the firing sound + var/vary_fire_sound = TRUE + ///The volume of the firing sound + var/fire_sound_volume = 50 + ///Sound of the gun firing when empty (dryfiring) + var/empty_sound = /singleton/sound_category/out_of_ammo + ///Determines what a player should hear in audible_message when the gun is fired. e.g gunshot, blast + var/fire_sound_text = "gunshot" + ///The firing sound to play when suppressed = TRUE + var/suppressed_sound = 'sound/weapons/gunshot/gunshot_suppressed.ogg' + ///The volume of the suppressed sound + var/suppressed_volume = 60 + ///The sound of the safety being turned on + var/safetyon_sound = 'sound/weapons/blade_open.ogg' + ///The sound of the safety being turned off + var/safetyoff_sound = 'sound/weapons/blade_close.ogg' + drop_sound = 'sound/items/drop/gun.ogg' + pickup_sound = 'sound/items/pickup/gun.ogg' + var/burst = 1 var/can_autofire = FALSE var/fire_delay = 6 //delay after shooting before the gun can be used again var/burst_delay = 1 //delay between shots, if firing in bursts var/move_delay = 0 - var/fire_sound = 'sound/weapons/gunshot/gunshot1.ogg' - var/fire_sound_text = "gunshot" + var/recoil = 0 //screen shake - var/silenced = 0 var/muzzle_flash = 3 var/accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment. var/offhand_accuracy = 0 // the higher this number, the more accurate this weapon is when fired from the off-hand @@ -83,8 +119,6 @@ var/displays_maptext = FALSE var/can_ammo_display = TRUE var/obj/item/ammo_display - var/empty_sound = /singleton/sound_category/out_of_ammo - var/casing_drop_sound = /singleton/sound_category/casing_drop_sound maptext_x = 22 maptext_y = 2 @@ -124,13 +158,6 @@ var/iff_capable = FALSE // if true, applies the user's ID iff_faction to the projectile - // sounds n shit - var/safetyon_sound = 'sound/weapons/blade_open.ogg' - var/safetyoff_sound = 'sound/weapons/blade_close.ogg' - - drop_sound = 'sound/items/drop/gun.ogg' - pickup_sound = 'sound/items/pickup/gun.ogg' - /obj/item/gun/Initialize(mapload) . = ..() for(var/i in 1 to firemodes.len) @@ -404,17 +431,12 @@ P.dispersion = disp P.shot_from = src.name - P.silenced = silenced + P.suppressed = suppressed P.launch_projectile(target) handle_post_fire() // should be safe to not include arguments here, as there are failsafes in effect (?) - if(silenced) - playsound(src, fire_sound, 10, 1) - else - playsound(src, fire_sound, 75, 1, 3, 0.5, 1) - if (muzzle_flash) set_light(muzzle_flash) addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, set_light), 0), 2, TIMER_UNIQUE | TIMER_OVERRIDE) @@ -450,11 +472,8 @@ //called after successfully firing /obj/item/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank = FALSE, var/reflex = FALSE, var/playemote = TRUE) - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 75, 1, 3, 0.5, 1) - + play_fire_sound() + if(!suppressed) if(playemote) if(reflex) user.visible_message( @@ -484,6 +503,12 @@ S.deactivate() update_icon() +/obj/item/gun/proc/play_fire_sound() + if(suppressed) + playsound(loc, suppressed_sound, suppressed_volume, vary_fire_sound) + else + playsound(loc, fire_sound, fire_sound_volume, vary_fire_sound, falloff = 0.5, is_global = TRUE) + /obj/item/gun/proc/process_point_blank(obj/projectile, mob/user, atom/target) var/obj/item/projectile/P = projectile if(!istype(P)) @@ -578,10 +603,7 @@ handle_click_empty(user) mouthshoot = FALSE return - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 75, 1, 3, 0.5, 1) + play_fire_sound() in_chamber.on_hit(M) @@ -634,6 +656,14 @@ accuracy = initial(accuracy) recoil = initial(recoil) +///Handles removing the suppressor from the gun +/obj/item/gun/proc/clear_suppressor() + if(!can_unsuppress) + return + suppressed = FALSE + suppressor = null + update_icon() + /obj/item/gun/examine(mob/user) ..() if(get_dist(src, user) > 1) @@ -872,6 +902,8 @@ QDEL_NULL(pin) if(bayonet) QDEL_NULL(bayonet) + if(istype(suppressor)) + QDEL_NULL(suppressor) return ..() @@ -901,15 +933,21 @@ /obj/item/gun/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/material/knife/bayonet)) if(!can_bayonet) + balloon_alert(user, "\the [I.name] doesn't fit") return ..() + if(user.l_hand != bayonet && user.r_hand != bayonet) + balloon_alert(user, "not in hand") + return + if(bayonet) - to_chat(user, SPAN_WARNING("There is a bayonet attached to \the [src] already!")) + balloon_alert(user, "\the [src] already has a bayonet") return TRUE user.drop_from_inventory(I,src) bayonet = I - to_chat(user, SPAN_NOTICE("You attach \the [I] to the front of \the [src].")) + balloon_alert(user, "[I.name] attached") + w_class += I.w_class update_icon() return TRUE @@ -918,24 +956,29 @@ if(istype(I, /obj/item/ammo_display)) if(!can_ammo_display) - to_chat(user, SPAN_WARNING("\The [I] cannot attach to \the [src].")) + balloon_alert(user, "\the [I.name] doesn't fit") return TRUE + if(user.l_hand != ammo_display && user.r_hand != ammo_display) + balloon_alert(user, "not in hand") + return if(ammo_display) - to_chat(user, SPAN_WARNING("\The [src] already has a holographic ammo display.")) + balloon_alert(user, "\the [src] already has an ammo display") return TRUE if(displays_maptext) - to_chat(user, SPAN_WARNING("\The [src] is already displaying its ammo count.")) + balloon_alert(user, "\the [src] is already displaying its ammo count") return TRUE user.drop_from_inventory(I, src) ammo_display = I displays_maptext = TRUE - to_chat(user, SPAN_NOTICE("You attach \the [I] to \the [src].")) + balloon_alert(user, "[I.name] attached") + w_class += I.w_class return TRUE if(I.iscrowbar() && bayonet) to_chat(user, SPAN_NOTICE("You detach \the [bayonet] from \the [src].")) bayonet.forceMove(get_turf(src)) user.put_in_hands(bayonet) + w_class -= bayonet.w_class bayonet = null update_icon() return TRUE @@ -944,6 +987,7 @@ to_chat(user, SPAN_NOTICE("You wrench the ammo display loose from \the [src].")) ammo_display.forceMove(get_turf(src)) user.put_in_hands(ammo_display) + w_class -= ammo_display.w_class ammo_display = null displays_maptext = FALSE maptext = "" diff --git a/code/modules/projectiles/guns/energy/modular.dm b/code/modules/projectiles/guns/energy/modular.dm index 6ef555b8f7c..ff22caf4381 100644 --- a/code/modules/projectiles/guns/energy/modular.dm +++ b/code/modules/projectiles/guns/energy/modular.dm @@ -144,7 +144,7 @@ for(var/obj/item/laser_components/modifier/modifier in gun_mods) switch(modifier.mod_type) if(MOD_SILENCE) - silenced = 1 + suppressed = TRUE if(MOD_NUCLEAR_CHARGE) self_recharge = 1 criticality *= 2 diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index f0253419621..cfca1b13b6e 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -47,7 +47,8 @@ origin_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 2, TECH_ILLEGAL = 5) matter = list(DEFAULT_WALL_MATERIAL = 2000) slot_flags = SLOT_BELT - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE fire_sound = 'sound/weapons/Genhit.ogg' projectile_type = /obj/item/projectile/energy/bolt max_shots = 5 diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 3859a5fb03e..02029935457 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -27,6 +27,11 @@ var/unjam_cooldown = 0 //Gives the unjammer some time after spamming unjam to not eject their mag var/jam_chance = 0 //Chance it jams on fire + ///Pixel offset for the suppressor overlay on the x axis. + var/suppressor_x_offset + ///Pixel offset for the suppressor overlay on the y axis. + var/suppressor_y_offset + //TODO generalize ammo icon states for guns //var/magazine_states = 0 //var/list/icon_keys = list() //keys @@ -49,6 +54,16 @@ QDEL_NULL_LIST(loaded) . = ..() +/obj/item/gun/projectile/update_icon() + ..() + if(suppressed) + var/mutable_appearance/MA = mutable_appearance('icons/obj/guns/suppressor.dmi', "suppressor") + if(suppressor_x_offset) + MA.pixel_x = suppressor_x_offset + if(suppressor_y_offset) + MA.pixel_y = suppressor_y_offset + underlays += MA + /obj/item/gun/projectile/consume_next_projectile() if(jam_num) return FALSE @@ -212,9 +227,26 @@ update_maptext() update_icon() -/obj/item/gun/projectile/attackby(obj/item/A, mob/user) +/obj/item/gun/projectile/attackby(obj/item/I, mob/user) . = ..() - load_ammo(A, user) + if(.) + return + load_ammo(I, user) + if(istype(I, /obj/item/suppressor)) + var/obj/item/suppressor/S = I + if(!can_suppress) + balloon_alert(user, "\the [S.name] doesn't fit") + return + if(user.l_hand != suppressor && user.r_hand != suppressor) + balloon_alert(user, "not in hand") + return + if(suppressed) + balloon_alert(user, "already has a suppressor") + return + user.drop_from_inventory(suppressor, src) + balloon_alert(user, "[S.name] attached") + install_suppressor(S) + return /obj/item/gun/projectile/toggle_firing_mode(mob/user) if(jam_num) @@ -261,6 +293,8 @@ to_chat(user, "It looks jammed.") if(ammo_magazine) to_chat(user, "It has \a [ammo_magazine] loaded.") + if(suppressed) + to_chat(user, "It has a suppressor attached.") to_chat(user, "Has [get_ammo()] round\s remaining.") return @@ -296,3 +330,26 @@ else . += "No magazine inserted.
" . += ..(FALSE) + +///Installs a new suppressor, assumes that the suppressor is already in the contents of src +/obj/item/gun/projectile/proc/install_suppressor(obj/item/suppressor/S) + suppressed = TRUE + w_class += S.w_class //Add our weight class to the item's weight class + suppressor = S + update_icon() + +/obj/item/gun/projectile/clear_suppressor() + if(!can_unsuppress) + return + if(istype(suppressor)) + w_class -= suppressor.w_class + return ..() + +/obj/item/gun/projectile/AltClick(mob/user) + if(use_check_and_message(user)) + return + if(suppressed && can_unsuppress) + balloon_alert(user, "[suppressor.name] removed") + user.put_in_hands(suppressor) + clear_suppressor() + return ..() diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 2462a321e71..378b5453b88 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -16,6 +16,8 @@ burst_delay = 2 sel_mode = 1 fire_delay = ROF_SMG + can_suppress = TRUE + suppressor_x_offset = 8 firemodes = list( list(mode_name="semiauto", can_autofire=0, burst=1, fire_delay=ROF_SMG), @@ -40,6 +42,9 @@ caliber = ".45" origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) ammo_type = /obj/item/ammo_casing/c45 + suppressed = FALSE + can_suppress = TRUE + suppressor_x_offset = 10 /obj/item/gun/projectile/automatic/mini_uzi/update_icon() ..() @@ -65,6 +70,9 @@ allowed_magazines = list(/obj/item/ammo_magazine/a10mm) auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + suppressed = FALSE + can_suppress = TRUE + suppressor_x_offset = 11 /obj/item/gun/projectile/automatic/c20r/update_icon() ..() @@ -80,6 +88,7 @@ icon = 'icons/obj/guns/sol_smg.dmi' icon_state = "vityaz" item_state = "vityaz" + suppressor_x_offset = 10 /obj/item/gun/projectile/automatic/c20r/sol/update_icon() ..() @@ -100,6 +109,9 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/mc9mmt/rubber allowed_magazines = list(/obj/item/ammo_magazine/mc9mmt) + can_suppress = TRUE + suppressor_x_offset = 10 + suppressor_y_offset = -1 /obj/item/gun/projectile/automatic/wt550/lethal magazine_type = /obj/item/ammo_magazine/mc9mmt @@ -133,6 +145,7 @@ fire_delay = ROF_RIFLE is_wieldable = TRUE + can_suppress = FALSE firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=ROF_RIFLE), @@ -529,6 +542,10 @@ allowed_magazines = list(/obj/item/ammo_magazine/submachinemag, /obj/item/ammo_magazine/submachinedrum) fire_sound = 'sound/weapons/gunshot/gunshot_tommygun.ogg' + can_suppress = TRUE + suppressor_x_offset = 10 + suppressor_y_offset = -1 + /obj/item/gun/projectile/automatic/tommygun/update_icon() ..() icon_state = (ammo_magazine)? "tommygun" : "tommygun-empty" @@ -566,6 +583,8 @@ auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + can_suppress = FALSE + firemodes = list( list(mode_name="single coil", burst = 1), list(mode_name="dual coil", burst = 2, move_delay = 1, accuracy = list(-2,-3), dispersion = list(20)) @@ -589,6 +608,8 @@ auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + can_suppress = FALSE + is_wieldable = TRUE firemodes = list( diff --git a/code/modules/projectiles/guns/projectile/dartgun.dm b/code/modules/projectiles/guns/projectile/dartgun.dm index b41a9ea028d..4452c4102bd 100644 --- a/code/modules/projectiles/guns/projectile/dartgun.dm +++ b/code/modules/projectiles/guns/projectile/dartgun.dm @@ -52,7 +52,8 @@ fire_sound_text = "a metallic click" accuracy = 1 recoil = 0 - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/chemdart auto_eject = 0 diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index ff19c03a70b..f7e83cca274 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -198,9 +198,9 @@ icon_state = "c05r-e" /obj/item/gun/projectile/silenced - name = "silenced pistol" + name = "suppressed pistol" desc = "A small, quiet, easily concealable gun." - desc_extended = "Created as a disposable and concealable weapon, the Mrrazhakulii suppressed pistol is a firearm with a silencer integrated as part of its barrel. \ + desc_extended = "Created as a disposable and concealable weapon, the Mrrazhakulii suppressed pistol is a firearm with a suppressor integrated as part of its barrel. \ Carried by guerrilla forces and spies, those guns are used in assassination and subterfuge operations. Due to using cheap and available materials, such as \ recycled iron and tires, countless of those pistols were distributed among cells and ALA soldiers." icon = 'icons/obj/guns/silenced_pistol.dmi' @@ -211,7 +211,8 @@ accuracy = 1 offhand_accuracy = 1 caliber = ".45" - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/c45m @@ -295,14 +296,15 @@ accuracy = 1 offhand_accuracy = 2 caliber = "9mm" - silenced = 0 + suppressed = FALSE + can_suppress = TRUE origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 2) fire_sound = 'sound/weapons/gunshot/gunshot_pistol.ogg' load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/mc9mm allowed_magazines = list(/obj/item/ammo_magazine/mc9mm) - var/can_silence = TRUE fire_delay = ROF_PISTOL + suppressor_x_offset = 5 /obj/item/gun/projectile/pistol/flash name = "9mm signal pistol" @@ -316,7 +318,7 @@ icon = 'icons/obj/guns/detgun.dmi' icon_state = "detgun" item_state = "detgun" - can_silence = FALSE + can_suppress = FALSE /obj/item/gun/projectile/pistol/detective/update_icon() ..() @@ -338,56 +340,12 @@ name = input to_chat(usr, "You name the gun [input]. Say hello to your new friend.") -/obj/item/gun/projectile/pistol/attack_hand(mob/user as mob) - if(user.get_inactive_hand() == src) - if(silenced && can_silence) - if(user.l_hand != src && user.r_hand != src) - ..() - return - to_chat(user, "You unscrew [silenced] from [src].") - user.put_in_hands(silenced) - silenced = 0 - w_class = ITEMSIZE_SMALL - update_icon() - return - ..() - -/obj/item/gun/projectile/pistol/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/silencer) && can_silence) - if(user.l_hand != src && user.r_hand != src) //if we're not in his hands - to_chat(user, "You'll need [src] in your hands to do that.") - return - user.drop_from_inventory(I,src) - to_chat(user, "You screw [I] onto [src].") - silenced = I //dodgy? - w_class = ITEMSIZE_NORMAL - update_icon() - return - ..() - /obj/item/gun/projectile/pistol/update_icon() ..() - if(silenced) - icon_state = "pistol-silencer" - else - icon_state = "pistol" - -/obj/item/gun/projectile/pistol/update_icon() - ..() - if(silenced) - icon_state = "pistol-silencer" - else - icon_state = "pistol" + icon_state = "pistol" if(!(ammo_magazine && ammo_magazine.stored_ammo.len)) icon_state = "[icon_state]-e" -/obj/item/silencer - name = "silencer" - desc = "A silencer" - icon = 'icons/obj/guns/pistol.dmi' - icon_state = "silencer" - w_class = ITEMSIZE_SMALL - /obj/item/gun/projectile/pirate name = "zip gun" desc = "Little more than a barrel, handle, and firing mechanism, cheap makeshift firearms like this one are not uncommon in frontier systems." @@ -447,7 +405,9 @@ icon = 'icons/obj/guns/sol_pistol.dmi' icon_state = "m8" item_state = "m8" - can_silence = FALSE + can_suppress = TRUE + suppressor_x_offset = 9 + suppressor_y_offset = 3 /obj/item/gun/projectile/pistol/sol/update_icon() ..() @@ -462,7 +422,7 @@ icon = 'icons/obj/guns/adhomian_pistol.dmi' icon_state = "adhomian_pistol" item_state = "adhomian_pistol" - can_silence = FALSE + can_suppress = FALSE desc_extended = "A mass produced pistol issued to People's Republic officers, government officials and low-ranking Party members. Known for their simple, cheap and reliable \ design, this weapon is produced by nearly all weapon factories in the Republic. The Adar'Mazy is also found in the hands of Adhomai Liberation Army soldiers and commanders." @@ -484,7 +444,7 @@ icon_state = "k2557-loaded" item_state = "k2557-loaded" contained_sprite = TRUE - can_silence = FALSE + can_suppress = FALSE w_class = ITEMSIZE_NORMAL load_method = MAGAZINE handle_casings = EJECT_CASINGS diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index 00a9e89cda6..f368fad6f8e 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -152,7 +152,8 @@ origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2) caliber = "PPS" recoil = 1 - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE fire_sound = 'sound/weapons/gunshot/gunshot_light.ogg' max_shells = 4 ammo_type = null diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index a6509195a1f..e28063c705f 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -16,7 +16,7 @@ var/def_zone = "" //Aiming at var/hit_zone // The place that actually got hit var/mob/firer = null//Who shot it - var/silenced = FALSE //Attack message + var/suppressed = FALSE //Attack message var/shot_from = "" // name of the object which shot us @@ -174,7 +174,7 @@ /obj/item/projectile/proc/launch_from_gun(atom/target, target_zone, mob/user, params, angle_override, forced_spread, obj/item/gun/launcher) shot_from = launcher.name - silenced = launcher.silenced + suppressed = launcher.suppressed if(launcher.iff_capable && user) iff = get_iff_from_user(user) @@ -206,7 +206,7 @@ switch(result) if(PROJECTILE_FORCE_MISS) if(!point_blank) - if(!silenced) + if(!suppressed) target_mob.visible_message("\The [src] misses [target_mob] narrowly!") playsound(target_mob, /singleton/sound_category/bulletflyby_sound, 50, 1) return FALSE @@ -217,7 +217,7 @@ var/impacted_organ = target_mob.get_organ_name_from_zone(def_zone) //hit messages - if(silenced) + if(suppressed) to_chat(target_mob, "You've been hit in the [impacted_organ] by \a [src]!") else target_mob.visible_message("\The [target_mob] is hit by \a [src] in the [impacted_organ]!", "You are hit by \a [src] in the [impacted_organ]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter @@ -621,7 +621,7 @@ /obj/item/projectile/proc/generate_muzzle_flash(duration = 3) if(duration <= 0) return - if(!muzzle_type || silenced) + if(!muzzle_type || suppressed) return var/datum/point/p = trajectory var/atom/movable/thing = new muzzle_type @@ -639,7 +639,7 @@ if(tracer_type) for(var/datum/point/p in beam_segments) generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration) - if(muzzle_type && !silenced) + if(muzzle_type && !suppressed) var/datum/point/p = beam_segments[1] var/atom/movable/thing = new muzzle_type p.move_atom_to_src(thing) diff --git a/code/modules/projectiles/suppressor.dm b/code/modules/projectiles/suppressor.dm new file mode 100644 index 00000000000..36a482c4b83 --- /dev/null +++ b/code/modules/projectiles/suppressor.dm @@ -0,0 +1,8 @@ +/obj/item/suppressor + name = "suppressor" + desc = "A suppressor" + desc_info = "Suppressors can be attached to weapons to reduce their sound. Click on a weapon adjacent to you or in your hand to attach it. Alt-Click the weapon to remove it." + icon = 'icons/obj/guns/suppressor.dmi' + icon_state = "suppressor_item" + origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 3) + w_class = ITEMSIZE_SMALL diff --git a/html/changelogs/GeneralCamo - Suppressor Rework.yml b/html/changelogs/GeneralCamo - Suppressor Rework.yml new file mode 100644 index 00000000000..0610199776f --- /dev/null +++ b/html/changelogs/GeneralCamo - Suppressor Rework.yml @@ -0,0 +1,49 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: GeneralCamo + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - refactor: "Refactored how weapon sounds are handled to be less hardcoded." + - tweak: "Renamed the silencer to the suppressor." + - tweak: "The suppressor can now be attached to most pistol-caliber weapons, with the notable exceptions of revolvers." + - tweak: "Suppressors are now removed with Alt-Click." + - rscadd: "Added a suppressor to the antagonist uplink, under \"Highly Visible and Dangerous Weapons\". It costs either 1 telecrystal or 1 bluecrystal." + - rscdel: "The 9mm pistol no longer comes with a suppressor. The 9mm pistol's cost has been reduced from 2 telecrystals to 1 to compensate." + - rscadd: "Added a permanently suppressed .45 pistol to the uplink." + - rscadd: "The holographic ammo display and bayonet now add their weights to a weapon when attached (and vice versa and detached)." + - balance: "The holographic ammo display's weight has been reduced from 'small' to 'tiny'." diff --git a/icons/obj/guns/suppressor.dmi b/icons/obj/guns/suppressor.dmi new file mode 100644 index 0000000000000000000000000000000000000000..61488a2e75d61f124ceb380688561344dde67ad7 GIT binary patch literal 422 zcmV;X0a^ZuP)V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+ z(=$pSoZ^zil2jm5skpSDpeVJtIKN1Vi!&v&s2C_{$iOmk|!HLH~I%#4(^b literal 0 HcmV?d00001 diff --git a/maps/away/ships/einstein/ee_spy_ship.dmm b/maps/away/ships/einstein/ee_spy_ship.dmm index 115c3de4ce8..979edf7abf9 100644 --- a/maps/away/ships/einstein/ee_spy_ship.dmm +++ b/maps/away/ships/einstein/ee_spy_ship.dmm @@ -1065,7 +1065,7 @@ req_access = list(205) }, /obj/item/gun/projectile/pistol, -/obj/item/silencer, +/obj/item/suppressor, /obj/item/ammo_magazine/mc9mm, /obj/item/ammo_magazine/mc9mm, /turf/simulated/floor/tiled/dark,