Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gun Safety PSA - Keep your gun safeties on to prevent accidental discharges! #3312

Merged
merged 18 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions code/__DEFINES/guns.dm
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@
#define MANUFACTURER_PGF "the Etherbor Industries emblem"
#define MANUFACTURER_IMPORT "Lanchester Import Co."

// Misfire chances if the gun's safety is off
#define GUN_NO_SAFETY_MALFUNCTION_CHANCE_LOW 100
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened here

#define GUN_NO_SAFETY_MALFUNCTION_CHANCE_MEDIUM 100
#define GUN_NO_SAFETY_MALFUNCTION_CHANCE_HIGH 100

/////////////////
// ATTACHMENTS //
/////////////////
Expand Down
2 changes: 2 additions & 0 deletions code/datums/status_effects/debuffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
. = ..()
if(!.)
return
owner.trip_with_gun("knockdown")
ADD_TRAIT(owner, TRAIT_FLOORED, TRAIT_STATUS_EFFECT(id))

/datum/status_effect/incapacitating/knockdown/on_remove()
Expand Down Expand Up @@ -79,6 +80,7 @@
. = ..()
if(!.)
return
owner.trip_with_gun("paralyze")
ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
ADD_TRAIT(owner, TRAIT_FLOORED, TRAIT_STATUS_EFFECT(id))
Expand Down
6 changes: 6 additions & 0 deletions code/game/objects/items/storage/storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
if(EXPLODE_LIGHT)
SSexplosions.lowobj += A

/obj/item/storage/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
for(var/obj/item/gun/at_risk in get_all_contents())
if(at_risk.safety == FALSE && prob(GUN_NO_SAFETY_MALFUNCTION_CHANCE_HIGH))
at_risk.discharge("is hits the ground hard")

/obj/item/storage/canStrip(mob/who)
. = ..()
if(!. && rummage_if_nodrop)
Expand Down
26 changes: 17 additions & 9 deletions code/modules/projectiles/ammunition/_firing.dm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from, misfire = FALSE)
distro += variance
var/targloc = get_turf(target)
ready_proj(target, user, quiet, zone_override, fired_from)
ready_proj(target, user, quiet, zone_override, fired_from, misfire)
if(pellets == 1)
if(distro) //We have to spread a pixel-precision bullet. throw_proj was called before so angles should exist by now...
if(randomspread)
Expand All @@ -15,19 +15,20 @@
return FALSE
AddComponent(/datum/component/pellet_cloud, projectile_type, pellets)
SEND_SIGNAL(src, COMSIG_PELLET_CLOUD_INIT, target, user, fired_from, randomspread, spread, zone_override, params, distro)
if(user)
if(click_cooldown_override)
user.changeNext_move(click_cooldown_override)

if(click_cooldown_override)
user.changeNext_move(click_cooldown_override)

user.newtonian_move(get_dir(target, user))
user.newtonian_move(get_dir(target, user))
update_appearance()
return TRUE

/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", atom/fired_from)
/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", atom/fired_from, misfire = FALSE)
if (!BB)
return
BB.original = target
BB.firer = user
BB.misfire = misfire
BB.fired_from = fired_from
if (zone_override)
BB.def_zone = zone_override
Expand All @@ -45,7 +46,11 @@
qdel(reagents)

/obj/item/ammo_casing/proc/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread)
var/turf/curloc = get_turf(user)
var/turf/curloc
if(user)
curloc = get_turf(user)
else
curloc = get_turf(src)
if (!istype(targloc) || !istype(curloc) || !BB)
return FALSE

Expand All @@ -60,7 +65,10 @@
if(target) //if the target is right on our location we'll skip the travelling code in the proj's fire()
direct_target = target
if(!direct_target)
BB.preparePixelProjectile(target, user, params, spread)
if(user)
BB.preparePixelProjectile(target, user, params, spread)
else
BB.preparePixelProjectile(target, curloc, params, spread)
BB.fire(null, direct_target)
BB = null
return TRUE
Expand Down
48 changes: 48 additions & 0 deletions code/modules/projectiles/gun.dm
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,11 @@
if(zoomed)
zoom(user, user.dir)

/obj/item/gun/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
if(prob(GUN_NO_SAFETY_MALFUNCTION_CHANCE_HIGH))
discharge("hits the ground hard")

/obj/item/gun/update_overlays()
. = ..()
if(ismob(loc) && has_safety)
Expand Down Expand Up @@ -945,6 +950,49 @@
flash_loc.vis_contents -= muzzle_flash
muzzle_flash.applied = FALSE

// for guns firing on their own without a user
/obj/item/gun/proc/discharge(cause, seek_chance = 10)
var/target
if(!safety)
// someone is very unlucky and about to be shot
if(prob(seek_chance))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be VERY VERY VERY low or not exist at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base chance has been reduced to 10%, and on throw now has been reduced to a 50% chance, as a coin flip hail mary option to throw your gun as a last resort

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still think it's too much honestly, should be pretty rare and absolutely not reliable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 and 20 sound okay for base and throw respectively?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chance to seek is just a flat 10% now, and should be seen even less with the reduced misfire chances now.

