diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm
index 374e89f715..1aaebc5f32 100644
--- a/code/__HELPERS/priority_announce.dm
+++ b/code/__HELPERS/priority_announce.dm
@@ -1,8 +1,10 @@
-/proc/priority_announce(text, title = "", sound = "attention", type , sender_override)
+/proc/priority_announce(text, title = "", sound, type , sender_override, has_important_message)
if(!text)
return
var/announcement
+ if(!sound)
+ sound = "attention"
if(type == "Priority")
announcement += "
Priority Announcement
"
@@ -26,7 +28,11 @@
else
GLOB.news_network.SubmitArticle(title + "
" + text, "Central Command", "Station Announcements", null)
- announcement += "
[html_encode(text)]
"
+ ///If the announcer overrides alert messages, use that message.
+ // if(SSstation.announcer.custom_alert_message && !has_important_message)
+ // announcement += SSstation.announcer.custom_alert_message
+ // else
+ announcement += "
[span_alert("[html_encode(text)]")]
"
announcement += "
"
var/s = sound(get_announcer_sound(sound))
@@ -127,12 +133,44 @@
if("welcome")
. = 'sound/announcer/medibot/welcome.ogg'
+/**
+ * Summon the crew for an emergency meeting
+ *
+ * Teleports the crew to a specified area, and tells everyone (via an announcement) who called the meeting. Should only be used during april fools!
+ * Arguments:
+ * * user - Mob who called the meeting
+ * * button_zone - Area where the meeting was called and where everyone will get teleported to
+ */
+/proc/call_emergency_meeting(mob/living/user, area/button_zone)
+ var/meeting_sound = sound('sound/misc/emergency_meeting.ogg')
+ var/announcement
+ announcement += "Captain Alert
"
+ announcement += "
[span_alert("[user] has called an Emergency Meeting!")]
"
+
+ for(var/mob/mob_to_teleport in GLOB.player_list) //gotta make sure the whole crew's here!
+ if(isnewplayer(mob_to_teleport) || iscameramob(mob_to_teleport))
+ continue
+ to_chat(mob_to_teleport, announcement)
+ SEND_SOUND(mob_to_teleport, meeting_sound) //no preferences here, you must hear the funny sound
+ mob_to_teleport.overlay_fullscreen("emergency_meeting", /atom/movable/screen/fullscreen/emergency_meeting, 1)
+ addtimer(CALLBACK(mob_to_teleport, /mob/.proc/clear_fullscreen, "emergency_meeting"), 3 SECONDS)
+
+ if (is_station_level(mob_to_teleport.z)) //teleport the mob to the crew meeting
+ var/turf/target
+ var/list/turf_list = get_area_turfs(button_zone)
+ while (!target && turf_list.len)
+ target = pick_n_take(turf_list)
+ if (isclosedturf(target))
+ target = null
+ continue
+ mob_to_teleport.forceMove(target)
+
/proc/print_command_report(text = "", title = null, announce=TRUE)
if(!title)
title = "Classified [command_name()] Update"
if(announce)
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport")
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport", has_important_message = TRUE)
var/datum/comm_message/M = new
M.title = title
@@ -140,13 +178,17 @@
SScommunications.send_message(M)
-/proc/minor_announce(message, title = "Attention:", alert)
+/proc/minor_announce(message, title = "Attention:", alert, html_encode = TRUE)
if(!message)
return
+ if (html_encode)
+ title = html_encode(title)
+ message = html_encode(message)
+
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M) && M.can_hear())
- to_chat(M, "[html_encode(title)]
[html_encode(message)]
")
+ to_chat(M, "[span_minorannounce("[title]
[message]")]
")
if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS)
if(alert)
SEND_SOUND(M, sound('sound/misc/notice1.ogg'))
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm
index a7247ccf09..81442b602f 100644
--- a/code/_onclick/hud/fullscreen.dm
+++ b/code/_onclick/hud/fullscreen.dm
@@ -82,6 +82,12 @@
severity = 0
. = ..()
+/atom/movable/screen/fullscreen/emergency_meeting
+ icon_state = "emergency_meeting"
+ show_when_dead = TRUE
+ layer = CURSE_LAYER
+ plane = SPLASHSCREEN_PLANE
+
/atom/movable/screen/fullscreen/brute
icon_state = "brutedamageoverlay"
layer = UI_DAMAGE_LAYER
diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm
index 718357b8bb..58a88890dd 100644
--- a/code/controllers/subsystem/communications.dm
+++ b/code/controllers/subsystem/communications.dm
@@ -1,33 +1,67 @@
-#define COMMUNICATION_COOLDOWN 300
-#define COMMUNICATION_COOLDOWN_AI 300
+#define COMMUNICATION_COOLDOWN (30 SECONDS)
+#define COMMUNICATION_COOLDOWN_AI (30 SECONDS)
+#define COMMUNICATION_COOLDOWN_MEETING (5 MINUTES)
SUBSYSTEM_DEF(communications)
name = "Communications"
flags = SS_NO_INIT | SS_NO_FIRE
- var/silicon_message_cooldown
- var/nonsilicon_message_cooldown
+ COOLDOWN_DECLARE(silicon_message_cooldown)
+ COOLDOWN_DECLARE(nonsilicon_message_cooldown)
+ COOLDOWN_DECLARE(emergency_meeting_cooldown)
/datum/controller/subsystem/communications/proc/can_announce(mob/living/user, is_silicon)
- if(is_silicon && silicon_message_cooldown > world.time)
- . = FALSE
- else if(!is_silicon && nonsilicon_message_cooldown > world.time)
- . = FALSE
+ if(is_silicon && COOLDOWN_FINISHED(src, silicon_message_cooldown))
+ return TRUE
+ else if(!is_silicon && COOLDOWN_FINISHED(src, nonsilicon_message_cooldown))
+ return TRUE
else
- . = TRUE
+ return FALSE
/datum/controller/subsystem/communications/proc/make_announcement(mob/living/user, is_silicon, input)
if(!can_announce(user, is_silicon))
return FALSE
if(is_silicon)
minor_announce(html_decode(input),"[user.name] Announces:")
- silicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN_AI
+ COOLDOWN_START(src, silicon_message_cooldown, COMMUNICATION_COOLDOWN_AI)
else
- priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain")
- nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
+ priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain", has_important_message = TRUE)
+ COOLDOWN_START(src, nonsilicon_message_cooldown, COMMUNICATION_COOLDOWN)
user.log_talk(input, LOG_SAY, tag="priority announcement")
message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.")
+/**
+ * Check if a mob can call an emergency meeting
+ *
+ * Should only really happen during april fools.
+ * Checks to see that it's been at least 5 minutes since the last emergency meeting call.
+ * Arguments:
+ * * user - Mob who called the meeting
+ */
+/datum/controller/subsystem/communications/proc/can_make_emergency_meeting(mob/living/user)
+ if(!(SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
+ return FALSE
+ else if(COOLDOWN_FINISHED(src, emergency_meeting_cooldown))
+ return TRUE
+ else
+ return FALSE
+
+/**
+ * Call an emergency meeting
+ *
+ * Communications subsystem wrapper for the call_emergency_meeting world proc.
+ * Checks to make sure the proc can be called, and handles
+ * relevant logging and timing. See that proc definition for more detail.
+ * Arguments:
+ * * user - Mob who called the meeting
+ */
+/datum/controller/subsystem/communications/proc/emergency_meeting(mob/living/user)
+ if(!can_make_emergency_meeting(user))
+ return FALSE
+ call_emergency_meeting(user, get_area(user))
+ COOLDOWN_START(src, emergency_meeting_cooldown, COMMUNICATION_COOLDOWN_MEETING)
+ message_admins("[ADMIN_LOOKUPFLW(user)] has called an emergency meeting.")
+
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
@@ -40,7 +74,7 @@ SUBSYSTEM_DEF(communications)
var/obj/item/paper/P = new /obj/item/paper(C.loc)
P.name = "paper - '[sending.title]'"
P.info = sending.content
- P.update_icon()
+ P.update_appearance()
#undef COMMUNICATION_COOLDOWN
#undef COMMUNICATION_COOLDOWN_AI
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index b33f7532df..73e3a65145 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -272,7 +272,6 @@
*
* A mind proc for giving anyone an uplink.
* arguments:
- * * traitor_class: (cit specific) the type of antag the user is.
* * silent: if this should send a message to the mind getting the uplink. traitors do not use this silence, but the silence var on their antag datum.
* * antag_datum: the antag datum of the uplink owner, for storing it in antag memory. optional!
*/
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index e05991dd8a..0c9c6f0321 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -247,61 +247,94 @@ Class Procs:
/obj/machinery/proc/auto_use_power()
if(!powered(power_channel))
- return 0
+ return FALSE
if(use_power == 1)
use_power(idle_power_usage,power_channel)
else if(use_power >= 2)
use_power(active_power_usage,power_channel)
- return 1
+ return TRUE
/obj/machinery/proc/is_operational()
return !(stat & (NOPOWER|BROKEN|MAINT))
/obj/machinery/can_interact(mob/user)
- var/silicon = hasSiliconAccessInArea(user) || IsAdminGhost(user)
- if((stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE))
+ if((stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE)) // Check if the machine is broken, and if we can still interact with it if so
return FALSE
- if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN))
- if(!silicon || !(interaction_flags_machine & INTERACT_MACHINE_OPEN_SILICON))
- return FALSE
- if(silicon)
+ if(IsAdminGhost(user))
+ return TRUE //if you're an admin, you probably know what you're doing (or at least have permission to do what you're doing)
+
+ if(!isliving(user))
+ return FALSE //no ghosts in the machine allowed, sorry
+
+ // if(SEND_SIGNAL(user, COMSIG_TRY_USE_MACHINE, src) & COMPONENT_CANT_USE_MACHINE_INTERACT)
+ // return FALSE
+
+ var/mob/living/living_user = user
+
+ var/is_dextrous = FALSE
+ if(isanimal(user))
+ var/mob/living/simple_animal/user_as_animal = user
+ if (user_as_animal.dextrous)
+ is_dextrous = TRUE
+
+ if(!issilicon(user) && !is_dextrous && !user.can_hold_items())
+ return FALSE //spiders gtfo
+
+ if(issilicon(user)) // If we are a silicon, make sure the machine allows silicons to interact with it
if(!(interaction_flags_machine & INTERACT_MACHINE_ALLOW_SILICON))
return FALSE
- else
- if(interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SILICON)
+
+ if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN) && !(interaction_flags_machine & INTERACT_MACHINE_OPEN_SILICON))
return FALSE
- if(!Adjacent(user))
- var/mob/living/carbon/H = user
- if(!(istype(H) && H.has_dna() && H.dna.check_mutation(TK)))
- return FALSE
- return TRUE
+
+ return TRUE //silicons don't care about petty mortal concerns like needing to be next to a machine to use it
+
+ if(living_user.incapacitated()) //idk why silicons aren't supposed to care about incapacitation when interacting with machines, but it was apparently like this before
+ return FALSE
+
+ // TODO: nerf blind people
+ // if((interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SIGHT) && user.is_blind())
+ // to_chat(user, span_warning("This machine requires sight to use."))
+ // return FALSE
+
+ if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN))
+ return FALSE
+
+ if(interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SILICON) //if the user was a silicon, we'd have returned out earlier, so the user must not be a silicon
+ return FALSE
+
+ if(!Adjacent(user)) // Next make sure we are next to the machine unless we have telekinesis
+ var/mob/living/carbon/carbon_user = living_user
+ if(!istype(carbon_user) || !carbon_user.has_dna() || !carbon_user.dna.check_mutation(TK))
+ return FALSE
+
+ return TRUE // If we passed all of those checks, woohoo! We can interact with this machine.
/obj/machinery/proc/check_nap_violations()
if(!SSeconomy.full_ancap)
return TRUE
if(occupant && !state_open)
- if(ishuman(occupant))
- var/mob/living/carbon/human/H = occupant
- var/obj/item/card/id/I = H.get_idcard()
- if(I)
- var/datum/bank_account/insurance = I.registered_account
- if(!insurance)
- say("[market_verb] NAP Violation: No bank account found.")
- nap_violation()
- return FALSE
- else
- if(!insurance.adjust_money(-fair_market_price))
- say("[market_verb] NAP Violation: Unable to pay.")
- nap_violation()
- return FALSE
- var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
- if(D)
- D.adjust_money(fair_market_price)
- else
- say("[market_verb] NAP Violation: No ID card found.")
- nap_violation()
+ var/mob/living/L = occupant
+ var/obj/item/card/id/I = L.get_idcard(TRUE)
+ if(I)
+ var/datum/bank_account/insurance = I.registered_account
+ if(!insurance)
+ say("[market_verb] NAP Violation: No bank account found.")
+ nap_violation(L)
return FALSE
+ else
+ if(!insurance.adjust_money(-fair_market_price))
+ say("[market_verb] NAP Violation: Unable to pay.")
+ nap_violation(L)
+ return FALSE
+ var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
+ if(D)
+ D.adjust_money(fair_market_price)
+ else
+ say("[market_verb] NAP Violation: No ID card found.")
+ nap_violation(L)
+ return FALSE
return TRUE
/obj/machinery/proc/nap_violation(mob/violator)
@@ -322,11 +355,11 @@ Class Procs:
/obj/machinery/Topic(href, href_list)
..()
if(!can_interact(usr))
- return 1
+ return TRUE
if(!usr.canUseTopic(src))
- return 1
+ return TRUE
add_fingerprint(usr)
- return 0
+ return FALSE
////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 5dcbd9430b..b81507024c 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -173,7 +173,7 @@
return
if (!authenticated_as_silicon_or_captain(usr))
return
- // emergency_meeting(usr)
+ emergency_meeting(usr)
if ("makePriorityAnnouncement")
if (!authenticated_as_silicon_or_captain(usr))
return
@@ -531,11 +531,11 @@
* * user - Mob who called the meeting
*/
/obj/machinery/computer/communications/proc/emergency_meeting(mob/living/user)
- // if(!SScommunications.can_make_emergency_meeting(user))
- // to_chat(user, span_alert("The emergency meeting button doesn't seem to work right now. Please stand by."))
- // return
- // SScommunications.emergency_meeting(user)
- // deadchat_broadcast(" called an emergency meeting from [span_name("[get_area_name(usr, TRUE)]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT)
+ if(!SScommunications.can_make_emergency_meeting(user))
+ to_chat(user, span_alert("The emergency meeting button doesn't seem to work right now. Please stand by."))
+ return
+ SScommunications.emergency_meeting(user)
+ deadchat_broadcast(" called an emergency meeting from [span_name("[get_area_name(usr, TRUE)]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT)
/obj/machinery/computer/communications/proc/make_announcement(mob/living/user)
var/is_ai = issilicon(user)
diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm
index 3d0b28d2f3..cdbf19367b 100644
--- a/code/game/objects/structures/manned_turret.dm
+++ b/code/game/objects/structures/manned_turret.dm
@@ -25,7 +25,7 @@
/obj/machinery/manned_turret/Destroy()
target = null
target_turf = null
- ..()
+ return ..()
//BUCKLE HOOKS
diff --git a/code/game/turfs/open/floor/catwalk_plating.dm b/code/game/turfs/open/floor/catwalk_plating.dm
index c6bfdc0448..cbcbade5d4 100644
--- a/code/game/turfs/open/floor/catwalk_plating.dm
+++ b/code/game/turfs/open/floor/catwalk_plating.dm
@@ -34,11 +34,11 @@
/turf/open/floor/plating/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool)
. = ..()
covered = !covered
- to_chat(user, span_notice("[!covered ? "You removed the cover!" : "You added the cover!"]"))
+ user.balloon_alert(user, "[!covered ? "cover removed" : "cover added"]")
update_icon(UPDATE_OVERLAYS)
/turf/open/floor/plating/catwalk_floor/pry_tile(obj/item/crowbar, mob/user, silent)
if(covered)
- to_chat(user, span_notice("You need to remove the cover first!"))
+ user.balloon_alert(user, "remove cover first!")
return FALSE
. = ..()
diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
index 8060b7b0cd..d5c9b2cd2f 100644
--- a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
@@ -264,7 +264,9 @@
ui.open()
/obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI
- . = list()
+ . = ..()
+ if(!.)
+ return
.["recollection"] = recollecting
.["power"] = DisplayPower(get_clockwork_power())
.["power_unformatted"] = get_clockwork_power()
@@ -275,6 +277,7 @@
if(S.tier == SCRIPTURE_PERIPHERAL) // This tier is skiped because this contains basetype stuff
continue
+ // FUTURE IMPL: cache these perhaps?
var/list/data = list()
data["name"] = S.name
data["descname"] = S.descname
diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm
index de34b031d9..ab1a5543d8 100644
--- a/code/modules/antagonists/clockcult/clockcult.dm
+++ b/code/modules/antagonists/clockcult/clockcult.dm
@@ -15,11 +15,11 @@
var/ignore_eligibility_check = FALSE
var/ignore_holy_water = FALSE
-/datum/antagonist/brainwashed/ui_static_data(mob/user)
+/datum/antagonist/clockcult/ui_data(mob/user)
. = ..()
- var/list/data = list()
- data["objectives"] = get_objectives()
- return data
+ if(!.)
+ return
+ .["HONOR_RATVAR"] = GLOB.ratvar_awakens
/datum/antagonist/clockcult/silent
name = "Silent Clock Cultist"
@@ -66,14 +66,6 @@
if(. && !ignore_eligibility_check)
. = is_eligible_servant(new_owner.current)
-/datum/antagonist/clockcult/greet()
- if(!owner.current || silent)
- return
- owner.current.visible_message("[owner.current]'s eyes glow a blazing yellow!", null, null, 7, owner.current) //don't show the owner this message
- to_chat(owner.current, "Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork \
- Justiciar above all else. Perform his every whim without hesitation.")
- owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/clockcultalr.ogg', 70, FALSE, pressure_affected = FALSE)
-
/datum/antagonist/clockcult/on_gain()
var/mob/living/current = owner.current
SSticker.mode.servants_of_ratvar += owner
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
index 56a7d78288..ac8ed537b5 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
@@ -29,13 +29,16 @@ Passive gate is similar to the regular pump except:
/obj/machinery/atmospherics/components/binary/passive_gate/CtrlClick(mob/user)
if(can_interact(user))
on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
update_icon()
return ..()
/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user)
if(can_interact(user))
target_pressure = MAX_OUTPUT_PRESSURE
- update_icon()
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "pressure output set to [target_pressure] kPa")
+ update_appearance()
return ..()
/obj/machinery/atmospherics/components/binary/passive_gate/Destroy()
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
index dc5a6eccd4..a8d82282d6 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
@@ -33,25 +33,19 @@
. += "You can hold Alt and click on it to maximize its pressure."
/obj/machinery/atmospherics/components/binary/pump/CtrlClick(mob/user)
- var/area/A = get_area(src)
- var/turf/T = get_turf(src)
- if(user.canUseTopic(src, BE_CLOSE, FALSE,))
+ if(can_interact(user))
on = !on
- update_icon()
- investigate_log("Pump, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
- message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
- return ..()
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_appearance()
+ return ..()
/obj/machinery/atmospherics/components/binary/pump/AltClick(mob/user)
- . = ..()
- var/area/A = get_area(src)
- var/turf/T = get_turf(src)
- if(user.canUseTopic(src, BE_CLOSE, FALSE,))
+ if(can_interact(user))
target_pressure = MAX_OUTPUT_PRESSURE
- to_chat(user,"You maximize the pressure on the [src].")
- investigate_log("Pump, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
- message_admins("Pump, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
- return TRUE
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "pressure output set to [target_pressure] kPa")
+ update_appearance()
+ return ..()
/obj/machinery/atmospherics/components/binary/pump/Destroy()
SSradio.remove_object(src,frequency)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
index 46d584339b..f5f0064558 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
@@ -33,15 +33,20 @@
. += "You can hold Alt and click on it to maximize its pressure."
/obj/machinery/atmospherics/components/binary/volume_pump/CtrlClick(mob/user)
- var/area/A = get_area(src)
- var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
on = !on
- update_icon()
- investigate_log("Volume Pump, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
- message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_appearance()
return ..()
+/obj/machinery/atmospherics/components/binary/volume_pump/AltClick(mob/user)
+ if(can_interact(user))
+ transfer_rate = MAX_TRANSFER_RATE
+ investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "volume output set to [transfer_rate] L/s")
+ update_appearance()
+ return ..()
+
/obj/machinery/atmospherics/components/binary/volume_pump/Destroy()
SSradio.remove_object(src,frequency)
return ..()
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 4182f5ceca..0814b46993 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -20,25 +20,19 @@
. += "You can hold Alt and click on it to maximize its flow rate."
/obj/machinery/atmospherics/components/trinary/filter/CtrlClick(mob/user)
- var/area/A = get_area(src)
- var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
on = !on
- update_icon()
- investigate_log("Filter, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
- message_admins("Filter, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_appearance()
return ..()
/obj/machinery/atmospherics/components/trinary/filter/AltClick(mob/user)
- . = ..()
- var/area/A = get_area(src)
- var/turf/T = get_turf(src)
- if(user.canUseTopic(src, BE_CLOSE, FALSE,))
+ if(can_interact(user))
transfer_rate = MAX_TRANSFER_RATE
- to_chat(user,"You maximize the flow rate on the [src].")
- investigate_log("Filter, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
- message_admins("Filter, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
- return TRUE
+ investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "volume output set to [transfer_rate] L/s")
+ update_appearance()
+ return ..()
/obj/machinery/atmospherics/components/trinary/filter/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
index 3296981e5e..49d6a71f78 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
@@ -17,35 +17,27 @@
//node 3 is the outlet, nodes 1 & 2 are intakes
/obj/machinery/atmospherics/components/trinary/mixer/CtrlClick(mob/user)
- if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ if(can_interact(user))
on = !on
- update_icon()
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_appearance()
return ..()
/obj/machinery/atmospherics/components/trinary/mixer/AltClick(mob/user)
- if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ if(can_interact(user))
target_pressure = MAX_OUTPUT_PRESSURE
- update_icon()
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "pressure output on set to [target_pressure] kPa")
+ update_appearance()
return ..()
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-/obj/machinery/atmospherics/components/trinary/mixer/update_icon()
- cut_overlays()
+/obj/machinery/atmospherics/components/trinary/mixer/update_overlays()
+ . = ..()
for(var/direction in GLOB.cardinals)
if(!(direction & initialize_directions))
continue
- var/obj/machinery/atmospherics/node = findConnecting(direction)
- var/image/cap
- if(node)
- cap = getpipeimage(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer)
- else
- cap = getpipeimage(icon, "cap", direction, piping_layer = piping_layer)
-
- add_overlay(cap)
-
- return ..()
+ . += getpipeimage(icon, "cap", direction, pipe_color, piping_layer, TRUE)
/obj/machinery/atmospherics/components/trinary/mixer/update_icon_nopipes()
var/on_state = on && nodes[1] && nodes[2] && nodes[3] && is_operational()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index b2fa26edba..c1990a0ffe 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -24,13 +24,16 @@
/obj/machinery/atmospherics/components/unary/outlet_injector/CtrlClick(mob/user)
if(can_interact(user))
on = !on
- update_icon()
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_appearance()
return ..()
/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user)
if(can_interact(user))
volume_rate = MAX_TRANSFER_RATE
- update_icon()
+ investigate_log("was set to [volume_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "volume output set to [volume_rate] L/s")
+ update_appearance()
return ..()
/obj/machinery/atmospherics/components/unary/outlet_injector/Destroy()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
index 8456c0b346..257e312701 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
@@ -217,16 +217,11 @@
min_temperature = max(T0C - (initial(min_temperature) + L * 15), TCMB) //73.15K with T1 stock parts
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/AltClick(mob/living/user)
- . = ..()
- var/area/A = get_area(src)
- var/turf/T = get_turf(src)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
+ if(!can_interact(user))
return
target_temperature = min_temperature
- to_chat(user,"You minimize the temperature on the [src].")
- investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
- message_admins("[src.name] was minimized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
- return TRUE
+ investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "temperature reset to [target_temperature] K")
/obj/machinery/atmospherics/components/unary/thermomachine/heater
name = "heater"
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 04b643e532..ccca7c93cb 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -79,15 +79,16 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
// Tgui Topic middleware
if(tgui_Topic(href_list))
- if(CONFIG_GET(flag/emergency_tgui_logging))
- log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
return
+ if(href_list["reload_tguipanel"])
+ nuke_chat()
+ if(href_list["reload_statbrowser"])
+ src << browse(file('html/statbrowser.html'), "window=statbrowser")
+ // Log all hrefs
+ log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
last_activity = world.time
- //Logs all hrefs
- log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
-
//byond bug ID:2256651
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
to_chat(src, "An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)")
@@ -353,13 +354,19 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
return
// Initialize tgui panel
- tgui_panel.initialize()
src << browse(file('html/statbrowser.html'), "window=statbrowser")
+ addtimer(CALLBACK(src, .proc/check_panel_loaded), 30 SECONDS)
+ tgui_panel.initialize()
-
- if(alert_mob_dupe_login)
- spawn()
- alert(mob, "You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
+ if(alert_mob_dupe_login && !holder)
+ var/dupe_login_message = "Your ComputerID has already logged in with another key this round, please log out of this one NOW or risk being banned!"
+ // if (alert_admin_multikey)
+ // dupe_login_message += "\nAdmins have been informed."
+ // message_admins(span_danger("MULTIKEYING: [key_name_admin(src)] has a matching CID+IP with another player and is clearly multikeying. They have been warned to leave the server or risk getting banned."))
+ // log_admin_private("MULTIKEYING: [key_name(src)] has a matching CID+IP with another player and is clearly multikeying. They have been warned to leave the server or risk getting banned.")
+ spawn(0.5 SECONDS) //needs to run during world init, do not convert to add timer
+ alert(mob, dupe_login_message) //players get banned if they don't see this message, do not convert to tgui_alert (or even tg_alert) please.
+ to_chat(mob, span_danger(dupe_login_message))
connection_time = world.time
connection_realtime = world.realtime
@@ -1031,18 +1038,27 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if(prefs && prefs.chat_toggles & CHAT_PULLR)
to_chat(src, announcement)
-/client/proc/show_character_previews(mutable_appearance/MA)
+/client/proc/show_character_previews(mutable_appearance/source)
+ LAZYINITLIST(char_render_holders)
+ if(!LAZYLEN(char_render_holders))
+ for(var/plane_master_path as anything in subtypesof(/atom/movable/screen/plane_master))
+ var/atom/movable/screen/plane_master/plane_master = new plane_master_path()
+ char_render_holders["plane_master-[plane_master.plane]"] = plane_master
+ plane_master.backdrop(mob)
+ screen |= plane_master
+ plane_master.screen_loc = "character_preview_map:0,CENTER"
+
var/pos = 0
- for(var/D in GLOB.cardinals)
+ for(var/dir in GLOB.cardinals)
pos++
- var/atom/movable/screen/O = LAZYACCESS(char_render_holders, "[D]")
- if(!O)
- O = new
- LAZYSET(char_render_holders, "[D]", O)
- screen |= O
- O.appearance = MA
- O.dir = D
- O.screen_loc = "character_preview_map:0,[pos]"
+ var/atom/movable/screen/preview = char_render_holders["preview-[dir]"]
+ if(!preview)
+ preview = new
+ char_render_holders["preview-[dir]"] = preview
+ screen |= preview
+ preview.appearance = source
+ preview.dir = dir
+ preview.screen_loc = "character_preview_map:0,[pos]"
/client/proc/clear_character_previews()
for(var/index in char_render_holders)
@@ -1078,8 +1094,14 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if(IsAdminAdvancedProcCall())
return
var/list/verblist = list()
- verb_tabs.Cut()
- for(var/thing in (verbs + mob?.verbs))
+ var/list/verbstoprocess = verbs.Copy()
+ if(mob)
+ verbstoprocess += mob.verbs
+ for(var/AM in mob.contents)
+ var/atom/movable/thing = AM
+ verbstoprocess += thing.verbs
+ panel_tabs.Cut() // panel_tabs get reset in init_verbs on JS side anyway
+ for(var/thing in verbstoprocess)
var/procpath/verb_to_init = thing
if(!verb_to_init)
continue
@@ -1087,9 +1109,14 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
continue
if(!istext(verb_to_init.category))
continue
- verb_tabs |= verb_to_init.category
+ panel_tabs |= verb_to_init.category
verblist[++verblist.len] = list(verb_to_init.category, verb_to_init.name)
- src << output("[url_encode(json_encode(verb_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs")
+ src << output("[url_encode(json_encode(panel_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs")
+
+/client/proc/check_panel_loaded()
+ if(statbrowser_ready)
+ return
+ to_chat(src, span_userdanger("Statpanel failed to load, click here to reload the panel "))
//increment progress for an unlockable loadout item
/client/proc/increment_progress(key, amount)
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 2e530226c8..a3c6294aec 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -115,13 +115,13 @@
. = ..()
if(!.)
return
- if(HAS_TRAIT(src, TRAIT_NOGUNS))
- to_chat(src, "You can't bring yourself to use a ranged weapon!")
- return FALSE
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS))
- to_chat(src, "Your meaty finger is much too large for the trigger guard!")
+ balloon_alert(src, "fingers are too big!")
return FALSE
+ if(HAS_TRAIT(src, TRAIT_NOGUNS))
+ to_chat(src, span_warning("You can't bring yourself to use a ranged weapon!"))
+ return FALSE
/mob/living/carbon/human/proc/get_bank_account()
RETURN_TYPE(/datum/bank_account)
diff --git a/icons/mob/screen_full.dmi b/icons/mob/screen_full.dmi
index 502e9ad3f9..975cbf3fe4 100644
Binary files a/icons/mob/screen_full.dmi and b/icons/mob/screen_full.dmi differ
diff --git a/sound/misc/emergency_meeting.ogg b/sound/misc/emergency_meeting.ogg
new file mode 100644
index 0000000000..ad27236ef0
Binary files /dev/null and b/sound/misc/emergency_meeting.ogg differ
diff --git a/sound/misc/license.txt b/sound/misc/license.txt
new file mode 100644
index 0000000000..b92a4a279a
--- /dev/null
+++ b/sound/misc/license.txt
@@ -0,0 +1,5 @@
+bloop.ogg by my man Tim Khan
+(https://freesound.org/people/tim.kahn/sounds/130377/)
+
+knuckles.ogg by CGEffex. Shortened and cut.
+https://freesound.org/people/CGEffex/sounds/93981/
\ No newline at end of file
diff --git a/tgui/packages/tgui/interfaces/AntagInfoClockwork.tsx b/tgui/packages/tgui/interfaces/AntagInfoClockwork.tsx
index 35039ca595..2d03d8f74d 100644
--- a/tgui/packages/tgui/interfaces/AntagInfoClockwork.tsx
+++ b/tgui/packages/tgui/interfaces/AntagInfoClockwork.tsx
@@ -1,17 +1,10 @@
import { BooleanLike } from 'common/react';
-import { useBackend, useLocalState } from '../backend';
-import { BlockQuote, Button, Dimmer, Section, Stack } from '../components';
+import { useBackend } from '../backend';
+import { Section, Stack } from '../components';
import { Window } from '../layouts';
-interface Objective {
- count: number;
- name: string;
- explanation: string;
-}
-
interface Info {
HONOR_RATVAR: BooleanLike;
- objectives: Objective[];
}
let REC_RATVAR = "";
@@ -79,30 +72,3 @@ export const AntagInfoClockwork = (props, context) => {
);
};
-
-const ObjectivePrintout = (props, context) => {
- const { data } = useBackend(context);
- const {
- objectives,
- } = data;
- return (
-
-
- Your current objectives:
-
-
- {!objectives && "None!"
- || objectives.map((objective: Objective) => (
- <>
-
- #{objective.count}: {objective.explanation}
-
-
- This Directive must be followed.
-
- >
- )) }
-
-
- );
-};
diff --git a/tgui/packages/tgui/styles/themes/clockcult.scss b/tgui/packages/tgui/styles/themes/clockcult.scss
index 36a0149fbe..7888b3aee2 100644
--- a/tgui/packages/tgui/styles/themes/clockcult.scss
+++ b/tgui/packages/tgui/styles/themes/clockcult.scss
@@ -6,6 +6,12 @@
@use 'sass:color';
@use 'sass:meta';
+
+@use '../base.scss' with (
+ $color-bg: #c9b12a,
+ $color-bg-grad-spread: 6%,
+ $border-radius: 2px,
+);
@use '../colors.scss' with (
$primary: #B18B25,
$good: #CFBA47,
@@ -14,16 +20,8 @@
$fg-map-keys: (),
$bg-map-keys: (),
);
-@use '../base.scss' with (
- $color-bg: #c9b12a,
- $color-bg-grad-spread: 6%,
- $border-radius: 2px,
-);
.theme-clockcult {
- // Atomic classes
- @include meta.load-css('../atomic/color.scss');
-
// Components
@include meta.load-css('../components/Button.scss', $with: (
'color-default': #5F380E, //wrong.