From 777f0934de2b553727281d0afe427f5cf0e5d9bc Mon Sep 17 00:00:00 2001 From: retlaw34 <58402542+retlaw34@users.noreply.github.com> Date: Fri, 10 Nov 2023 07:08:59 -0800 Subject: [PATCH] Gun Safeties (#2443) Request from a friend Adds gun safeties as I have seen people accidentally discharge their weapons one too many times Adjusts tactical reload to 1 second rather than 1.2 seconds ![Screenshot_7922](https://github.com/shiptest-ss13/Shiptest/assets/58402542/a59e6c2e-d49f-4235-a5c1-80557e9aa753) ![Screenshot_7923](https://github.com/shiptest-ss13/Shiptest/assets/58402542/788adbc0-e7c8-41de-a908-4db5206846af) overlay only appears in inventory ![Screenshot_7924](https://github.com/shiptest-ss13/Shiptest/assets/58402542/90389886-4af4-49d6-bf0d-b340fe9f7083) ~~Gun safety RP~~ Accidentally shooting someone happens far too many times to be just a 'skill issue' :cl: add: Adds gun safetys balance: Tacitcal reload time adjusted from 1.2 seconds to 1 second /:cl: --------- Signed-off-by: retlaw34 <58402542+retlaw34@users.noreply.github.com> Co-authored-by: Mark Suckerberg --- code/modules/projectiles/gun.dm | 54 +++++++++++++++++- code/modules/projectiles/guns/ballistic.dm | 7 ++- .../projectiles/guns/ballistic/pistol.dm | 3 + .../projectiles/guns/ballistic/revolver.dm | 3 + code/modules/projectiles/guns/energy.dm | 9 ++- .../projectiles/guns/energy/special.dm | 2 +- code/modules/unit_tests/projectiles.dm | 1 + icons/obj/guns/safety.dmi | Bin 0 -> 313 bytes 8 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 icons/obj/guns/safety.dmi diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 0bfccb6b9113..628fd38d2e5e 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -109,6 +109,12 @@ ///Color of the muzzle flash effect. var/muzzle_flash_color = COLOR_VERY_SOFT_YELLOW + //gun saftey + ///Does this gun have a saftey and thus can toggle it? + var/has_safety = FALSE + ///If the saftey on? If so, we can't fire the weapon + var/safety = FALSE + /obj/item/gun/Initialize() . = ..() RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) @@ -198,6 +204,9 @@ else if(can_bayonet) . += "It has a bayonet lug on it." + if(has_safety) + . += "The safety is [safety ? "ON" : "OFF"]. Ctrl-Click to toggle the safety." + /obj/item/gun/equipped(mob/living/user, slot) . = ..() if(zoomed && user.get_active_held_item() != src) @@ -210,11 +219,16 @@ //check if there's enough ammo/energy/whatever to shoot one time //i.e if clicking would make it shoot /obj/item/gun/proc/can_shoot() + if(safety) + return FALSE return TRUE /obj/item/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj) - to_chat(user, "*[dry_fire_text]*") //WS Edit - Dry firing - playsound(src, dry_fire_sound, 30, TRUE) + if(!safety) + to_chat(user, "*[dry_fire_text]*") + playsound(src, dry_fire_sound, 30, TRUE) + return + to_chat(user, "Safeties are active on the [src]! Turn them off to fire!") /obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = 0, atom/pbtarget = null, message = 1) @@ -484,6 +498,25 @@ else return ..() +/obj/item/gun/CtrlClick(mob/user) + . = ..() + if(!has_safety) + return + + if(src == !user.get_active_held_item()) + return + + playsound(user, 'sound/weapons/gun/general/selector.ogg', 100, TRUE) + safety = !safety + + user.visible_message( + span_notice("[user] turns the safety on [src] [safety ? "ON" : "OFF"]."), + span_notice("You turn the safety on [src] [safety ? "ON" : "OFF"]."), + vision_distance = COMBAT_MESSAGE_RANGE + ) + update_appearance() + + /obj/item/gun/screwdriver_act(mob/living/user, obj/item/I) . = ..() if(.) @@ -634,13 +667,19 @@ var/datum/action/A = X A.UpdateButtonIcon() +/obj/item/gun/attack_hand(mob/user) + . = ..() + update_appearance() + /obj/item/gun/pickup(mob/user) - ..() + . = ..() + update_appearance() if(azoom) azoom.Grant(user) /obj/item/gun/dropped(mob/user) . = ..() + update_appearance() if(azoom) azoom.Remove(user) if(zoomed) @@ -669,6 +708,15 @@ knife_overlay.pixel_y = knife_y_offset . += knife_overlay + if(ismob(loc) && has_safety) + var/mutable_appearance/safety_overlay + safety_overlay = mutable_appearance('icons/obj/guns/safety.dmi') + if(safety) + safety_overlay.icon_state = "safety-on" + else + safety_overlay.icon_state = "safety-off" + . += safety_overlay + /obj/item/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer) if(!ishuman(user) || !ishuman(target)) return diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 90bcf0c73508..a8e2a201c81a 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -6,6 +6,9 @@ icon_state = "pistol" w_class = WEIGHT_CLASS_NORMAL + has_safety = TRUE + safety = TRUE + ///sound when inserting magazine var/load_sound = 'sound/weapons/gun/general/magazine_insert_full.ogg' ///sound when inserting an empty magazine @@ -88,7 +91,7 @@ ///Whether the gun can be tacloaded by slapping a fresh magazine directly on it var/tac_reloads = TRUE //Snowflake mechanic no more. ///If we have the 'snowflake mechanic,' how long should it take to reload? - var/tactical_reload_delay = 1.2 SECONDS + var/tactical_reload_delay = 1 SECONDS /obj/item/gun/ballistic/Initialize() . = ..() @@ -242,6 +245,8 @@ update_appearance() /obj/item/gun/ballistic/can_shoot() + if(safety) + return FALSE return chambered /obj/item/gun/ballistic/attackby(obj/item/A, mob/user, params) diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index b466f2811dd4..591bc7eafa3d 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -237,6 +237,9 @@ can_suppress = FALSE var/random_icon = TRUE + has_safety = FALSE //thing barely costs anything, why would it have a safety? + safety = FALSE + /obj/item/gun/ballistic/automatic/pistol/disposable/Initialize() . = ..() var/picked = pick("none","red","purple","yellow","green","dark") diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 1e922d26aed0..74c7f95d0db2 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -24,6 +24,9 @@ bolt_wording = "hammer" wield_slowdown = 0.3 + has_safety = FALSE //irl revolvers dont have safetys. i think. maybe + safety = FALSE + /obj/item/gun/ballistic/revolver/examine(mob/user) . = ..() . += "You can use the revolver with your other empty hand to empty the cylinder." diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 2a16164c6119..681d79338a52 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -7,6 +7,9 @@ muzzleflash_iconstate = "muzzle_flash_laser" muzzle_flash_color = COLOR_SOFT_RED + has_safety = TRUE + safety = TRUE + var/obj/item/stock_parts/cell/gun/cell //What type of power cell this uses var/cell_type = /obj/item/stock_parts/cell/gun var/modifystate = 0 @@ -147,7 +150,9 @@ eject_cell(user) return ..() -/obj/item/gun/energy/can_shoot() +/obj/item/gun/energy/can_shoot(visuals) + if(safety && !visuals) + return FALSE var/obj/item/ammo_casing/energy/shot = ammo_type[select] return !QDELETED(cell) ? (cell.charge >= shot.e_cost) : FALSE @@ -252,7 +257,7 @@ ///Used by update_icon_state() and update_overlays() /obj/item/gun/energy/proc/get_charge_ratio() - return can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0 + return can_shoot(visuals = TRUE) ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0 // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if its power cell is removed. /obj/item/gun/energy/vv_edit_var(var_name, var_value) diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 9226a587e4aa..2037e77fbed0 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -384,7 +384,7 @@ return return ..() -/obj/item/gun/energy/gravity_gun/can_shoot() +/obj/item/gun/energy/gravity_gun/can_shoot(visuals) if(!firing_core) return FALSE return ..() diff --git a/code/modules/unit_tests/projectiles.dm b/code/modules/unit_tests/projectiles.dm index 4950be10c1a6..e93d20910af0 100644 --- a/code/modules/unit_tests/projectiles.dm +++ b/code/modules/unit_tests/projectiles.dm @@ -19,6 +19,7 @@ gunner.put_in_hands(test_gun, forced=TRUE) var/expected_damage = loaded_bullet.damage loaded_bullet.def_zone = BODY_ZONE_CHEST + test_gun.safety = FALSE //So we can shoot the gun var/did_we_shoot = test_gun.afterattack(victim, gunner) TEST_ASSERT(did_we_shoot, "Gun does not appeared to have successfully fired.") TEST_ASSERT_EQUAL(victim.getBruteLoss(), expected_damage, "Victim took incorrect amount of damage, expected [expected_damage], got [victim.getBruteLoss()].") diff --git a/icons/obj/guns/safety.dmi b/icons/obj/guns/safety.dmi new file mode 100644 index 0000000000000000000000000000000000000000..072a483fa7956e24b6c77d9148ff66d65f7d3431 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQlbGqA+84w9Eh8#y;Vr6;c?J^ z6&109#3nAWV;5fr02MHn1o;IsI6S+N2ILf1g+!FNq!uR^WfqiV=I1dmRLltuD<~@c z{w28J$4-*7Rk3ehk=wenIb z(E4Cc7sn8b-sA)Ukpu@;A1{p1WZg_HadH9`ZjLZXxPOh zDjp&&(bU_^JmIINo*rjNn1Ga2*CGX7UEa`x8WOC^{0t12v-n;u-MUW{Xgq_btDnm{ Hr-UW|COd2m literal 0 HcmV?d00001