for(var/mob/living/target_mob in range(6, get_turf(src)))
if(!isInSight(src, target_mob))
continue
target = target_mob
break
if(!target)
var/fire_dir = pick(GLOB.alldirs)
target = get_ranged_target_turf(get_turf(src),fire_dir,6)
if(!chambered || !chambered.BB)
visible_message(span_danger("\The [src] [cause ? "[cause], suddenly going off" : "suddenly goes off"] without its safteies on! Luckily it wasn't live."))
playsound(src, dry_fire_sound, 30, TRUE)
else
visible_message(span_danger("\The [src] [cause ? "[cause], suddenly going off" : "suddenly goes off"] without its safeties on!"))
unsafe_shot(target)

/obj/item/gun/proc/unsafe_shot(target)
if(chambered)
chambered.fire_casing(target,null, null, null, suppressed, ran_zone(BODY_ZONE_CHEST, 50), 0, src,TRUE)
playsound(src, fire_sound, 100, TRUE)

/mob/living/proc/trip_with_gun(cause)
var/mob/living/carbon/human/human_holder
if(ishuman(src))
human_holder = src
for(var/obj/item/gun/at_risk in get_all_contents())
var/chance_to_fire = GUN_NO_SAFETY_MALFUNCTION_CHANCE_MEDIUM
var/did_fire = FALSE
if(human_holder)
// gun is less likely to go off in a holster
if(at_risk == human_holder.s_store)
chance_to_fire = GUN_NO_SAFETY_MALFUNCTION_CHANCE_LOW
if(at_risk.safety == FALSE && prob(chance_to_fire))
if(at_risk.process_fire(src,src,FALSE, null, pick(BODY_ZONE_L_LEG,BODY_ZONE_R_LEG)) == TRUE)
log_combat(src,src,"misfired",at_risk,"caused by [cause]")
visible_message(span_danger("\The [at_risk.name]'s trigger gets caught as [src] falls, suddenly going off into [src]'s leg without its safties on!"), span_danger("\The [at_risk.name]'s trigger gets caught on something as you fall, suddenly going off into your leg without its safeties on!"))
emote("scream")

//I need to refactor this into an attachment
/datum/action/toggle_scope_zoom
name = "Toggle Scope"
Expand Down
5 changes: 5 additions & 0 deletions code/modules/projectiles/guns/ballistic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,8 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list(
if(AC.BB)
process_fire(user, user, FALSE)
. = TRUE

/obj/item/gun/ballistic/unsafe_shot(target, empty_chamber = TRUE)
. = ..()
process_chamber(empty_chamber,TRUE)

6 changes: 6 additions & 0 deletions code/modules/projectiles/guns/energy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
/obj/item/gun/energy/emp_act(severity)
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
if(prob(GUN_NO_SAFETY_MALFUNCTION_CHANCE_HIGH))
discharge("malfunctions from the EMP")
cell.use(round(cell.charge / severity))
chambered = null //we empty the chamber
recharge_newshot() //and try to charge a new shot
Expand Down Expand Up @@ -323,3 +325,7 @@
. += "\The [name] has [round(cell.charge/shot.e_cost)] shots remaining on <b>[shot.select_name]</b> mode."
else
. += span_notice("\The [name] doesn't seem to have a cell!")

/obj/item/gun/energy/unsafe_shot(target)
. = ..()
process_chamber()
6 changes: 5 additions & 1 deletion code/modules/projectiles/projectile.dm
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/def_zone = "" //Aiming at
var/atom/movable/firer = null//Who shot it
// if the projectile was the result of a misfire. For logging.
var/misfire = FALSE
var/atom/fired_from = null // the atom that the projectile was fired from (gun, turret)
var/suppressed = FALSE //Attack message
var/yo = null
Expand Down Expand Up @@ -280,7 +282,9 @@
for(var/datum/reagent/R in reagents.reagent_list)
reagent_note += "[R.name] ([num2text(R.volume)])"

if(ismob(firer))
if(misfire)
L.log_message("has been hit by a misfired [src] from \a [fired_from] last touched by [fired_from.fingerprintslast]", LOG_ATTACK, color = "orange")
else if(ismob(firer))
log_combat(firer, L, "shot", src, reagent_note)
else
L.log_message("has been shot by [firer] with [src]", LOG_ATTACK, color="orange")
Expand Down
6 changes: 6 additions & 0 deletions code/modules/shuttle/on_move.dm
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ All ShuttleMove procs go here

/************************************Item move procs************************************/


/obj/item/storage/pod/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
// If the pod was launched, the storage will always open. The reserved_level check
Expand All @@ -299,6 +300,11 @@ All ShuttleMove procs go here
if (oldT && !is_reserved_level(oldT))
unlocked = TRUE

/obj/item/gun/lateShuttleMove(turf/oldT, list/movement_force, move_dir)
Gristlebee marked this conversation as resolved.
Show resolved Hide resolved
. = ..()
if(prob(GUN_NO_SAFETY_MALFUNCTION_CHANCE_MEDIUM))
discharge("is thrown around by the force of the take off")

/************************************Mob move procs************************************/

/mob/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock, list/obj/docking_port/mobile/towed_shuttles)
Expand Down
Loading