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 00000000000..61488a2e75d
Binary files /dev/null and b/icons/obj/guns/suppressor.dmi differ
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,