/obj/item/firing_pin name = "electronic firing pin" desc = "A small authentication device, to be inserted into a firearm receiver to allow operation. NT safety regulations require all new designs to incorporate one." icon = 'icons/obj/devices/gunmod.dmi' icon_state = "firing_pin" inhand_icon_state = "pen" worn_icon_state = "pen" obj_flags = CONDUCTS_ELECTRICITY w_class = WEIGHT_CLASS_TINY attack_verb_continuous = list("pokes") attack_verb_simple = list("poke") var/fail_message = "invalid user!" /// Explode when user check is failed. var/selfdestruct = FALSE /// Can forcefully replace other pins. var/force_replace = FALSE /// Can be replaced by any pin. var/pin_hot_swappable = FALSE ///Can be removed from the gun using tools or replaced by a pin with force_replace var/pin_removable = TRUE var/obj/item/gun/gun /obj/item/firing_pin/New(newloc) ..() if(isgun(newloc)) gun = newloc /obj/item/firing_pin/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isgun(interacting_with)) return NONE var/obj/item/gun/targeted_gun = interacting_with var/obj/item/firing_pin/old_pin = targeted_gun.pin if(old_pin?.pin_removable && (force_replace || old_pin.pin_hot_swappable)) if(Adjacent(user)) user.put_in_hands(old_pin) else old_pin.forceMove(targeted_gun.drop_location()) old_pin.gun_remove(user) if(!targeted_gun.pin) if(!user.temporarilyRemoveItemFromInventory(src)) return . if(gun_insert(user, targeted_gun)) if(old_pin) balloon_alert(user, "swapped firing pin") else balloon_alert(user, "inserted firing pin") else to_chat(user, span_notice("This firearm already has a firing pin installed.")) return ITEM_INTERACT_SUCCESS /obj/item/firing_pin/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) return FALSE obj_flags |= EMAGGED balloon_alert(user, "authentication checks overridden") return TRUE /obj/item/firing_pin/proc/gun_insert(mob/living/user, obj/item/gun/G) gun = G forceMove(gun) gun.pin = src return TRUE /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) balloon_alert(user, fail_message) if(selfdestruct) if(user) user.show_message("[span_danger("SELF-DESTRUCTING...")]
", MSG_VISUAL) to_chat(user, span_userdanger("[gun] explodes!")) explosion(src, devastation_range = -1, light_impact_range = 2, flash_range = 3) if(gun) qdel(gun) /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_hot_swappable = TRUE /obj/item/firing_pin/test_range/pin_auth(mob/living/user) if(!istype(user)) return FALSE if (istype(get_area(user), /area/station/security/range)) return TRUE return FALSE // 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/implant/I in user.implants) if(req_implant && I.type == req_implant) return TRUE return FALSE /obj/item/firing_pin/implant/mindshield name = "mindshield firing pin" desc = "This Security firing pin authorizes the weapon for only mindshield-implanted users." icon_state = "firing_pin_loyalty" req_implant = /obj/item/implant/mindshield /obj/item/firing_pin/implant/pindicate name = "syndicate firing pin" icon_state = "firing_pin_pindi" req_implant = /obj/item/implant/weapons_auth // Honk pin, clown's joke item. // Can replace other pins. Replace a pin in cap's laser for extra fun! /obj/item/firing_pin/clown name = "hilarious firing pin" desc = "Advanced clowntech that can convert any firearm into a far more useful object." color = COLOR_YELLOW 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 // Ultra-honk pin, clown's deadly joke item. // A gun with ultra-honk pin is useful for clown and useless for everyone else. /obj/item/firing_pin/clown/ultra name = "ultra hilarious firing pin" /obj/item/firing_pin/clown/ultra/pin_auth(mob/living/user) playsound(src.loc, 'sound/items/bikehorn.ogg', 50, TRUE) if(QDELETED(user)) //how the hell...? stack_trace("/obj/item/firing_pin/clown/ultra/pin_auth called with a [isnull(user) ? "null" : "invalid"] user.") return TRUE if(HAS_TRAIT(user, TRAIT_CLUMSY)) //clumsy return TRUE if(user.mind) if(is_clown_job(user.mind.assigned_role)) //traitor clowns can use this, even though they're technically not clumsy return TRUE if(user.mind.has_antag_datum(/datum/antagonist/nukeop/clownop)) //clown ops aren't clumsy by default and technically don't have an assigned role of "Clown", but come on, they're basically clowns return TRUE if(user.mind.has_antag_datum(/datum/antagonist/nukeop/leader/clownop)) //Wanna hear a funny joke? return TRUE //The clown op leader antag datum isn't a subtype of the normal clown op antag datum. return FALSE /obj/item/firing_pin/clown/ultra/gun_insert(mob/living/user, obj/item/gun/G) ..() G.clumsy_check = FALSE /obj/item/firing_pin/clown/ultra/gun_remove(mob/living/user) gun.clumsy_check = initial(gun.clumsy_check) ..() // Now two times deadlier! /obj/item/firing_pin/clown/ultra/selfdestruct name = "super ultra hilarious firing pin" desc = "Advanced clowntech that can convert any firearm into a far more useful object. It has a small nitrobananium charge on it." selfdestruct = TRUE // 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/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(iscarbon(interacting_with)) var/mob/living/carbon/M = interacting_with if(M.dna && M.dna.unique_enzymes) unique_enzymes = M.dna.unique_enzymes balloon_alert(user, "dna lock set") return ITEM_INTERACT_SUCCESS return ITEM_INTERACT_BLOCKING return ..() /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 balloon_alert(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 // Paywall pin, brought to you by ARMA 3 DLC. // Checks if the user has a valid bank account on an ID and if so attempts to extract a one-time payment to authorize use of the gun. Otherwise fails to shoot. /obj/item/firing_pin/paywall name = "paywall firing pin" desc = "A firing pin with a built-in configurable paywall." color = COLOR_GOLD fail_message = "" ///list of account IDs which have accepted the license prompt. If this is the multi-payment pin, then this means they accepted the waiver that each shot will cost them money var/list/gun_owners = list() ///how much gets paid out to license yourself to the gun var/payment_amount var/datum/bank_account/pin_owner ///if true, user has to pay everytime they fire the gun var/multi_payment = FALSE var/owned = FALSE ///purchase prompt to prevent spamming it, set to the user who opens to prompt to prevent locking the gun up for other users. var/active_prompt_user /obj/item/firing_pin/paywall/attack_self(mob/user) multi_payment = !multi_payment to_chat(user, span_notice("You set the pin to [( multi_payment ) ? "process payment for every shot" : "one-time license payment"].")) /obj/item/firing_pin/paywall/examine(mob/user) . = ..() if(pin_owner) . += span_notice("This firing pin is currently authorized to pay into the account of [pin_owner.account_holder].") /obj/item/firing_pin/paywall/gun_insert(mob/living/user, obj/item/gun/G) if(!pin_owner) to_chat(user, span_warning("ERROR: Please swipe valid identification card before installing firing pin!")) user.put_in_hands(src) return FALSE gun = G forceMove(gun) gun.pin = src if(multi_payment) gun.desc += span_notice(" This [gun.name] has a per-shot cost of [payment_amount] credit[( payment_amount > 1 ) ? "s" : ""].") return TRUE gun.desc += span_notice(" This [gun.name] has a license permit cost of [payment_amount] credit[( payment_amount > 1 ) ? "s" : ""].") return TRUE /obj/item/firing_pin/paywall/gun_remove(mob/living/user) gun.desc = initial(desc) ..() /obj/item/firing_pin/paywall/attackby(obj/item/M, mob/living/user, params) if(isidcard(M)) var/obj/item/card/id/id = M if(!id.registered_account) to_chat(user, span_warning("ERROR: Identification card lacks registered bank account!")) return if(id.registered_account != pin_owner && owned) to_chat(user, span_warning("ERROR: This firing pin has already been authorized!")) return if(id.registered_account == pin_owner) to_chat(user, span_notice("You unlink the card from the firing pin.")) gun_owners -= user.get_bank_account() pin_owner = null owned = FALSE return var/transaction_amount = tgui_input_number(user, "Insert valid deposit amount for gun purchase", "Money Deposit") if(!transaction_amount || QDELETED(user) || QDELETED(src) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return pin_owner = id.registered_account owned = TRUE payment_amount = transaction_amount gun_owners += user.get_bank_account() to_chat(user, span_notice("You link the card to the firing pin.")) /obj/item/firing_pin/paywall/pin_auth(mob/living/user) if(!istype(user))//nice try commie return FALSE var/datum/bank_account/credit_card_details = user.get_bank_account() if(credit_card_details in gun_owners) if(multi_payment && credit_card_details) if(!gun.can_shoot()) return TRUE //So you don't get charged for attempting to fire an empty gun. if(credit_card_details.adjust_money(-payment_amount, "Firing Pin: Gun Rent")) if(pin_owner) pin_owner.adjust_money(payment_amount, "Firing Pin: Payout For Gun Rent") return TRUE to_chat(user, span_warning("ERROR: User balance insufficent for successful transaction!")) return FALSE return TRUE if(!credit_card_details) to_chat(user, span_warning("ERROR: User has no valid bank account to subtract neccesary funds from!")) return FALSE if(active_prompt_user == user) return FALSE active_prompt_user = user var/license_request = tgui_alert(user, "Do you wish to pay [payment_amount] credit[( payment_amount > 1 ) ? "s" : ""] for [( multi_payment ) ? "each shot of [gun.name]" : "usage license of [gun.name]"]?", "Weapon Purchase", list("Yes", "No"), 15 SECONDS) if(!user.can_perform_action(src)) active_prompt_user = null return FALSE switch(license_request) if("Yes") if(multi_payment) gun_owners += credit_card_details to_chat(user, span_notice("Gun rental terms agreed to, have a secure day!")) else if(credit_card_details.adjust_money(-payment_amount, "Firing Pin: Gun License")) if(pin_owner) pin_owner.adjust_money(payment_amount, "Firing Pin: Gun License Bought") gun_owners += credit_card_details to_chat(user, span_notice("Gun license purchased, have a secure day!")) else to_chat(user, span_warning("ERROR: User balance insufficent for successful transaction!")) if("No", null) to_chat(user, span_warning("ERROR: User has declined to purchase gun license!")) active_prompt_user = null return FALSE //we return false here so you don't click initially to fire, get the prompt, accept the prompt, and THEN the gun // Explorer Firing Pin- Prevents use on station Z-Level, so it's justifiable to give Explorers guns that don't suck. /obj/item/firing_pin/explorer name = "outback firing pin" desc = "A firing pin used by the austrailian defense force, retrofit to prevent weapon discharge on the station." icon_state = "firing_pin_explorer" fail_message = "cannot fire while on station, mate!" // This checks that the user isn't on the 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)) 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, span_warning("You need to be wearing [tagcolor] laser tag armor!")) return FALSE /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" /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/monkey name = "monkeylock firing pin" desc = "This firing pin prevents non-monkeys from firing a gun." fail_message = "not a monkey!" /obj/item/firing_pin/monkey/pin_auth(mob/living/user) if(!is_simian(user)) playsound(src, SFX_SCREECH, 75, TRUE) return FALSE return TRUE /obj/item/firing_pin/Destroy() if(gun) gun.pin = null gun = null return ..()