diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 8f1c01be21..17b68f1d4e 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -103,6 +103,8 @@
var/flight_x_offset = 0
var/flight_y_offset = 0
+ var/obj/item/firing_pin/pin = /obj/item/firing_pin // YWStation add - Standard firing pin for most guns
+
/obj/item/weapon/gun/CtrlClick(mob/user)
if(can_flashlight && ishuman(user) && src.loc == usr && !user.incapacitated(INCAPACITATION_ALL))
toggle_flashlight()
@@ -123,6 +125,11 @@
/obj/item/weapon/gun/New()
..()
+ // YWStation Add
+ if(pin)
+ pin = new pin(src)
+ // YWStation Add End
+
for(var/i in 1 to firemodes.len)
firemodes[i] = new /datum/firemode(src, firemodes[i])
@@ -230,8 +237,11 @@
return
else
- Fire(A, user, params) //Otherwise, fire normally.
- return
+ if(user.get_active_hand().can_trigger_gun(user))
+ Fire(A, user, params) //Otherwise, fire normally.
+ return
+ else
+ return
/* //Commented out for quality control and testing
if(automatic == 1)//Are we are going to be using automatic shooting
@@ -253,6 +263,10 @@
/obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone)
if (A == user && user.zone_sel.selecting == O_MOUTH && !mouthshoot)
+ if(istype(user))
+ var/mob/living/L = user
+ if(!can_trigger_gun(L))
+ return
handle_suicide(user)
else if(user.a_intent == I_HURT) //point blank shooting
if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A && A != user)
@@ -736,9 +750,18 @@
/obj/item/weapon/gun/examine(mob/user)
. = ..()
+// YWStation Add
+ var/msg = ""
+ if(pin)
+ msg += "It has \a [pin] installed.\n"
+ msg += "[pin] looks like it could be removed with some tools.\n"
+ else
+ msg += "It doesn't have a firing pin installed, and won't fire.\n"
if(firemodes.len > 1)
var/datum/firemode/current_mode = firemodes[sel_mode]
- to_chat(user, "The fire selector is set to [current_mode.name].")
+ msg += "The fire selector is set to [current_mode.name]."
+ to_chat(user, msg)
+// YWStation Add End
/obj/item/weapon/gun/proc/switch_firemodes(mob/user)
if(firemodes.len <= 1)
@@ -755,3 +778,23 @@
/obj/item/weapon/gun/attack_self(mob/user)
switch_firemodes(user)
+
+// YWStation Add
+
+/obj/item/weapon/gun/proc/can_trigger_gun(mob/user)
+ . = ..()
+ if(!handle_pins(user))
+ return FALSE
+
+/obj/item/weapon/gun/proc/handle_pins(mob/user)
+ if(pin)
+ if(pin.pin_auth(user) || pin.emagged)
+ return TRUE
+ else
+ pin.auth_fail(user)
+ return FALSE
+ else
+ to_chat(user, "[src]'s trigger is locked. This weapon doesn't have a firing pin installed!")
+ return FALSE
+
+// YWStation Add End
\ No newline at end of file
diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm
new file mode 100644
index 0000000000..56438df950
--- /dev/null
+++ b/code/modules/projectiles/pins.dm
@@ -0,0 +1,232 @@
+/************************/
+/* Firing Pin Def */
+/************************/
+
+/obj/item/firing_pin
+ name = "electronic firing pin"
+ desc = "A small authentication device, to be inserted into a firearm receiver to allow operation."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "firing_pin"
+ item_state = "pen"
+ attack_verb = list("poked")
+ var/fail_message = "INVALID USER."
+ var/selfdestruct = 0 // Explode when user check is failed.
+ var/force_replace = 0 // Can forcefully replace other pins.
+ var/pin_removeable = 0 // Can be replaced by any pin.
+ var/obj/item/weapon/gun/gun
+ var/emagged = 0
+
+/obj/item/firing_pin/New(newloc)
+ ..()
+ if(istype(newloc, /obj/item/weapon/gun))
+ gun = newloc
+
+/obj/item/firing_pin/afterattack(atom/target, mob/user, adjacent, params)
+ . = ..()
+ if(adjacent)
+ if(istype(target, /obj/item/weapon/gun))
+ var/obj/item/weapon/gun/G = target
+ var/obj/item/firing_pin/old_pin = G.pin
+ if(old_pin && (force_replace || old_pin.pin_removeable))
+ to_chat(user, "You remove [old_pin] from [G].")
+ if(Adjacent(user))
+ user.put_in_hands(old_pin)
+ else
+ old_pin.forceMove(G.drop_location())
+ old_pin.gun_remove(user)
+
+ if(!G.pin)
+ gun_insert(user, G)
+ to_chat(user, "You insert [src] into [G].")
+ else
+ to_chat(user, "This firearm already has a firing pin installed.")
+
+/obj/item/firing_pin/emag_act(var/remaining_charges, var/mob/user)
+ if(emagged)
+ return
+ emagged = !emagged
+ to_chat(user, "You override the authentication mechanism.")
+
+/obj/item/firing_pin/proc/gun_insert(mob/living/user, obj/item/weapon/gun/G)
+ gun = G
+ forceMove(gun)
+ gun.pin = src
+ return
+
+/obj/item/firing_pin/proc/gun_remove(mob/living/user)
+ gun.pin = null
+ gun = null
+ return
+
+/obj/item/firing_pin/proc/pin_auth(mob/living/user)
+ return TRUE
+
+/obj/item/firing_pin/proc/auth_fail(mob/living/user)
+ if(user)
+ user.show_message(fail_message, 2)
+ if(selfdestruct)
+ if(user)
+ user.show_message("SELF-DESTRUCTING...")
+ to_chat(user, "[gun] explodes!")
+ explosion(get_turf(gun), -1, 0, 2, 3)
+ if(gun)
+ qdel(gun)
+
+/*********************/
+/* Firing Pins */
+/*********************/
+
+// Magic weapon pin
+/obj/item/firing_pin/magic
+ name = "magic crystal shard"
+ desc = "A small enchanted shard which allows magical weapons to fire."
+
+
+// Test pin, works only near firing range.
+/obj/item/firing_pin/test_range
+ name = "test-range firing pin"
+ desc = "This safety firing pin allows weapons to be fired within proximity to a firing range."
+ fail_message = "TEST RANGE CHECK FAILED."
+ pin_removeable = TRUE
+
+/obj/item/firing_pin/test_range/pin_auth(mob/living/user)
+ if(!istype(user))
+ return FALSE
+ for(var/obj/machinery/magnetic_controller/M in range(user, 3))
+ return TRUE
+ return FALSE
+
+/**********************************************************************/
+/* Temporarily removed, as I have no clue how med systems work! -Gear */
+/**********************************************************************/
+/*
+// Implant pin, checks for implant
+/obj/item/firing_pin/implant
+ name = "implant-keyed firing pin"
+ desc = "This is a security firing pin which only authorizes users who are implanted with a certain device."
+ fail_message = "IMPLANT CHECK FAILED."
+ var/obj/item/implant/req_implant = null
+
+obj/item/firing_pin/implant/pin_auth(mob/living/user)
+ if(user)
+ for(var/obj/item/organ/external/E in user.organs)
+ for(var/obj/item/weapon/implant/I in E.implants)
+ if(req_implant && I.type == req_implant)
+ return TRUE
+ return FALSE
+
+ // Loyalty implant
+/obj/item/firing_pin/implant/loyalty
+ name = "loyalty firing pin"
+ desc = "This Security firing pin authorizes the weapon for only loyalty-implanted users."
+ icon_state = "firing_pin_loyalty"
+ req_implant = /obj/item/weapon/implant/loyalty
+*/
+
+// Honk pin, clown's joke item.
+// Can replace other pins. Replace a pin in cap's laser for extra fun!
+// Left in for my own peace of mind. -Gear
+/obj/item/firing_pin/clown
+ name = "hilarious firing pin"
+ desc = "Adcanced clowntech that can convert any firearm into a far more useful object."
+ color = "#FFFF00"
+ fail_message = "HONK!"
+ force_replace = TRUE
+
+/obj/item/firing_pin/clown/pin_auth(mob/living/user)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE)
+ return FALSE // :^)
+
+
+/**********************************************************************/
+/* Temporarily removed, as I have no clue how med systems work! -Gear */
+/**********************************************************************/
+/*
+// DNA-keyed pin.
+// When you want to keep your toys for yourself.
+/obj/item/firing_pin/dna
+ name = "DNA-keyed firing pin"
+ desc = "This is a DNA-locked firing pin which only authorizes one user. Attempt to fire once to DNA-link."
+ icon_state = "firing_pin_dna"
+ fail_message = "DNA CHECK FAILED."
+ var/unique_enzymes = null
+
+/obj/item/firing_pin/dna/afterattack(atom/target, mob/user, proximity_flag)
+ . = ..()
+ if(proximity_flag && iscarbon(target))
+ var/mob/living/carbon/M = target
+ if(M.dna && M.dna.unique_enzymes)
+ unique_enzymes = M.dna.unique_enzymes
+ to_chat(user, "DNA-LOCK SET.")
+
+/obj/item/firing_pin/dna/pin_auth(mob/living/carbon/user)
+ if(user && user.dna && user.dna.unique_enzymes)
+ if(user.dna.unique_enzymes == unique_enzymes)
+ return TRUE
+ return FALSE
+
+/obj/item/firing_pin/dna/auth_fail(mob/living/carbon/user)
+ if(!unique_enzymes)
+ if(user && user.dna && user.dna.unique_enzymes)
+ unique_enzymes = user.dna.unique_enzymes
+ to_chat(user, "DNA-LOCK SET.")
+ else
+ ..()
+
+/obj/item/firing_pin/dna/dredd
+ desc = "This is a DNA-locked firing pin which only authorizes one user. Attempt to fire once to DNA-link. It has a small explosive charge on it."
+ selfdestruct = TRUE
+*/
+
+
+// // Explorer firing pin
+// // Usage restricted to off station Z-level
+// /obj/item/firing_pin/explorer
+// name = "outback firing pin"
+// desc = "A firing pin used by the australian defense force, retrofit to prevent weapon discharge on the station."
+// icon_state = "firing_pin_explorer"
+// fail_message = "CANNOT FIRE WHILE ON STATION, MATE!"
+
+// // Checks that the user isn't on station Z-level
+// /obj/item/firing_pin/explorer/pin_auth(mob/living/user)
+// var/turf/station_check = get_turf(user)
+// if(!station_check||is_station_level(station_check.z))
+// to_chat(user, "You cannot use your weapon while on the station!")
+// return FALSE
+// return TRUE
+
+
+// Laser tag pins
+/obj/item/firing_pin/tag
+ name = "laser tag firing pin"
+ desc = "A recreational firing pin, used in laser tag units to ensure users have their vests on."
+ fail_message = "SUIT CHECK FAILED."
+ var/obj/item/clothing/suit/suit_requirement = null
+ var/tagcolor = ""
+
+/obj/item/firing_pin/tag/pin_auth(mob/living/user)
+ if(ishuman(user))
+ var/mob/living/carbon/human/M = user
+ if(istype(M.wear_suit, suit_requirement))
+ return TRUE
+ to_chat(user, "You need to be wearing [tagcolor] laser tag armor!")
+ return FALSE
+
+ // Red laser tag firing pin
+/obj/item/firing_pin/tag/red
+ name = "red laser tag firing pin"
+ icon_state = "firing_pin_red"
+ suit_requirement = /obj/item/clothing/suit/redtag
+ tagcolor = "red"
+
+ // Blue laser tag firing pin
+/obj/item/firing_pin/tag/blue
+ name = "blue laser tag firing pin"
+ icon_state = "firing_pin_blue"
+ suit_requirement = /obj/item/clothing/suit/bluetag
+ tagcolor = "blue"
+
+/obj/item/firing_pin/Destroy()
+ if(gun)
+ gun.pin = null
+ return ..()
\ No newline at end of file
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 6fd1a8d0d3..fc15f5e24b 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/vorestation.dme b/vorestation.dme
index 8f722b5bb3..9e431e3f7b 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2979,6 +2979,7 @@
#include "code\modules\projectiles\ammunition.dm"
#include "code\modules\projectiles\dnalocking.dm"
#include "code\modules\projectiles\gun.dm"
+#include "code\modules\projectiles\pins.dm"
#include "code\modules\projectiles\projectile.dm"
#include "code\modules\projectiles\ammunition\boxes_yw.dm"
#include "code\modules\projectiles\ammunition\magazines.dm"