Skip to content

Commit

Permalink
Gun Safeties (shiptest-ss13#2443)
Browse files Browse the repository at this point in the history
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 <[email protected]>
Co-authored-by: Mark Suckerberg <[email protected]>
  • Loading branch information
2 people authored and Mirag1993 committed Nov 10, 2023
1 parent ba24e34 commit 777f093
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 7 deletions.
54 changes: 51 additions & 3 deletions code/modules/projectiles/gun.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -198,6 +204,9 @@
else if(can_bayonet)
. += "It has a <b>bayonet</b> lug on it."

if(has_safety)
. += "The safety is [safety ? "<span class='green'>ON</span>" : "<span class='red'>OFF</span>"]. Ctrl-Click to toggle the safety."

/obj/item/gun/equipped(mob/living/user, slot)
. = ..()
if(zoomed && user.get_active_held_item() != src)
Expand All @@ -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, "<span class='danger'>*[dry_fire_text]*</span>") //WS Edit - Dry firing
playsound(src, dry_fire_sound, 30, TRUE)
if(!safety)
to_chat(user, "<span class='danger'>*[dry_fire_text]*</span>")
playsound(src, dry_fire_sound, 30, TRUE)
return
to_chat(user, "<span class='danger'>Safeties are active on the [src]! Turn them off to fire!</span>")


/obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = 0, atom/pbtarget = null, message = 1)
Expand Down Expand Up @@ -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 ? "<span class='green'>ON</span>" : "<span class='red'>OFF</span>"]."),
span_notice("You turn the safety on [src] [safety ? "<span class='green'>ON</span>" : "<span class='red'>OFF</span>"]."),
vision_distance = COMBAT_MESSAGE_RANGE
)
update_appearance()


/obj/item/gun/screwdriver_act(mob/living/user, obj/item/I)
. = ..()
if(.)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion code/modules/projectiles/guns/ballistic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
. = ..()
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions code/modules/projectiles/guns/ballistic/pistol.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
3 changes: 3 additions & 0 deletions code/modules/projectiles/guns/ballistic/revolver.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
. = ..()
. += "<span class='info'>You can use the revolver with your <b>other empty hand</b> to empty the cylinder.</span>"
Expand Down
9 changes: 7 additions & 2 deletions code/modules/projectiles/guns/energy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/projectiles/guns/energy/special.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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 ..()
Expand Down
1 change: 1 addition & 0 deletions code/modules/unit_tests/projectiles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()].")
Expand Down
Binary file added icons/obj/guns/safety.dmi
Binary file not shown.

0 comments on commit 777f093

Please sign in to comment.