mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-23 12:07:27 +01:00
Adds the "Jestographic Sequencer", a clown-exclusive traitor item (#18933)
* Initial commit * Removes ability for AI/door remotes to interface with cmagged doors * Adds cleaning method, fixes windoor functionality, makes cmag slippery * Cleaning cmagged doors checks for remaining space cleaner, cleanup * Reduced TC cost from 6 to 4, fixed small bug * Code review super happy funtime * Adds cooldown to cmag airlock chuckle * Cleanup, cmag door laugh no longer sounds through walls (again) * Prevents blank spare IDs from passing through cmagged airlocks * Cleanup * Cmagged state is now carried by a trait instead of a global var, cleanup * Adds early return that I missed, fixes small bug)
This commit is contained in:
@@ -199,6 +199,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
/// Show what machine/door wires do when held.
|
||||
#define TRAIT_SHOW_WIRE_INFO "show_wire_info"
|
||||
#define TRAIT_BUTCHERS_HUMANS "butchers_humans"
|
||||
#define TRAIT_CMAGGED "cmagged"
|
||||
|
||||
//
|
||||
// common trait sources
|
||||
|
||||
@@ -71,7 +71,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
),
|
||||
/obj/item = list(
|
||||
"TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO,
|
||||
"TRAIT_BUTCHER_HUMANS" = TRAIT_BUTCHERS_HUMANS
|
||||
"TRAIT_BUTCHER_HUMANS" = TRAIT_BUTCHERS_HUMANS,
|
||||
"TRAIT_CMAGGED" = TRAIT_CMAGGED
|
||||
)
|
||||
))
|
||||
|
||||
|
||||
@@ -182,6 +182,15 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
surplus = 75
|
||||
job = list("Clown")
|
||||
|
||||
/datum/uplink_item/jobspecific/cmag
|
||||
name = "Jestographic Sequencer"
|
||||
desc = "The jestographic sequencer, also known as a cmag, is a small card that inverts the access on any door it's used on. Perfect for locking command out of their own departments. Honk!"
|
||||
reference = "CMG"
|
||||
item = /obj/item/card/cmag
|
||||
cost = 4
|
||||
surplus = 75
|
||||
job = list("Clown")
|
||||
|
||||
/datum/uplink_item/jobspecific/trick_revolver
|
||||
name = "Trick Revolver"
|
||||
desc = "A revolver that will fire backwards and kill whoever attempts to use it. Perfect for those pesky vigilante or just a good laugh."
|
||||
|
||||
+4
-1
@@ -423,7 +423,7 @@
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
if(updates & NONE)
|
||||
return // NONE is being sent on purpose, and thus no signal should be sent.
|
||||
return // NONE is being sent on purpose, and thus no signal should be sent.
|
||||
|
||||
updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON, updates)
|
||||
if(updates & UPDATE_ICON_STATE)
|
||||
@@ -514,6 +514,9 @@
|
||||
/atom/proc/unemag()
|
||||
return
|
||||
|
||||
/atom/proc/cmag_act()
|
||||
return
|
||||
|
||||
/**
|
||||
* Respond to a radioactive wave hitting this atom
|
||||
*
|
||||
|
||||
@@ -605,6 +605,8 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
|
||||
. = ..()
|
||||
if(emagged)
|
||||
. += "<span class='warning'>Its access panel is smoking slightly.</span>"
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
. += "<span class='warning'>The access panel is coated in yellow ooze...</span>"
|
||||
if(note)
|
||||
if(!in_range(user, src))
|
||||
. += "There's a [note.name] pinned to the front. You can't [note_type() == "note" ? "read" : "see"] it from here."
|
||||
@@ -802,7 +804,7 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
|
||||
/obj/machinery/door/airlock/proc/ai_control_check(mob/user)
|
||||
if(!issilicon(user))
|
||||
return TRUE
|
||||
if(emagged)
|
||||
if(emagged || HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
to_chat(user, "<span class='warning'>Unable to interface: Internal error.</span>")
|
||||
return FALSE
|
||||
if(!canAIControl())
|
||||
@@ -1336,6 +1338,19 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
|
||||
emagged = TRUE
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/airlock/cmag_act(mob/user)
|
||||
if(operating || HAS_TRAIT(src, TRAIT_CMAGGED) || !density || !arePowerSystemsOn())
|
||||
return
|
||||
operating = TRUE
|
||||
update_icon(AIRLOCK_EMAG, 1)
|
||||
sleep(6)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
operating = FALSE
|
||||
update_icon(AIRLOCK_CLOSED, 1)
|
||||
ADD_TRAIT(src, TRAIT_CMAGGED, "clown_emag")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/airlock/emp_act(severity)
|
||||
. = ..()
|
||||
if(prob(20 / severity))
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
var/unres_sides = 0
|
||||
//Multi-tile doors
|
||||
var/width = 1
|
||||
//Whether nonstandard door sounds (cmag laughter) are off cooldown.
|
||||
var/sound_ready = TRUE
|
||||
var/sound_cooldown = 1 SECONDS
|
||||
|
||||
/// ID for the window tint button, or another external control
|
||||
var/id
|
||||
@@ -116,8 +119,14 @@
|
||||
if(world.time - mecha.occupant.last_bumped <= 10)
|
||||
return
|
||||
if(mecha.occupant && allowed(mecha.occupant) || check_access_list(mecha.operation_req_access))
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(FALSE, mecha.occupant)
|
||||
return
|
||||
open()
|
||||
else
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(TRUE, mecha.occupant)
|
||||
return
|
||||
do_animate("deny")
|
||||
return
|
||||
|
||||
@@ -149,6 +158,9 @@
|
||||
|
||||
if(density && !emagged)
|
||||
if(allowed(user))
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(FALSE, user)
|
||||
return
|
||||
open()
|
||||
if(isbot(user))
|
||||
var/mob/living/simple_animal/bot/B = user
|
||||
@@ -156,6 +168,9 @@
|
||||
else
|
||||
if(pry_open_check(user))
|
||||
return
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(TRUE, user)
|
||||
return
|
||||
do_animate("deny")
|
||||
|
||||
/obj/machinery/door/proc/pry_open_check(mob/user)
|
||||
@@ -204,10 +219,18 @@
|
||||
return
|
||||
if(requiresID() && (allowed(user) || user.can_advanced_admin_interact()))
|
||||
if(density)
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED) && !user.can_advanced_admin_interact()) //cmag should not prevent admin intervention
|
||||
cmag_switch(FALSE, user)
|
||||
return
|
||||
open()
|
||||
else
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED) && !user.can_advanced_admin_interact())
|
||||
return
|
||||
close()
|
||||
return TRUE
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(TRUE, user)
|
||||
return
|
||||
if(density)
|
||||
do_animate("deny")
|
||||
|
||||
@@ -226,7 +249,28 @@
|
||||
/obj/machinery/door/proc/try_to_crowbar(mob/user, obj/item/I)
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/clean_cmag_ooze(obj/item/I, mob/user) //Emags are Engineering's problem, cmags are the janitor's problem
|
||||
var/cleaning = FALSE
|
||||
if(istype(I, /obj/item/reagent_containers/spray/cleaner))
|
||||
var/obj/item/reagent_containers/spray/cleaner/C = I
|
||||
if(C.reagents.total_volume >= C.amount_per_transfer_from_this)
|
||||
cleaning = TRUE
|
||||
else
|
||||
return
|
||||
if(istype(I, /obj/item/soap))
|
||||
cleaning = TRUE
|
||||
|
||||
if(!cleaning)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] starts to clean the ooze off the access panel.</span>", "<span class='notice'>You start to clean the ooze off the access panel.</span>")
|
||||
if(do_after(user, 50, target = src))
|
||||
user.visible_message("<span class='notice'>[user] cleans the ooze off [src].</span>", "<span class='notice'>You clean the ooze off [src].</span>")
|
||||
REMOVE_TRAIT(src, TRAIT_CMAGGED, "clown_emag")
|
||||
|
||||
/obj/machinery/door/attackby(obj/item/I, mob/user, params)
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
clean_cmag_ooze(I, user)
|
||||
|
||||
if(user.a_intent != INTENT_HARM && istype(I, /obj/item/twohanded/fireaxe))
|
||||
try_to_crowbar(user, I)
|
||||
return 1
|
||||
@@ -235,7 +279,6 @@
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/door/crowbar_act(mob/user, obj/item/I)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
@@ -272,6 +315,46 @@
|
||||
emagged = TRUE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/cmag_act(mob/user)
|
||||
if(!density)
|
||||
return
|
||||
flick("door_spark", src)
|
||||
sleep(6) //The cmag doesn't automatically open doors. It inverts access, not provides it!
|
||||
ADD_TRAIT(src, TRAIT_CMAGGED, "clown_emag")
|
||||
return TRUE
|
||||
|
||||
//Proc for inverting access on cmagged doors."canopen" should always return the OPPOSITE of the normal result.
|
||||
/obj/machinery/door/proc/cmag_switch(canopen, mob/living/user)
|
||||
if(!canopen || locked || !hasPower())
|
||||
if(density) //Windoors can still do their deny animation in unpowered environments, this bugs out if density isn't checked for
|
||||
do_animate("deny")
|
||||
if(hasPower() && sound_ready)
|
||||
playsound(loc, 'sound/machines/honkbot_evil_laugh.ogg', 25, TRUE, ignore_walls = FALSE)
|
||||
soundcooldown()
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/card/id/idcard = H.get_idcard()
|
||||
if(!idcard?.assignment) //Humans can't game inverted access by taking their ID off or using spare IDs.
|
||||
if(!density)
|
||||
return
|
||||
do_animate("deny")
|
||||
to_chat(H, "<span class='warning'>The airlock speaker chuckles: 'What's wrong, pal? Lost your ID? Nyuk nyuk nyuk!'</span>")
|
||||
if(sound_ready)
|
||||
playsound(loc, 'sound/machines/honkbot_evil_laugh.ogg', 25, TRUE, ignore_walls = FALSE)
|
||||
soundcooldown() //Thanks, mechs
|
||||
return
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
|
||||
/obj/machinery/door/proc/soundcooldown()
|
||||
if(!sound_ready)
|
||||
return
|
||||
sound_ready = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, sound_ready, TRUE), sound_cooldown)
|
||||
|
||||
/obj/machinery/door/proc/toggle_polarization()
|
||||
return
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
. = ..()
|
||||
if(emagged)
|
||||
. += "<span class='warning'>Its access panel is smoking slightly.</span>"
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
. += "<span class='warning'>The access panel is coated in yellow ooze...</span>"
|
||||
|
||||
/obj/machinery/door/window/emp_act(severity)
|
||||
. = ..()
|
||||
@@ -83,8 +85,14 @@
|
||||
if(ismecha(AM))
|
||||
var/obj/mecha/mecha = AM
|
||||
if(mecha.occupant && allowed(mecha.occupant))
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(FALSE)
|
||||
return
|
||||
open_and_close()
|
||||
else
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(TRUE)
|
||||
return
|
||||
do_animate("deny")
|
||||
return
|
||||
if(!SSticker)
|
||||
@@ -98,8 +106,14 @@
|
||||
return
|
||||
add_fingerprint(user)
|
||||
if(!requiresID() || allowed(user))
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(FALSE, user)
|
||||
return
|
||||
open_and_close()
|
||||
else
|
||||
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cmag_switch(TRUE, user)
|
||||
return
|
||||
do_animate("deny")
|
||||
|
||||
/obj/machinery/door/window/unrestricted_side(mob/M)
|
||||
@@ -247,6 +261,17 @@
|
||||
open(2)
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/window/cmag_act(mob/user, obj/weapon)
|
||||
if(operating || !density || HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
return
|
||||
ADD_TRAIT(src, TRAIT_CMAGGED, "clown_emag")
|
||||
operating = TRUE
|
||||
flick("[base_state]spark", src)
|
||||
playsound(src, "sparks", 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
sleep(6)
|
||||
operating = FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/window/attackby(obj/item/I, mob/living/user, params)
|
||||
//If it's in the process of opening/closing, ignore the click
|
||||
if(operating)
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
/obj/item/door_remote/afterattack(obj/machinery/door/airlock/D, mob/user)
|
||||
if(!istype(D))
|
||||
return
|
||||
if(HAS_TRAIT(D, TRAIT_CMAGGED))
|
||||
to_chat(user, "<span class='danger'>The door doesn't respond to [src]!</span>")
|
||||
return
|
||||
if(D.is_special)
|
||||
to_chat(user, "<span class='danger'>[src] cannot access this kind of door!</span>")
|
||||
return
|
||||
|
||||
@@ -80,6 +80,27 @@
|
||||
return
|
||||
A.emag_act(user)
|
||||
|
||||
/obj/item/card/cmag
|
||||
desc = "It's a card coated in a slurry of electromagnetic bananium."
|
||||
name = "jestographic sequencer"
|
||||
icon_state = "cmag"
|
||||
item_state = "card-id"
|
||||
origin_tech = "magnets=2;syndicate=2"
|
||||
flags = NOBLUDGEON
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
|
||||
/obj/item/card/cmag/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, src, 16 SECONDS, 100)
|
||||
|
||||
/obj/item/card/cmag/attack()
|
||||
return
|
||||
|
||||
/obj/item/card/cmag/afterattack(atom/target, mob/user, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
target.cmag_act(user)
|
||||
|
||||
/obj/item/card/id
|
||||
name = "identification card"
|
||||
desc = "A card used to provide ID and determine access across the station."
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
Reference in New Issue
Block a user