From e9d4eb45d1f7608eb7b3fd8bb2f198d61e6ac496 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Fri, 26 Aug 2022 18:53:57 -0400 Subject: [PATCH] [MDB IGNORE] Improves status display even more, makes the brig door timers based on status displays (#69153) This PR was originally just going to be a re-factor of brig doors to be based on status displays, as a big chunk of their code was duplicating the exact same appearance, but then I realized "Cell 1" would have marqueed for being 6 characters and ended up doing the second half of the status display overhaul I meant to do a while back. So firstly: Yes, brig doors are now subtypes of status displays. The main improvement out of that refactor, other than a lot of code trimming, is that the on-screen timer updates its readout as you set it, which looks nice. Also handled various states in a more consistent way in some edge cases. The timer now also displays the cell's actual name instead of the internal ID on the top line. Now for status displays: Long ago, I wanted the marquee to be continuous but the math required knowing the actual measured text width, though without a user that is impossible. I recently realized the scope of the text usable on status displays (no formatting, or icons) is so narrow, I can cheat it like crazy into a small lookup table and a looping function. No, this method can't possibly extend to runetext. So now the marquees loop seemlessly without any gaps! In fact behind the scenes they loop the very first pixel possible, and still done as a one-and-done animate() sequence as before. (click the preview below if you want to see it smoother) Status displays are now a bit more colorful and have gapless marquee text. Brig door timers were massively refactored behind the scenes. Door control should still work as before but be mindful. --- .../map_files/Deltastation/DeltaStation2.dmm | 10 +- .../map_files/IceBoxStation/IceBoxStation.dmm | 6 +- _maps/map_files/KiloStation/KiloStation.dmm | 12 +- _maps/map_files/MetaStation/MetaStation.dmm | 6 +- _maps/map_files/tramstation/tramstation.dmm | 8 +- code/__HELPERS/global_lists.dm | 1 - code/game/machinery/doors/brigdoors.dm | 179 ++++++++---------- code/game/machinery/status_display.dm | 169 +++++++++-------- code/modules/events/prison_break.dm | 5 +- tools/UpdatePaths/Scripts/69153_brigdoors.txt | 1 + 10 files changed, 191 insertions(+), 206 deletions(-) create mode 100644 tools/UpdatePaths/Scripts/69153_brigdoors.txt diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index b0bcd53f139..3be17a8b4d4 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -12086,7 +12086,7 @@ /turf/open/floor/iron, /area/station/maintenance/department/engine/atmos) "cMM" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "medsci-cell"; name = "Med-Sci Cell"; pixel_y = -32 @@ -37019,7 +37019,7 @@ "iXM" = ( /obj/structure/cable, /obj/item/kirbyplants/random, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "engcell"; name = "Engineering Cell"; pixel_y = 32 @@ -72744,7 +72744,7 @@ /area/station/engineering/atmos/storage/gas) "rNV" = ( /obj/item/kirbyplants/random, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "brig1"; name = "Cell 1"; pixel_x = -32 @@ -78116,7 +78116,7 @@ /area/station/maintenance/department/chapel) "tbZ" = ( /obj/item/kirbyplants/random, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "brig2"; name = "Cell 2"; pixel_x = -32 @@ -83875,7 +83875,7 @@ /turf/open/floor/iron/white/smooth_large, /area/station/medical/psychology) "uxC" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "cargocell"; name = "Cargo Cell"; pixel_x = -32; diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 508f2dc56b0..3eec6804474 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -11762,7 +11762,7 @@ /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "dwS" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 3"; name = "Cell 3"; pixel_x = -32 @@ -21111,7 +21111,7 @@ }, /area/station/command/heads_quarters/rd) "gqZ" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 2"; name = "Cell 2"; pixel_x = -32 @@ -65110,7 +65110,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "ubo" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 1"; name = "Cell 1"; pixel_x = -32 diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index f848cf688be..290b94dc5bf 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -42978,7 +42978,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 5"; name = "Cell 5"; pixel_x = -32 @@ -43511,7 +43511,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 6"; name = "Cell 6"; pixel_x = -32 @@ -48306,7 +48306,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 2"; name = "Cell 2"; pixel_x = -32 @@ -58517,7 +58517,7 @@ /obj/effect/turf_decal/stripes/corner{ dir = 8 }, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 3"; name = "Cell 3"; pixel_x = -32 @@ -59719,7 +59719,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 1"; name = "Cell 1"; pixel_x = -32 @@ -65931,7 +65931,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 4"; name = "Cell 4"; pixel_x = -32 diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 402f1d70552..286b0e58eb1 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -9419,7 +9419,7 @@ /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "dyr" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 3"; name = "Cell 3"; pixel_x = 32; @@ -55584,7 +55584,7 @@ /area/station/engineering/storage/tech) "tDz" = ( /obj/machinery/light/directional/south, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 1"; name = "Cell 1"; pixel_y = -32 @@ -68034,7 +68034,7 @@ /turf/open/floor/plating, /area/station/maintenance/department/science/central) "xWQ" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "Cell 2"; name = "Cell 2"; pixel_y = -32 diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 0a2760e5687..2a304614edf 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -20462,7 +20462,7 @@ /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 }, -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "scicell"; name = "Science Cell"; pixel_y = 32 @@ -32076,7 +32076,7 @@ /turf/open/floor/iron, /area/station/hallway/secondary/command) "ldp" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "crgcell"; name = "Cargo Cell"; pixel_x = 32 @@ -38603,7 +38603,7 @@ /turf/open/floor/iron, /area/station/engineering/atmospherics_engine) "niv" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "medcell"; name = "Medical Cell"; pixel_y = 32 @@ -40184,7 +40184,7 @@ /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) "nNP" = ( -/obj/machinery/door_timer{ +/obj/machinery/status_display/door_timer{ id = "engcell"; name = "Engineering Cell"; pixel_x = -32 diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 47a9b3755cf..6721baa255e 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -107,7 +107,6 @@ GLOBAL_LIST_INIT(WALLITEMS_INTERIOR, typecacheof(list( /obj/machinery/computer/security/telescreen, /obj/machinery/computer/security/telescreen/entertainment, /obj/machinery/defibrillator_mount, - /obj/machinery/door_timer, /obj/machinery/embedded_controller/radio/simple_vent_controller, /obj/machinery/firealarm, /obj/machinery/flasher, diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index a2f2c810301..f8aed583d82 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -1,30 +1,22 @@ -#define CHARS_PER_LINE 5 -#define FONT_SIZE "5pt" -#define FONT_COLOR "#09f" -#define FONT_STYLE "Small Fonts" #define MAX_TIMER 15 MINUTES - #define PRESET_SHORT 2 MINUTES #define PRESET_MEDIUM 3 MINUTES #define PRESET_LONG 5 MINUTES - - -/////////////////////////////////////////////////////////////////////////////////////////////// -// Brig Door control displays. -// Description: This is a controls the timer for the brig doors, displays the timer on itself and -// has a popup window when used, allowing to set the timer. -// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code -// Date: 01/September/2010 -// Programmer: Veryinky -///////////////////////////////////////////////////////////////////////////////////////////////// -/obj/machinery/door_timer +/** + * Brig Door control displays. + * + * This is a controls the timer for the brig doors, displays the timer on itself and + * has a popup window when used, allowing to set the timer. + */ +/obj/machinery/status_display/door_timer name = "door timer" - icon = 'icons/obj/status_display.dmi' - icon_state = "frame" desc = "A remote control for a door." + current_mode = SD_MESSAGE req_access = list(ACCESS_SECURITY) - density = FALSE + text_color = "#F44" + header_text_color = "#F88" + var/id = null // id of linked machinery/lockers var/activation_time = 0 @@ -37,21 +29,15 @@ var/list/flashers = list() ///List of weakrefs to nearby closets var/list/closets = list() + ///needed to send messages to sec radio + var/obj/item/radio/sec_radio - var/obj/item/radio/Radio //needed to send messages to sec radio - - maptext_height = 26 - maptext_width = 32 - maptext_y = -1 - -/obj/machinery/door_timer/Initialize(mapload) +/obj/machinery/status_display/door_timer/Initialize(mapload) . = ..() - Radio = new/obj/item/radio(src) - Radio.set_listening(FALSE) + sec_radio = new/obj/item/radio(src) + sec_radio.set_listening(FALSE) -/obj/machinery/door_timer/Initialize(mapload) - . = ..() if(id != null) for(var/obj/machinery/door/window/brigdoor/M in urange(20, src)) if (M.id == id) @@ -67,29 +53,48 @@ if(!length(doors) && !length(flashers) && length(closets)) atom_break() - update_appearance() - //Main door timer loop, if it's timing and time is >0 reduce time by 1. // if it's less than 0, open door, reset timer // update the door_timer window and the icon -/obj/machinery/door_timer/process() +/obj/machinery/status_display/door_timer/process() if(machine_stat & (NOPOWER|BROKEN)) + // No power, no processing. + update_appearance() + return PROCESS_KILL + + if(!timing) + return PROCESS_KILL + + if(world.time - activation_time >= timer_duration) + timer_end() // open doors, reset timer, clear status screen + update_content() + +/** + * Update the display content. + */ +/obj/machinery/status_display/door_timer/proc/update_content() + var/time_left = time_left(seconds = TRUE) + + if(time_left == 0) + set_messages("", "") return - if(timing) - if(world.time - activation_time >= timer_duration) - timer_end() // open doors, reset timer, clear status screen - update_appearance() + var/disp1 = name + var/disp2 = "[add_leading(num2text((time_left / 60) % 60), 2, "0")]:[add_leading(num2text(time_left % 60), 2, "0")]" + set_messages(disp1, disp2) -// open/closedoor checks if door_timer has power, if so it checks if the -// linked door is open/closed (by density) then opens it/closes it. -/obj/machinery/door_timer/proc/timer_start() +/** + * Starts counting down the timer and closes linked the door. + * The timer is expected to have already been set by set_timer() + */ +/obj/machinery/status_display/door_timer/proc/timer_start() if(machine_stat & (NOPOWER|BROKEN)) return 0 activation_time = world.time timing = TRUE + begin_processing() for(var/datum/weakref/door_ref as anything in doors) var/obj/machinery/door/window/brigdoor/door = door_ref.resolve() @@ -113,20 +118,23 @@ closet.update_appearance() return 1 - -/obj/machinery/door_timer/proc/timer_end(forced = FALSE) - +/** + * Stops the timer and resets the timer to 0, and opens the linked door. + * Arguments: + * * forced - TRUE if it was forced to stop rather than timing out. Will skip radioing, etc. + */ +/obj/machinery/status_display/door_timer/proc/timer_end(forced = FALSE) if(machine_stat & (NOPOWER|BROKEN)) return 0 if(!forced) - Radio.set_frequency(FREQ_SECURITY) - Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY) + sec_radio.set_frequency(FREQ_SECURITY) + sec_radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY) timing = FALSE activation_time = null set_timer(0) - update_appearance() + end_processing() for(var/datum/weakref/door_ref as anything in doors) var/obj/machinery/door/window/brigdoor/door = door_ref.resolve() @@ -151,67 +159,37 @@ return 1 - -/obj/machinery/door_timer/proc/time_left(seconds = FALSE) - . = max(0,timer_duration - (activation_time ? world.time - activation_time : 0)) +/** + * Return time left. + * Arguments: + * * seconds - return time in seconds it TRUE, else deciseconds. + */ +/obj/machinery/status_display/door_timer/proc/time_left(seconds = FALSE) + . = max(0, timer_duration - (activation_time ? world.time - activation_time : 0)) if(seconds) . /= 10 -/obj/machinery/door_timer/proc/set_timer(value) - var/new_time = clamp(value,0,MAX_TIMER) +/** + * Set the timer. Does NOT automatically start counting down, but does update the display. + * + * returns TRUE if no change occurred + * + * Arguments: + * value - time in deciseconds to set the timer for. + */ +/obj/machinery/status_display/door_timer/proc/set_timer(value) + var/new_time = clamp(value, 0, MAX_TIMER) . = new_time == timer_duration //return 1 on no change timer_duration = new_time + update_content() -/obj/machinery/door_timer/ui_interact(mob/user, datum/tgui/ui) +/obj/machinery/status_display/door_timer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "BrigTimer", name) ui.open() -//icon update function -// if NOPOWER, display blank -// if BROKEN, display blue screen of death icon AI uses -// if timing=true, run update display function -/obj/machinery/door_timer/update_icon() - . = ..() - if(machine_stat & (NOPOWER)) - return - - if(machine_stat & (BROKEN)) - set_picture("ai_bsod") - return - - if(timing) - var/disp1 = id - var/time_left = time_left(seconds = TRUE) - var/disp2 = "[add_leading(num2text((time_left / 60) % 60), 2, "0")]:[add_leading(num2text(time_left % 60), 2, "0")]" - if(length(disp2) > CHARS_PER_LINE) - disp2 = "Error" - update_display(disp1, disp2) - else - if(maptext) - maptext = "" - return - - -// Adds an icon in case the screen is broken/off, stolen from status_display.dm -/obj/machinery/door_timer/proc/set_picture(state) - if(maptext) - maptext = "" - cut_overlays() - add_overlay(mutable_appearance('icons/obj/status_display.dmi', state)) - - -//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display -// Stolen from status_display -/obj/machinery/door_timer/proc/update_display(line1, line2) - line1 = uppertext(line1) - line2 = uppertext(line2) - var/new_text = {"
[line1]
[line2]
"} - if(maptext != new_text) - maptext = new_text - -/obj/machinery/door_timer/ui_data() +/obj/machinery/status_display/door_timer/ui_data() var/list/data = list() var/time_left = time_left(seconds = TRUE) data["seconds"] = round(time_left % 60) @@ -228,8 +206,7 @@ break return data - -/obj/machinery/door_timer/ui_act(action, params) +/obj/machinery/status_display/door_timer/ui_act(action, params) . = ..() if(.) return @@ -284,13 +261,7 @@ else . = FALSE - #undef PRESET_SHORT #undef PRESET_MEDIUM #undef PRESET_LONG - #undef MAX_TIMER -#undef FONT_SIZE -#undef FONT_COLOR -#undef FONT_STYLE -#undef CHARS_PER_LINE diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index b9762f2308c..b99f12892be 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -1,10 +1,8 @@ // Status display // (formerly Countdown timer display) -#define CHARS_PER_LINE 5 -#define FONT_SIZE "5pt" -#define FONT_COLOR "#09f" -#define FONT_STYLE "Small Fonts" +#define MAX_STATIC_WIDTH 25 +#define FONT_STYLE "5pt 'Small Fonts'" #define SCROLL_RATE (0.04 SECONDS) // time per pixel #define LINE1_Y -8 #define LINE2_Y -15 @@ -20,7 +18,6 @@ desc = null icon = 'icons/obj/status_display.dmi' icon_state = "frame" - base_icon_state = "unanchoredstatusdisplay" verb_say = "beeps" verb_ask = "beeps" verb_exclaim = "beeps" @@ -34,6 +31,11 @@ var/message1 = "" var/message2 = "" + /// Normal text color + var/text_color = "#09F" + /// Color for headers, eg. "- ETA -" + var/header_text_color = "#2CF" + /obj/item/wallframe/status_display name = "status display frame" desc = "Used to build status displays, just secure to the wall." @@ -42,6 +44,11 @@ result_path = /obj/machinery/status_display/evac pixel_shift = 32 +//makes it go on the wall when built +/obj/machinery/status_display/Initialize(mapload, ndir, building) + . = ..() + update_appearance() + /obj/machinery/status_display/wrench_act_secondary(mob/living/user, obj/item/tool) . = ..() balloon_alert(user, "[anchored ? "un" : ""]securing...") @@ -125,7 +132,7 @@ if(overlay) qdel(overlay) - var/obj/effect/overlay/status_display_text/new_status_display_text = new(src, line_y, message) + var/obj/effect/overlay/status_display_text/new_status_display_text = new(src, line_y, message, text_color, header_text_color) vis_contents += new_status_display_text return new_status_display_text @@ -198,9 +205,9 @@ if (message1_overlay || message2_overlay) . += "The display says:" if (message1_overlay.message) - . += "
\t[html_encode(message1_overlay.message)]" + . += "\t[html_encode(message1_overlay.message)]" if (message2_overlay.message) - . += "
\t[html_encode(message2_overlay.message)]" + . += "\t[html_encode(message2_overlay.message)]" // Helper procs for child display types. /obj/machinery/status_display/proc/display_shuttle_status(obj/docking_port/mobile/shuttle) @@ -209,28 +216,14 @@ set_messages("shutl?","") return PROCESS_KILL else if(shuttle.timer) - var/line1 = "-[shuttle.getModeStr()]-" + var/line1 = "- [shuttle.getModeStr()] -" var/line2 = shuttle.getTimerStr() - if(length_char(line2) > CHARS_PER_LINE) - line2 = "error" set_messages(line1, line2) else // don't kill processing, the timer might turn back on set_messages("", "") -/obj/machinery/status_display/proc/examine_shuttle(mob/user, obj/docking_port/mobile/shuttle) - if (shuttle) - var/modestr = shuttle.getModeStr() - if (modestr) - if (shuttle.timer) - modestr = "
\t[modestr]: [shuttle.getTimerStr()]" - else - modestr = "
\t[modestr]" - return "The display says:
\t[shuttle.name][modestr]" - else - return "The display says:
\tShuttle missing!" - /obj/machinery/status_display/Destroy() remove_messages() return ..() @@ -242,39 +235,93 @@ icon = 'icons/obj/status_display.dmi' vis_flags = VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID + /// The message this overlay is displaying. var/message -/obj/effect/overlay/status_display_text/Initialize(mapload, yoffset, line) + // If the line is short enough to not marquee, and it matches this, it's a header. + var/static/regex/header_regex = regex("^-.*-$") + + /// Width of each character, including kerning gap afterwards. + /// We don't use rich text or anything fancy, so we can bake these values. + var/static/list/char_widths = list( + // ! " # $ % & ' ( ) * + , - . / + 1, 2, 3, 5, 4, 5, 5, 2, 3, 3, 3, 4, 2, 3, 2, 3, + // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 3, 3, 3, 3, + // @ A B C D E F G H I J K L M N O + 7, 5, 5, 5, 5, 4, 4, 5, 5, 2, 4, 5, 4, 6, 5, 5, + // P Q R S T U V W X Y Z [ \ ] ^ _ + 5, 5, 5, 5, 4, 5, 4, 6, 4, 4, 4, 3, 3, 3, 4, 4, + // ` a b c d e f g h i j k l m n o + 3, 5, 5, 5, 5, 4, 4, 5, 5, 2, 4, 5, 4, 6, 5, 5, + // p q r s t u v w x y z { | } ~ + 5, 5, 5, 5, 4, 5, 4, 6, 4, 4, 4, 3, 2, 3, 4, + ) + +/obj/effect/overlay/status_display_text/Initialize(mapload, yoffset, line, text_color, header_text_color) . = ..() maptext_y = yoffset message = line - var/line_length = length_char(line) + var/line_width = measure_width(line) - if(line_length > CHARS_PER_LINE) + if(line_width > MAX_STATIC_WIDTH) // Marquee text - var/marquee_message = "[line] • [line] • [line]" - var/marquee_length = line_length * 3 + 6 - maptext = generate_text(marquee_message, center = FALSE) - maptext_width = 6 * marquee_length - maptext_x = 32 + var/marquee_message = "[line] - [line] - [line]" + + // Width of full content. Must of these is never revealed unless the user inputted a single character. + var/full_marquee_width = measure_width(marquee_message) + // We loop after only this much has passed. + var/looping_marquee_width = measure_width("[line] - ") + + maptext = generate_text(marquee_message, center = FALSE, text_color = text_color) + maptext_width = full_marquee_width + maptext_x = 0 // Mask off to fit in screen. add_filter("mask", 1, alpha_mask_filter(icon = icon(icon, "outline"))) // Scroll. - var/width = 4 * marquee_length - var/time = (width + 32) * SCROLL_RATE - animate(src, maptext_x = -width, time = time, loop = -1) - animate(maptext_x = 32, time = 0) + var/time = looping_marquee_width * SCROLL_RATE + animate(src, maptext_x = -looping_marquee_width, time = time, loop = -1) + animate(maptext_x = 0, time = 0) else // Centered text - maptext = generate_text(line, center = TRUE) + var/color = header_regex.Find(line) ? header_text_color : text_color + maptext = generate_text(line, center = TRUE, text_color = color) maptext_x = 0 -/obj/effect/overlay/status_display_text/proc/generate_text(text, center) - return {"
[text]
"} +/** + * A hyper-streamlined version of MeasureText that doesn't support different fonts, rich formatting, or multiline. + * But it also doesn't require a client. + * + * Returns the width in pixels + * + * Arguments: + * * text - the text to measure + */ +/obj/effect/overlay/status_display_text/proc/measure_width(text) + var/width = 0 + for(var/text_idx in 1 to length(text)) + var/ascii = text2ascii(text, text_idx) + if(!(ascii in 0x20 to 0x7E)) + // So we can't possibly runtime, even though the input should be in range already. + width += 3 + continue + width += char_widths[ascii - 0x1F] + + return width + +/** + * Generate the actual maptext. + * Arguments: + * * text - the text to display + * * center - center the text if TRUE, otherwise left-align + * * text_color - the text color + */ +/obj/effect/overlay/status_display_text/proc/generate_text(text, center, text_color) + return {"
[text]
"} /// Evac display which shows shuttle timer or message set by Command. /obj/machinery/status_display/evac @@ -285,11 +332,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) -//makes it go on the wall when built -/obj/machinery/status_display/Initialize(mapload, ndir, building) - . = ..() - update_appearance() - /obj/machinery/status_display/evac/Initialize(mapload) . = ..() // register for radio system @@ -328,13 +370,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) set_picture(last_picture) return PROCESS_KILL -/obj/machinery/status_display/evac/examine(mob/user) - . = ..() - if(current_mode == SD_EMERGENCY) - . += examine_shuttle(user, SSshuttle.emergency) - else if(!message1 && !message2) - . += "The display is blank." - /obj/machinery/status_display/evac/receive_signal(datum/signal/signal) switch(signal.data["command"]) if("blank") @@ -359,6 +394,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) /obj/machinery/status_display/supply name = "supply display" current_mode = SD_MESSAGE + text_color = "#F90" + header_text_color = "#FC2" /obj/machinery/status_display/supply/process() if(machine_stat & NOPOWER) @@ -381,26 +418,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) line1 = "" line2 = "" else - line1 = "CARGO" + line1 = "- [SSshuttle.supply.getModeStr()] -" line2 = SSshuttle.supply.getTimerStr() - if(length_char(line2) > CHARS_PER_LINE) - line2 = "Error" set_messages(line1, line2) -/obj/machinery/status_display/supply/examine(mob/user) - . = ..() - var/obj/docking_port/mobile/shuttle = SSshuttle.supply - var/shuttleMsg = null - if (shuttle.mode == SHUTTLE_IDLE) - if (is_station_level(shuttle.z)) - shuttleMsg = "Docked" - else - shuttleMsg = "[shuttle.getModeStr()]: [shuttle.getTimerStr()]" - if (shuttleMsg) - . += "The display says:
\t[shuttleMsg]" - else - . += "The display is blank." - /// General-purpose shuttle status display. /obj/machinery/status_display/shuttle @@ -408,6 +429,9 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) current_mode = SD_MESSAGE var/shuttle_id + text_color = "#0F5" + header_text_color = "#2FC" + /obj/machinery/status_display/shuttle/process() if(!shuttle_id || (machine_stat & NOPOWER)) // No power, no processing. @@ -416,13 +440,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) return display_shuttle_status(SSshuttle.getShuttle(shuttle_id)) -/obj/machinery/status_display/shuttle/examine(mob/user) - . = ..() - if(shuttle_id) - . += examine_shuttle(user, SSshuttle.getShuttle(shuttle_id)) - else - . += "The display is blank." - /obj/machinery/status_display/shuttle/vv_edit_var(var_name, var_value) . = ..() if(!.) @@ -574,9 +591,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/ai, 32) connected_display.receive_signal(status_signal) -#undef CHARS_PER_LINE -#undef FONT_SIZE -#undef FONT_COLOR +#undef MAX_STATIC_WIDTH #undef FONT_STYLE #undef SCROLL_RATE #undef LINE1_Y diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index 04515edffcd..a7839befe13 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -55,7 +55,6 @@ if(temp.critical_machine) //Skip doors in critical positions, such as the SM chamber. continue temp.prison_open() - else if(istype(O, /obj/machinery/door_timer)) - var/obj/machinery/door_timer/temp = O + else if(istype(O, /obj/machinery/status_display/door_timer)) + var/obj/machinery/status_display/door_timer/temp = O temp.timer_end(forced = TRUE) - diff --git a/tools/UpdatePaths/Scripts/69153_brigdoors.txt b/tools/UpdatePaths/Scripts/69153_brigdoors.txt new file mode 100644 index 00000000000..68075fa589b --- /dev/null +++ b/tools/UpdatePaths/Scripts/69153_brigdoors.txt @@ -0,0 +1 @@ +/obj/machinery/door_timer : /obj/machinery/status_display/door_timer{@OLD} \ No newline at end of file