mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
TGUI Backend Tweaks & Fixes
This commit is contained in:
@@ -289,6 +289,11 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
/proc/format_frequency(var/f)
|
||||
return "[round(f / 10)].[f % 10]"
|
||||
|
||||
//Opposite of format, returns as a number
|
||||
/proc/unformat_frequency(frequency)
|
||||
frequency = text2num(frequency)
|
||||
return frequency * 10
|
||||
|
||||
|
||||
|
||||
//This will update a mob's name, real_name, mind.name, data_core records, pda and id
|
||||
|
||||
@@ -148,6 +148,41 @@ var/list/radiochannels = list(
|
||||
"Talon" = TALON_FREQ //VOREStation Add
|
||||
)
|
||||
|
||||
// Hey, if anyone ever needs to update tgui/packages/tgui/constants.js with new radio channels
|
||||
// I've kept this around just for you.
|
||||
/* /client/verb/generate_tgui_radio_constants()
|
||||
set name = "Generate TGUI Radio Constants"
|
||||
set category = "Generate TGUI Radio Constants"
|
||||
|
||||
var/list/channel_info = list()
|
||||
|
||||
for(var/i in RADIO_LOW_FREQ to RADIO_HIGH_FREQ)
|
||||
for(var/key in radiochannels)
|
||||
if(i == radiochannels[key])
|
||||
channel_info.Add(list(list("name" = key, "freq" = i, "color" = frequency_span_class(i))))
|
||||
|
||||
for(var/list/channel in channel_info)
|
||||
switch(channel["color"])
|
||||
if("deadsay") channel["color"] = "#530FAD"
|
||||
if("radio") channel["color"] = "#008000"
|
||||
if("deptradio") channel["color"] = "#ff00ff"
|
||||
if("newscaster") channel["color"] = "#750000"
|
||||
if("comradio") channel["color"] = "#193A7A"
|
||||
if("syndradio") channel["color"] = "#6D3F40"
|
||||
if("centradio") channel["color"] = "#5C5C8A"
|
||||
if("airadio") channel["color"] = "#FF00FF"
|
||||
if("entradio") channel["color"] = "#339966"
|
||||
if("secradio") channel["color"] = "#A30000"
|
||||
if("engradio") channel["color"] = "#A66300"
|
||||
if("medradio") channel["color"] = "#008160"
|
||||
if("sciradio") channel["color"] = "#993399"
|
||||
if("supradio") channel["color"] = "#5F4519"
|
||||
if("srvradio") channel["color"] = "#6eaa2c"
|
||||
if("expradio") channel["color"] = "#555555"
|
||||
|
||||
to_chat(src, json_encode(channel_info)) */
|
||||
|
||||
|
||||
// central command channels, i.e deathsquid & response teams
|
||||
var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
|
||||
|
||||
|
||||
@@ -332,6 +332,19 @@ var/global/list/PDA_Manifest = list()
|
||||
var/datum/job/J = SSjob.get_job(assignment)
|
||||
hidden = J?.offmap_spawn
|
||||
|
||||
/* Note: Due to cached_character_icon, a number of emergent properties occur due to the initialization
|
||||
* order of readied-up vs latejoiners. Namely, latejoiners will get a uniform in their datacore picture, but readied-up will
|
||||
* not. This is due to the fact that SSticker calls data_core.manifest_inject() inside of ticker/proc/create_characters(),
|
||||
* but does not equip them until ticker/proc/equip_characters(), which is called later. So, this proc is literally called before
|
||||
* they ever get their equipment, and so it can't get a picture of them in their equipment.
|
||||
* Latejoiners do not have this problem, because /mob/new_player/proc/AttemptLateSpawn calls EquipRank() before it calls
|
||||
* this proc, which means that they're already clothed by the time they get their picture taken here.
|
||||
* The COMPILE_OVERLAYS() here is just to bypass SSoverlays taking for-fucking-ever to update the mob, since we're about to
|
||||
* take a picture of them, we want all the overlays.
|
||||
*/
|
||||
COMPILE_OVERLAYS(H)
|
||||
SSoverlays.queue -= H
|
||||
|
||||
var/id = generate_record_id()
|
||||
//General Record
|
||||
var/datum/data/record/G = CreateGeneralRecord(H, id, hidden)
|
||||
@@ -418,8 +431,8 @@ var/global/list/PDA_Manifest = list()
|
||||
var/icon/side
|
||||
if(H)
|
||||
var/icon/charicon = cached_character_icon(H)
|
||||
front = icon(charicon, dir = SOUTH)
|
||||
side = icon(charicon, dir = WEST)
|
||||
front = icon(charicon, dir = SOUTH, frame = 1)
|
||||
side = icon(charicon, dir = WEST, frame = 1)
|
||||
else // Sending null things through browse_rsc() makes a runtime and breaks the console trying to view the record.
|
||||
front = icon('html/images/no_image32.png')
|
||||
side = icon('html/images/no_image32.png')
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
/datum/wires/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
if(!interactable(user))
|
||||
|
||||
@@ -455,13 +455,13 @@
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/tgui_act(action, params)
|
||||
if(..())
|
||||
return FALSE // don't update uis
|
||||
return TRUE
|
||||
if(!istype(usr.loc, /turf))
|
||||
return FALSE // don't update uis
|
||||
return TRUE
|
||||
if(!src || !src.connected)
|
||||
return FALSE // don't update uis
|
||||
return TRUE
|
||||
if(irradiating) // Make sure that it isn't already irradiating someone...
|
||||
return FALSE // don't update uis
|
||||
return TRUE
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
|
||||
/obj/machinery/sleeper/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
if(!controls_inside && usr == occupant)
|
||||
return
|
||||
if(panel_open)
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
|
||||
/obj/machinery/bodyscanner/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
switch(action)
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
|
||||
/obj/machinery/computer/operating/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
|
||||
/obj/machinery/computer/cloning/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
|
||||
/obj/machinery/computer/med_data/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(!data_core.general.Find(active1))
|
||||
active1 = null
|
||||
@@ -508,3 +508,6 @@
|
||||
icon_screen = "medlaptop"
|
||||
circuit = /obj/item/weapon/circuitboard/med_data/laptop
|
||||
density = 0
|
||||
|
||||
#undef FIELD
|
||||
#undef MED_FIELD
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/tgui_act(action, params)
|
||||
if(..() || usr == occupant)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
switch(action)
|
||||
|
||||
@@ -213,6 +213,13 @@ Class Procs:
|
||||
/obj/machinery/proc/inoperable(var/additional_flags = 0)
|
||||
return (stat & (NOPOWER | BROKEN | additional_flags))
|
||||
|
||||
// Duplicate of below because we don't want to fuck around with CanUseTopic in TGUI
|
||||
// TODO: Replace this with can_interact from /tg/
|
||||
/obj/machinery/tgui_status(mob/user)
|
||||
if(!interact_offline && (stat & (NOPOWER | BROKEN)))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/CanUseTopic(var/mob/user)
|
||||
if(!interact_offline && (stat & (NOPOWER | BROKEN)))
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
/datum/computer_file/program/nano_host()
|
||||
return computer.nano_host()
|
||||
|
||||
/datum/computer_file/program/tgui_host()
|
||||
return computer.tgui_host()
|
||||
|
||||
/datum/computer_file/program/clone()
|
||||
var/datum/computer_file/program/temp = ..()
|
||||
temp.required_access = required_access
|
||||
|
||||
@@ -379,7 +379,7 @@
|
||||
|
||||
/obj/machinery/chem_master/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(tgui_act_modal(action, params, ui, state))
|
||||
return TRUE
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
|
||||
/obj/machinery/chemical_dispenser/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
switch(action)
|
||||
|
||||
@@ -260,18 +260,18 @@
|
||||
|
||||
/obj/machinery/disposal/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(usr.loc == src)
|
||||
to_chat(usr, "<span class='warning'>You cannot reach the controls from inside.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(mode==-1 && action != "eject") // If the mode is -1, only allow ejection
|
||||
to_chat(usr, "<span class='warning'>The disposal units power is disabled.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
/obj/machinery/computer/transhuman/resleeving/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional ui datum/tgui The UI to be updated, if it exists.
|
||||
* optional parent_ui datum/tgui A parent UI that, when closed, closes this UI as well.
|
||||
*/
|
||||
|
||||
/datum/proc/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
/datum/proc/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null)
|
||||
return FALSE // Not implemented.
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@
|
||||
*
|
||||
* return list Data to be sent to the UI.
|
||||
*/
|
||||
/datum/proc/tgui_data(mob/user)
|
||||
/datum/proc/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||
return list() // Not implemented.
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,12 +12,15 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
||||
var/list/using_access
|
||||
|
||||
var/tgui_id
|
||||
var/ntos = FALSE
|
||||
|
||||
/datum/tgui_module/New(var/host)
|
||||
src.host = host
|
||||
if(ntos)
|
||||
tgui_id = "Ntos" + tgui_id
|
||||
|
||||
/datum/tgui_module/tgui_host()
|
||||
return host ? host : src
|
||||
return host ? host.tgui_host() : src
|
||||
|
||||
/datum/tgui_module/tgui_close(mob/user)
|
||||
if(host)
|
||||
@@ -43,4 +46,34 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
||||
if(access in I.access)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
return 0
|
||||
|
||||
/datum/tgui_module/tgui_static_data()
|
||||
. = ..()
|
||||
|
||||
var/obj/item/modular_computer/host = tgui_host()
|
||||
if(istype(host))
|
||||
. += host.get_header_data()
|
||||
|
||||
/datum/tgui_module/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/obj/item/modular_computer/host = tgui_host()
|
||||
if(istype(host))
|
||||
if(action == "PC_exit")
|
||||
host.kill_program()
|
||||
return TRUE
|
||||
if(action == "PC_shutdown")
|
||||
host.shutdown_computer()
|
||||
return TRUE
|
||||
if(action == "PC_minimize")
|
||||
host.minimize_program(usr)
|
||||
return TRUE
|
||||
|
||||
// Just a nice little default interact in case the subtypes don't need any special behavior here
|
||||
/datum/tgui_module/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, tgui_id, name)
|
||||
ui.open()
|
||||
@@ -144,7 +144,7 @@
|
||||
return data
|
||||
|
||||
/datum/tgui_module/camera/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/data = ..()
|
||||
data["mapRef"] = map_name
|
||||
var/list/cameras = get_available_cameras(user)
|
||||
data["cameras"] = list()
|
||||
@@ -160,11 +160,11 @@
|
||||
|
||||
/datum/tgui_module/camera/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(action && !issilicon(usr))
|
||||
playsound(tgui_host(), "terminal_type", 50, 1)
|
||||
|
||||
|
||||
if(action == "switch_camera")
|
||||
var/c_tag = params["name"]
|
||||
var/list/cameras = get_available_cameras(usr)
|
||||
@@ -287,33 +287,7 @@
|
||||
// If/when that is done, just move all the PC_ specific data and stuff to the modular computers themselves
|
||||
// instead of copying this approach here.
|
||||
/datum/tgui_module/camera/ntos
|
||||
tgui_id = "NtosCameraConsole"
|
||||
|
||||
/datum/tgui_module/camera/ntos/tgui_state()
|
||||
return GLOB.tgui_ntos_state
|
||||
|
||||
/datum/tgui_module/camera/ntos/tgui_static_data()
|
||||
. = ..()
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
. += host.computer.get_header_data()
|
||||
|
||||
/datum/tgui_module/camera/ntos/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
if(action == "PC_exit")
|
||||
host.computer.kill_program()
|
||||
return TRUE
|
||||
if(action == "PC_shutdown")
|
||||
host.computer.shutdown_computer()
|
||||
return TRUE
|
||||
if(action == "PC_minimize")
|
||||
host.computer.minimize_program(usr)
|
||||
return TRUE
|
||||
ntos = TRUE
|
||||
|
||||
// ERT Version provides some additional networks.
|
||||
/datum/tgui_module/camera/ntos/ert
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
return TRUE
|
||||
if("setZLevel")
|
||||
ui.set_map_z_level(params["mapZLevel"])
|
||||
SStgui.update_uis(src)
|
||||
return TRUE
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
var/z = get_z(user)
|
||||
@@ -43,7 +43,7 @@
|
||||
ui.open()
|
||||
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_data(mob/user, ui_key = "main", datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
/datum/tgui_module/crew_monitor/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["isAI"] = isAI(user)
|
||||
@@ -59,33 +59,7 @@
|
||||
return data
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos
|
||||
tgui_id = "NtosCrewMonitor"
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos/tgui_state(mob/user)
|
||||
return GLOB.tgui_ntos_state
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos/tgui_static_data()
|
||||
. = ..()
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
. += host.computer.get_header_data()
|
||||
|
||||
/datum/tgui_module/crew_monitor/ntos/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/datum/computer_file/program/host = tgui_host()
|
||||
if(istype(host) && host.computer)
|
||||
if(action == "PC_exit")
|
||||
host.computer.kill_program()
|
||||
return TRUE
|
||||
if(action == "PC_shutdown")
|
||||
host.computer.shutdown_computer()
|
||||
return TRUE
|
||||
if(action == "PC_minimize")
|
||||
host.computer.minimize_program(usr)
|
||||
return TRUE
|
||||
ntos = TRUE
|
||||
|
||||
// Subtype for glasses_state
|
||||
/datum/tgui_module/crew_monitor/glasses
|
||||
|
||||
@@ -36,13 +36,29 @@ GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new)
|
||||
return STATUS_DISABLED // Otherwise they can keep the UI open.
|
||||
|
||||
/mob/living/silicon/ai/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. < STATUS_INTERACTIVE)
|
||||
. = shared_tgui_interaction()
|
||||
if(. != STATUS_INTERACTIVE)
|
||||
return
|
||||
|
||||
// The AI can interact with anything it can see nearby, or with cameras while wireless control is enabled.
|
||||
if(!control_disabled && can_see(src_object))
|
||||
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
|
||||
// unless it's on the same level as the object it's interacting with.
|
||||
var/turf/T = get_turf(src_object)
|
||||
if(!T || !(z == T.z || (T.z in using_map.player_levels)))
|
||||
return STATUS_CLOSE
|
||||
|
||||
// If an object is in view then we can interact with it
|
||||
if(src_object in view(client.view, src))
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
|
||||
if(is_in_chassis())
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
|
||||
return STATUS_CLOSE
|
||||
return STATUS_INTERACTIVE
|
||||
else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/simple_animal/default_can_use_tgui_topic(src_object)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* tgui state: ntos_state
|
||||
*
|
||||
* Checks a number of things -- mostly physical distance for humans and view for robots.
|
||||
* This is basically the same as default, except instead of src_object, it uses the computer
|
||||
* it's attached to.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_ntos_state, /datum/tgui_state/ntos, new)
|
||||
|
||||
/datum/tgui_state/ntos/can_use_topic(src_object, mob/user)
|
||||
var/datum/computer_file/program/P = src_object
|
||||
if(!istype(P) || !P.computer)
|
||||
return FALSE
|
||||
return user.default_can_use_tgui_topic(P.computer) // Call the individual mob-overridden procs.
|
||||
@@ -34,8 +34,12 @@
|
||||
var/status = STATUS_INTERACTIVE
|
||||
/// Topic state used to determine status/interactability.
|
||||
var/datum/tgui_state/state = null
|
||||
// The map z-level to display.
|
||||
/// The map z-level to display.
|
||||
var/map_z_level = 1
|
||||
/// The Parent UI
|
||||
var/datum/tgui/parent_ui
|
||||
/// Children of this UI
|
||||
var/list/children = list()
|
||||
|
||||
/**
|
||||
* public
|
||||
@@ -46,12 +50,13 @@
|
||||
* required src_object datum The object or datum which owns the UI.
|
||||
* required interface string The interface used to render the UI.
|
||||
* optional title string The title of the UI.
|
||||
* optional parent_ui datum/tgui The parent of this UI.
|
||||
* optional ui_x int Deprecated: Window width.
|
||||
* optional ui_y int Deprecated: Window height.
|
||||
*
|
||||
* return datum/tgui The requested UI.
|
||||
*/
|
||||
/datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y)
|
||||
/datum/tgui/New(mob/user, datum/src_object, interface, title, datum/tgui/parent_ui, ui_x, ui_y)
|
||||
src.user = user
|
||||
src.src_object = src_object
|
||||
src.window_key = "[REF(src_object)]-main"
|
||||
@@ -59,6 +64,9 @@
|
||||
if(title)
|
||||
src.title = title
|
||||
src.state = src_object.tgui_state()
|
||||
src.parent_ui = parent_ui
|
||||
if(parent_ui)
|
||||
parent_ui.children += src
|
||||
// Deprecated
|
||||
if(ui_x && ui_y)
|
||||
src.window_size = list(ui_x, ui_y)
|
||||
@@ -104,6 +112,9 @@
|
||||
if(closing)
|
||||
return
|
||||
closing = TRUE
|
||||
for(var/datum/tgui/child in children)
|
||||
child.close()
|
||||
children.Cut()
|
||||
// If we don't have window_id, open proc did not have the opportunity
|
||||
// to finish, therefore it's safe to skip this whole block.
|
||||
if(window)
|
||||
@@ -115,6 +126,7 @@
|
||||
src_object.tgui_close(user)
|
||||
SStgui.on_close(src)
|
||||
state = null
|
||||
parent_ui = null
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
@@ -209,7 +221,7 @@
|
||||
"observer" = isobserver(user),
|
||||
),
|
||||
)
|
||||
var/data = custom_data || with_data && src_object.tgui_data(user)
|
||||
var/data = custom_data || with_data && src_object.tgui_data(user, src, state)
|
||||
if(data)
|
||||
json_data["data"] = data
|
||||
var/static_data = with_static_data && src_object.tgui_static_data(user)
|
||||
@@ -244,7 +256,7 @@
|
||||
return
|
||||
// Update through a normal call to ui_interact
|
||||
if(status != STATUS_DISABLED && (autoupdate || force))
|
||||
src_object.tgui_interact(user, src)
|
||||
src_object.tgui_interact(user, src, parent_ui)
|
||||
return
|
||||
// Update status only
|
||||
var/needs_update = process_status()
|
||||
@@ -262,6 +274,8 @@
|
||||
/datum/tgui/proc/process_status()
|
||||
var/prev_status = status
|
||||
status = src_object.tgui_status(user, state)
|
||||
if(parent_ui)
|
||||
status = min(status, parent_ui.status)
|
||||
return prev_status != status
|
||||
|
||||
/datum/tgui/proc/log_message(message)
|
||||
|
||||
@@ -190,9 +190,9 @@
|
||||
/datum/tgui_window/proc/send_asset(datum/asset/asset)
|
||||
if(!client || !asset)
|
||||
return
|
||||
// if(istype(asset, /datum/asset/spritesheet))
|
||||
// var/datum/asset/spritesheet/spritesheet = asset
|
||||
// send_message("asset/stylesheet", spritesheet.css_filename())
|
||||
if(istype(asset, /datum/asset/spritesheet))
|
||||
var/datum/asset/spritesheet/spritesheet = asset
|
||||
send_message("asset/stylesheet", spritesheet.css_filename())
|
||||
send_message("asset/mappings", asset.get_url_mappings())
|
||||
sent_assets += list(asset)
|
||||
asset.send(client)
|
||||
|
||||
@@ -369,7 +369,7 @@ rules:
|
||||
# max-depth: error
|
||||
## Enforce a maximum line length
|
||||
max-len: [error, {
|
||||
code: 80,
|
||||
code: 120, # Bump to 140 if this is still too in the way
|
||||
## Ignore imports
|
||||
ignorePattern: '^(import\s.+\sfrom\s|.*require\()',
|
||||
ignoreUrls: true,
|
||||
|
||||
@@ -77,7 +77,7 @@ input. The input's `action` and `params` are passed to the proc.
|
||||
```dm
|
||||
/obj/machinery/my_machine/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
if(action == "change_color")
|
||||
var/new_color = params["color"]
|
||||
if(!(color in allowed_coors))
|
||||
@@ -305,7 +305,7 @@ upon code review):
|
||||
|
||||
/obj/copypasta/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("copypasta")
|
||||
var/newvar = params["var"]
|
||||
|
||||
@@ -91,7 +91,7 @@ export const toTitleCase = str => {
|
||||
return str;
|
||||
}
|
||||
// Handle string
|
||||
const WORDS_UPPER = ['Id', 'Tv'];
|
||||
const WORDS_UPPER = ['Id', 'Tv', 'Rcd'];
|
||||
const WORDS_LOWER = [
|
||||
'A', 'An', 'And', 'As', 'At', 'But', 'By', 'For', 'For', 'From', 'In',
|
||||
'Into', 'Near', 'Nor', 'Of', 'On', 'Onto', 'Or', 'The', 'To', 'With',
|
||||
@@ -105,7 +105,7 @@ export const toTitleCase = str => {
|
||||
}
|
||||
for (let word of WORDS_UPPER) {
|
||||
const regex = new RegExp('\\b' + word + '\\b', 'g');
|
||||
currentStr = currentStr.replace(regex, str => str.toLowerCase());
|
||||
currentStr = currentStr.replace(regex, str => str.toUpperCase());
|
||||
}
|
||||
return currentStr;
|
||||
};
|
||||
|
||||
@@ -52,16 +52,18 @@ export class Dropdown extends Component {
|
||||
{option}
|
||||
</div>
|
||||
));
|
||||
ops.unshift((
|
||||
<div
|
||||
key={placeholder}
|
||||
className="Dropdown__menuentry"
|
||||
onClick={() => {
|
||||
this.setSelected(null);
|
||||
}}>
|
||||
-- {placeholder} --
|
||||
</div>
|
||||
));
|
||||
if (placeholder) {
|
||||
ops.unshift((
|
||||
<div
|
||||
key={placeholder}
|
||||
className="Dropdown__menuentry"
|
||||
onClick={() => {
|
||||
this.setSelected(null);
|
||||
}}>
|
||||
-- {placeholder} --
|
||||
</div>
|
||||
));
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
@@ -73,6 +75,7 @@ export class Dropdown extends Component {
|
||||
noscroll,
|
||||
nochevron,
|
||||
width,
|
||||
maxHeight,
|
||||
onClick,
|
||||
selected,
|
||||
disabled,
|
||||
@@ -92,6 +95,7 @@ export class Dropdown extends Component {
|
||||
tabIndex="-1"
|
||||
style={{
|
||||
'width': width,
|
||||
'max-height': maxHeight,
|
||||
}}
|
||||
className={classes([
|
||||
noscroll && 'Dropdown__menu-noscroll' || 'Dropdown__menu',
|
||||
|
||||
@@ -2,16 +2,15 @@ import { Box, Icon, Tooltip } from '.';
|
||||
import { Component } from 'inferno';
|
||||
import { useBackend } from "../backend";
|
||||
import { resolveAsset } from '../assets';
|
||||
import { logger } from '../logging';
|
||||
|
||||
export class NanoMap extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// Auto center based on window size
|
||||
const Xcenter = (window.innerWidth / 2) - 256;
|
||||
|
||||
this.state = {
|
||||
offsetX: Xcenter,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
transform: 'none',
|
||||
dragging: false,
|
||||
@@ -42,8 +41,8 @@ export class NanoMap extends Component {
|
||||
const newOffsetX = e.screenX - state.originX;
|
||||
const newOffsetY = e.screenY - state.originY;
|
||||
if (prevState.dragging) {
|
||||
state.offsetX += newOffsetX;
|
||||
state.offsetY += newOffsetY;
|
||||
state.offsetX += (newOffsetX / this.props.zoom);
|
||||
state.offsetY += (newOffsetY / this.props.zoom);
|
||||
state.originX = e.screenX;
|
||||
state.originY = e.screenY;
|
||||
} else {
|
||||
@@ -71,11 +70,12 @@ export class NanoMap extends Component {
|
||||
const { offsetX, offsetY } = this.state;
|
||||
const { children, zoom, reset } = this.props;
|
||||
|
||||
let matrix
|
||||
= `matrix(${zoom}, 0, 0, ${zoom}, ${offsetX * zoom}, ${offsetY * zoom})`;
|
||||
|
||||
const newStyle = {
|
||||
width: '512px',
|
||||
height: '512px',
|
||||
"margin-top": offsetY + 'px',
|
||||
"margin-left": offsetX + 'px',
|
||||
width: '560px',
|
||||
height: '560px',
|
||||
"overflow": "hidden",
|
||||
"position": "relative",
|
||||
"padding": "0px",
|
||||
@@ -83,8 +83,7 @@ export class NanoMap extends Component {
|
||||
"url("+config.map+"_nanomap_z"+config.mapZLevel+".png)",
|
||||
"background-size": "cover",
|
||||
"text-align": "center",
|
||||
"transform-origin": "center center",
|
||||
"transform": "scale(" + zoom + ")",
|
||||
"transform": matrix,
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -110,32 +109,26 @@ const NanoMapMarker = (props, context) => {
|
||||
icon,
|
||||
tooltip,
|
||||
color,
|
||||
onClick,
|
||||
} = props;
|
||||
// Please note, the horrifying `3.65714285714` is just the ratio of the
|
||||
// width/height of the minimap *element* (not image)
|
||||
// to the actual turf size of the map
|
||||
const rx = (-256 * (zoom - 1)
|
||||
+ (x * (3.65714285714 * zoom))
|
||||
- 1.5 * zoom - 3);
|
||||
const ry = (512 * zoom
|
||||
- (y * (3.65714285714 * zoom))
|
||||
+ zoom - 1.5);
|
||||
const rx = (x * 4) - 5;
|
||||
const ry = (y * 4) - 4;
|
||||
|
||||
return (
|
||||
<div style={"transform: scale(" + 1 / zoom + ")"}>
|
||||
<Box
|
||||
position="absolute"
|
||||
className="NanoMap__marker"
|
||||
lineHeight="0"
|
||||
top={ry + 'px'}
|
||||
left={rx + 'px'} >
|
||||
<Icon
|
||||
name={icon}
|
||||
color={color}
|
||||
fontSize="6px"
|
||||
/>
|
||||
<Tooltip content={tooltip} />
|
||||
</Box>
|
||||
</div>
|
||||
<Box
|
||||
position="absolute"
|
||||
className="NanoMap__marker"
|
||||
lineHeight="0"
|
||||
bottom={ry + 'px'}
|
||||
left={rx + 'px'}
|
||||
onMouseDown={onClick} >
|
||||
<Icon
|
||||
name={icon}
|
||||
color={color}
|
||||
fontSize="4px"
|
||||
/>
|
||||
<Tooltip content={tooltip} scale={zoom} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export const Tooltip = props => {
|
||||
const {
|
||||
content,
|
||||
position = 'bottom',
|
||||
scale,
|
||||
} = props;
|
||||
// Empirically calculated length of the string,
|
||||
// at which tooltip text starts to overflow.
|
||||
@@ -14,6 +15,7 @@ export const Tooltip = props => {
|
||||
'Tooltip',
|
||||
long && 'Tooltip--long',
|
||||
position && 'Tooltip--' + position,
|
||||
scale && 'Tooltip--scale--' + Math.floor(scale),
|
||||
])}
|
||||
data-tooltip={content} />
|
||||
);
|
||||
|
||||
@@ -26,4 +26,4 @@ export { Section } from './Section';
|
||||
export { Slider } from './Slider';
|
||||
export { Table } from './Table';
|
||||
export { Tabs } from './Tabs';
|
||||
export { Tooltip } from './Tooltip';
|
||||
export { Tooltip } from './Tooltip';
|
||||
@@ -4,6 +4,10 @@ export const UI_UPDATE = 1;
|
||||
export const UI_DISABLED = 0;
|
||||
export const UI_CLOSE = -1;
|
||||
|
||||
// Atmospheric helpers
|
||||
/** 0.0 Degrees Celsius in Kelvin */
|
||||
export const T0C = 273.15;
|
||||
|
||||
// All game related colors are stored here
|
||||
export const COLORS = {
|
||||
// Department colors
|
||||
@@ -48,77 +52,105 @@ export const CSS_COLORS = [
|
||||
'label',
|
||||
];
|
||||
|
||||
|
||||
// If you ever add a new radio channel, you can either manually update this, or
|
||||
// go use /client/verb/generate_tgui_radio_constants() in communications.dm.
|
||||
export const RADIO_CHANNELS = [
|
||||
{
|
||||
name: 'Syndicate',
|
||||
freq: 1213,
|
||||
color: '#a52a2a',
|
||||
"name": "Mercenary",
|
||||
"freq": 1213,
|
||||
"color": "#6D3F40",
|
||||
},
|
||||
{
|
||||
name: 'Red Team',
|
||||
freq: 1215,
|
||||
color: '#ff4444',
|
||||
"name": "Raider",
|
||||
"freq": 1277,
|
||||
"color": "#6D3F40",
|
||||
},
|
||||
{
|
||||
name: 'Blue Team',
|
||||
freq: 1217,
|
||||
color: '#3434fd',
|
||||
"name": "Special Ops",
|
||||
"freq": 1341,
|
||||
"color": "#5C5C8A",
|
||||
},
|
||||
{
|
||||
name: 'CentCom',
|
||||
freq: 1337,
|
||||
color: '#2681a5',
|
||||
"name": "AI Private",
|
||||
"freq": 1343,
|
||||
"color": "#FF00FF",
|
||||
},
|
||||
{
|
||||
name: 'Supply',
|
||||
freq: 1347,
|
||||
color: '#b88646',
|
||||
"name": "Response Team",
|
||||
"freq": 1345,
|
||||
"color": "#5C5C8A",
|
||||
},
|
||||
{
|
||||
name: 'Service',
|
||||
freq: 1349,
|
||||
color: '#6ca729',
|
||||
"name": "Supply",
|
||||
"freq": 1347,
|
||||
"color": "#5F4519",
|
||||
},
|
||||
{
|
||||
name: 'Science',
|
||||
freq: 1351,
|
||||
color: '#c68cfa',
|
||||
"name": "Service",
|
||||
"freq": 1349,
|
||||
"color": "#6eaa2c",
|
||||
},
|
||||
{
|
||||
name: 'Command',
|
||||
freq: 1353,
|
||||
color: '#5177ff',
|
||||
"name": "Science",
|
||||
"freq": 1351,
|
||||
"color": "#993399",
|
||||
},
|
||||
{
|
||||
name: 'Medical',
|
||||
freq: 1355,
|
||||
color: '#57b8f0',
|
||||
"name": "Command",
|
||||
"freq": 1353,
|
||||
"color": "#193A7A",
|
||||
},
|
||||
{
|
||||
name: 'Engineering',
|
||||
freq: 1357,
|
||||
color: '#f37746',
|
||||
"name": "Medical",
|
||||
"freq": 1355,
|
||||
"color": "#008160",
|
||||
},
|
||||
{
|
||||
name: 'Security',
|
||||
freq: 1359,
|
||||
color: '#dd3535',
|
||||
"name": "Engineering",
|
||||
"freq": 1357,
|
||||
"color": "#A66300",
|
||||
},
|
||||
{
|
||||
name: 'AI Private',
|
||||
freq: 1447,
|
||||
color: '#d65d95',
|
||||
"name": "Security",
|
||||
"freq": 1359,
|
||||
"color": "#A30000",
|
||||
},
|
||||
{
|
||||
name: 'Common',
|
||||
freq: 1459,
|
||||
color: '#1ecc43',
|
||||
"name": "Explorer",
|
||||
"freq": 1361,
|
||||
"color": "#555555",
|
||||
},
|
||||
{
|
||||
"name": "Talon",
|
||||
"freq": 1363,
|
||||
"color": "#555555",
|
||||
},
|
||||
{
|
||||
"name": "Common",
|
||||
"freq": 1459,
|
||||
"color": "#008000",
|
||||
},
|
||||
{
|
||||
"name": "Entertainment",
|
||||
"freq": 1461,
|
||||
"color": "#339966",
|
||||
},
|
||||
{
|
||||
"name": "Security(I)",
|
||||
"freq": 1475,
|
||||
"color": "#008000",
|
||||
},
|
||||
{
|
||||
"name": "Medical(I)",
|
||||
"freq": 1485,
|
||||
"color": "#008000",
|
||||
},
|
||||
];
|
||||
|
||||
const GASES = [
|
||||
{
|
||||
'id': 'o2',
|
||||
'id': 'oxygen',
|
||||
'name': 'Oxygen',
|
||||
'label': 'O₂',
|
||||
'color': 'blue',
|
||||
@@ -130,15 +162,15 @@ const GASES = [
|
||||
'color': 'red',
|
||||
},
|
||||
{
|
||||
'id': 'co2',
|
||||
'id': 'carbon dioxide',
|
||||
'name': 'Carbon Dioxide',
|
||||
'label': 'CO₂',
|
||||
'color': 'grey',
|
||||
},
|
||||
{
|
||||
'id': 'plasma',
|
||||
'name': 'Plasma',
|
||||
'label': 'Plasma',
|
||||
'id': 'phoron',
|
||||
'name': 'Phoron',
|
||||
'label': 'Phoron',
|
||||
'color': 'pink',
|
||||
},
|
||||
{
|
||||
@@ -201,6 +233,24 @@ const GASES = [
|
||||
'label': 'H₂',
|
||||
'color': 'white',
|
||||
},
|
||||
{
|
||||
'id': 'other',
|
||||
'name': 'Other',
|
||||
'label': 'Other',
|
||||
'color': 'white',
|
||||
},
|
||||
{
|
||||
'id': 'pressure',
|
||||
'name': 'Pressure',
|
||||
'label': 'Pressure',
|
||||
'color': 'average',
|
||||
},
|
||||
{
|
||||
'id': 'temperature',
|
||||
'name': 'Temperature',
|
||||
'label': 'Temperature',
|
||||
'color': 'yellow',
|
||||
},
|
||||
];
|
||||
|
||||
export const getGasLabel = (gasId, fallbackValue) => {
|
||||
|
||||
@@ -4,10 +4,6 @@ import { useBackend } from "../backend";
|
||||
import { AnimatedNumber, Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table, Tooltip } from "../components";
|
||||
import { Window } from "../layouts";
|
||||
|
||||
import { createLogger } from '../logging';
|
||||
|
||||
const debugBodyScannerLogger = createLogger('debugBodyScanner');
|
||||
|
||||
const stats = [
|
||||
['good', 'Alive'],
|
||||
['average', 'Unconscious'],
|
||||
|
||||
@@ -103,6 +103,9 @@ export const CrewMonitorContent = (props, context) => {
|
||||
</Table>
|
||||
);
|
||||
} else if (tabIndex === 1) {
|
||||
// Please note, if you ever change the zoom values,
|
||||
// you MUST update styles/components/Tooltip.scss
|
||||
// and change the @for scss to match.
|
||||
body = (
|
||||
<Box textAlign="center">
|
||||
Zoom Level:
|
||||
@@ -113,7 +116,7 @@ export const CrewMonitorContent = (props, context) => {
|
||||
stepPixelSize="5"
|
||||
value={mapZoom}
|
||||
minValue={1}
|
||||
maxValue={8}
|
||||
maxValue={8}
|
||||
onChange={(e, value) => setZoom(value)} />
|
||||
Z-Level:
|
||||
{data.map_levels
|
||||
|
||||
20
tgui/packages/tgui/interfaces/common/FullscreenNotice.js
Normal file
20
tgui/packages/tgui/interfaces/common/FullscreenNotice.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Flex, Section } from '../../components';
|
||||
|
||||
/**
|
||||
* Just a generic wrapper for fullscreen notices.
|
||||
*/
|
||||
export const FullscreenNotice = (props, context) => {
|
||||
const {
|
||||
children,
|
||||
title = 'Welcome',
|
||||
} = props;
|
||||
return (
|
||||
<Section title={title} height="100%" stretchContents>
|
||||
<Flex height="100%" align="center" justify="center">
|
||||
<Flex.Item textAlign="center" mt="-2rem">
|
||||
{children}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useBackend } from '../../backend';
|
||||
import { Box, Button, Flex, Icon, Section } from '../../components';
|
||||
import { FullscreenNotice } from './FullscreenNotice';
|
||||
|
||||
/**
|
||||
* Displays a login screen that users can interact with
|
||||
@@ -30,55 +31,51 @@ export const LoginScreen = (_properties, context) => {
|
||||
isRobot,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Welcome" height="100%" stretchContents>
|
||||
<Flex height="100%" align="center" justify="center">
|
||||
<Flex.Item textAlign="center" mt="-2rem">
|
||||
<Box fontSize="1.5rem" bold>
|
||||
<Icon
|
||||
name="user-circle"
|
||||
verticalAlign="middle"
|
||||
size={3}
|
||||
mr="1rem"
|
||||
/>
|
||||
Guest
|
||||
</Box>
|
||||
<Box color="label" my="1rem">
|
||||
ID:
|
||||
<Button
|
||||
icon="id-card"
|
||||
content={scan ? scan : "----------"}
|
||||
ml="0.5rem"
|
||||
onClick={() => act('scan')}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
icon="sign-in-alt"
|
||||
disabled={!scan}
|
||||
content="Login"
|
||||
onClick={() => act('login', {
|
||||
login_type: 1,
|
||||
})}
|
||||
/>
|
||||
{!!isAI && (
|
||||
<Button
|
||||
icon="sign-in-alt"
|
||||
content="Login as AI"
|
||||
onClick={() => act('login', {
|
||||
login_type: 2,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{!!isRobot && (
|
||||
<Button
|
||||
icon="sign-in-alt"
|
||||
content="Login as Cyborg"
|
||||
onClick={() => act('login', {
|
||||
login_type: 3,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
<FullscreenNotice title="Welcome">
|
||||
<Box fontSize="1.5rem" bold>
|
||||
<Icon
|
||||
name="user-circle"
|
||||
verticalAlign="middle"
|
||||
size={3}
|
||||
mr="1rem"
|
||||
/>
|
||||
Guest
|
||||
</Box>
|
||||
<Box color="label" my="1rem">
|
||||
ID:
|
||||
<Button
|
||||
icon="id-card"
|
||||
content={scan ? scan : "----------"}
|
||||
ml="0.5rem"
|
||||
onClick={() => act('scan')}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
icon="sign-in-alt"
|
||||
disabled={!scan}
|
||||
content="Login"
|
||||
onClick={() => act('login', {
|
||||
login_type: 1,
|
||||
})}
|
||||
/>
|
||||
{!!isAI && (
|
||||
<Button
|
||||
icon="sign-in-alt"
|
||||
content="Login as AI"
|
||||
onClick={() => act('login', {
|
||||
login_type: 2,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{!!isRobot && (
|
||||
<Button
|
||||
icon="sign-in-alt"
|
||||
content="Login as Cyborg"
|
||||
onClick={() => act('login', {
|
||||
login_type: 3,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</FullscreenNotice>
|
||||
);
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -259,7 +259,7 @@ A fatal exception has occurred at 002B:C562F1B7 in TGUI.
|
||||
The current application will be terminated.
|
||||
Please remain calm. Get to the nearest NTNet workstation
|
||||
and send the copy of the following stack trace to:
|
||||
www.github.com/tgstation/tgstation. Thank you for your cooperation.
|
||||
www.github.com/VOREStation/VOREStation. Thank you for your cooperation.
|
||||
</marquee>
|
||||
<div id="FatalError__stack" class="FatalError__stack"></div>
|
||||
<div class="FatalError__footer">
|
||||
|
||||
@@ -125,3 +125,15 @@ $border-radius: base.$border-radius !default;
|
||||
.Tooltip--right:hover::after {
|
||||
transform: translateX(0.5em) translateY(-50%);
|
||||
}
|
||||
|
||||
@for $i from 1 through 8 {
|
||||
.Tooltip--scale--#{$i}::after {
|
||||
top: 30%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) scale(1 / $i);
|
||||
}
|
||||
|
||||
.Tooltip--scale--#{$i}:hover::after {
|
||||
transform: translateX(-50%) scale(1 / $i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
margin: base.em(6px);
|
||||
}
|
||||
|
||||
.Layout__content--flexRow {
|
||||
|
||||
@@ -3504,7 +3504,6 @@
|
||||
#include "code\modules\tgui\states\inventory_vr.dm"
|
||||
#include "code\modules\tgui\states\not_incapacitated.dm"
|
||||
#include "code\modules\tgui\states\notcontained.dm"
|
||||
#include "code\modules\tgui\states\ntos.dm"
|
||||
#include "code\modules\tgui\states\observer.dm"
|
||||
#include "code\modules\tgui\states\physical.dm"
|
||||
#include "code\modules\tgui\states\self.dm"
|
||||
|
||||
Reference in New Issue
Block a user