diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm
index 8f47c609b2..565c595473 100644
--- a/code/modules/tgui/external.dm
+++ b/code/modules/tgui/external.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* External tgui definitions, such as src_object APIs.
*
* Copyright (c) 2020 Aleksej Komarov
@@ -71,12 +71,13 @@
* required action string The action/button that has been invoked by the user.
* required params list A list of parameters attached to the button.
*
- * return bool If the UI should be updated or not.
+ * return bool If the user's input has been handled and the UI should update.
*/
/datum/proc/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ // SHOULD_CALL_PARENT(TRUE)
// If UI is not interactive or usr calling Topic is not the UI user, bail.
if(!ui || ui.status != UI_INTERACTIVE)
- return 1
+ return TRUE
/**
* public
@@ -157,7 +158,7 @@
// Name the verb, and hide it from the user panel.
set name = "uiclose"
set hidden = TRUE
- var/mob/user = src && src.mob
+ var/mob/user = src?.mob
if(!user)
return
// Close all tgui datums based on window_id.
diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm
index fa88cc1338..cc66e71953 100644
--- a/code/modules/tgui/states.dm
+++ b/code/modules/tgui/states.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Base state and helpers for states. Just does some sanity checks,
* implement a proper state for in-depth checks.
*
@@ -83,27 +83,12 @@
return ..()
/mob/living/silicon/robot/shared_ui_interaction(src_object)
- // Disable UIs if the Borg is unpowered or locked.
- if(!cell || cell.charge <= 0 || locked_down)
+ // Disable UIs if the object isn't installed in the borg AND the borg is either locked, has a dead cell, or no cell.
+ var/atom/device = src_object
+ if((istype(device) && device.loc != src) && (!cell || cell.charge <= 0 || locked_down))
return UI_DISABLED
return ..()
-/**
- * public
- *
- * Check the distance for a living mob.
- * Really only used for checks outside the context of a mob.
- * Otherwise, use shared_living_ui_distance().
- *
- * required src_object The object which owns the UI.
- * required user mob The mob who opened/is using the UI.
- *
- * return UI_state The state of the UI.
- */
-/atom/proc/contents_ui_distance(src_object, mob/living/user)
- // Just call this mob's check.
- return user.shared_living_ui_distance(src_object)
-
/**
* public
*
diff --git a/code/modules/tgui/states/admin.dm b/code/modules/tgui/states/admin.dm
index 227a294078..4da5061dfc 100644
--- a/code/modules/tgui/states/admin.dm
+++ b/code/modules/tgui/states/admin.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: admin_state
*
* Checks that the user is an admin, end-of-story.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(admin_state, /datum/ui_state/admin_state, new)
diff --git a/code/modules/tgui/states/always.dm b/code/modules/tgui/states/always.dm
index 210f0896a2..2406dbb2b9 100644
--- a/code/modules/tgui/states/always.dm
+++ b/code/modules/tgui/states/always.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: always_state
*
* Always grants the user UI_INTERACTIVE. Period.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(always_state, /datum/ui_state/always_state, new)
diff --git a/code/modules/tgui/states/conscious.dm b/code/modules/tgui/states/conscious.dm
index 670ca7c07e..8e35a97da3 100644
--- a/code/modules/tgui/states/conscious.dm
+++ b/code/modules/tgui/states/conscious.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: conscious_state
*
* Only checks if the user is conscious.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(conscious_state, /datum/ui_state/conscious_state, new)
diff --git a/code/modules/tgui/states/contained.dm b/code/modules/tgui/states/contained.dm
index 1eb8edba25..98187b746e 100644
--- a/code/modules/tgui/states/contained.dm
+++ b/code/modules/tgui/states/contained.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: contained_state
*
* Checks that the user is inside the src_object.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(contained_state, /datum/ui_state/contained_state, new)
diff --git a/code/modules/tgui/states/deep_inventory.dm b/code/modules/tgui/states/deep_inventory.dm
index a2b9276a59..a7351a0d2d 100644
--- a/code/modules/tgui/states/deep_inventory.dm
+++ b/code/modules/tgui/states/deep_inventory.dm
@@ -1,11 +1,13 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: deep_inventory_state
*
* Checks that the src_object is in the user's deep
* (backpack, box, toolbox, etc) inventory.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(deep_inventory_state, /datum/ui_state/deep_inventory_state, new)
diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm
index 367e57beff..56220105a5 100644
--- a/code/modules/tgui/states/default.dm
+++ b/code/modules/tgui/states/default.dm
@@ -1,11 +1,13 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: default_state
*
* Checks a number of things -- mostly physical distance for humans
* and view for robots.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
@@ -18,15 +20,10 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
/mob/living/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
- if(. > UI_CLOSE && loc)
- . = min(., loc.contents_ui_distance(src_object, src)) // Check the distance...
- if(. == UI_INTERACTIVE) // Non-human living mobs can only look, not touch.
- return UI_UPDATE
-
-/mob/living/carbon/human/default_can_use_topic(src_object)
- . = shared_ui_interaction(src_object)
- if(. > UI_CLOSE)
+ if(. > UI_CLOSE && loc) //must not be in nullspace.
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
+ if(. == UI_INTERACTIVE && !IsAdvancedToolUser(src)) // unhandy living mobs can only look, not touch.
+ return UI_UPDATE
/mob/living/silicon/robot/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
@@ -49,14 +46,9 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
return UI_INTERACTIVE
return UI_CLOSE
-/mob/living/simple_animal/default_can_use_topic(src_object)
- . = shared_ui_interaction(src_object)
- if(. > UI_CLOSE)
- . = min(., shared_living_ui_distance(src_object)) //simple animals can only use things they're near.
-
/mob/living/silicon/pai/default_can_use_topic(src_object)
// pAIs can only use themselves and the owner's radio.
if((src_object == src || src_object == radio) && !stat)
return UI_INTERACTIVE
else
- return ..()
+ return min(..(), UI_UPDATE)
diff --git a/code/modules/tgui/states/hands.dm b/code/modules/tgui/states/hands.dm
index 1c885ed414..e8cb844bf7 100644
--- a/code/modules/tgui/states/hands.dm
+++ b/code/modules/tgui/states/hands.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: hands_state
*
* Checks that the src_object is in the user's hands.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(hands_state, /datum/ui_state/hands_state, new)
diff --git a/code/modules/tgui/states/human_adjacent.dm b/code/modules/tgui/states/human_adjacent.dm
index 2ac7c8637b..b9208f96cd 100644
--- a/code/modules/tgui/states/human_adjacent.dm
+++ b/code/modules/tgui/states/human_adjacent.dm
@@ -1,11 +1,13 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: human_adjacent_state
*
* In addition to default checks, only allows interaction for a
* human adjacent user.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(human_adjacent_state, /datum/ui_state/human_adjacent_state, new)
diff --git a/code/modules/tgui/states/inventory.dm b/code/modules/tgui/states/inventory.dm
index dc5dd0d57e..4bc121b278 100644
--- a/code/modules/tgui/states/inventory.dm
+++ b/code/modules/tgui/states/inventory.dm
@@ -1,11 +1,13 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: inventory_state
*
* Checks that the src_object is in the user's top-level
* (hand, ear, pocket, belt, etc) inventory.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(inventory_state, /datum/ui_state/inventory_state, new)
diff --git a/code/modules/tgui/states/language_menu.dm b/code/modules/tgui/states/language_menu.dm
index 6389b05cd5..eaaa125786 100644
--- a/code/modules/tgui/states/language_menu.dm
+++ b/code/modules/tgui/states/language_menu.dm
@@ -1,10 +1,12 @@
-/**
- * tgui state: language_menu_state
- *
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
+/**
+ * tgui state: language_menu_state
+ */
+
GLOBAL_DATUM_INIT(language_menu_state, /datum/ui_state/language_menu, new)
/datum/ui_state/language_menu/can_use_topic(src_object, mob/user)
diff --git a/code/modules/tgui/states/new_player.dm b/code/modules/tgui/states/new_player.dm
new file mode 100644
index 0000000000..cf6f83ed3a
--- /dev/null
+++ b/code/modules/tgui/states/new_player.dm
@@ -0,0 +1,13 @@
+/**
+ * tgui state: new_player_state
+ *
+ * Checks that the user is a new_player, or if user is an admin
+ */
+
+GLOBAL_DATUM_INIT(new_player_state, /datum/ui_state/new_player_state, new)
+
+/datum/ui_state/new_player_state/can_use_topic(src_object, mob/user)
+ if(isnewplayer(user) || check_rights_for(user.client, R_ADMIN))
+ return UI_INTERACTIVE
+ return UI_CLOSE
+
diff --git a/code/modules/tgui/states/not_incapacitated.dm b/code/modules/tgui/states/not_incapacitated.dm
index 16dcb7881e..48787c81a7 100644
--- a/code/modules/tgui/states/not_incapacitated.dm
+++ b/code/modules/tgui/states/not_incapacitated.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: not_incapacitated_state
*
* Checks that the user isn't incapacitated
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(not_incapacitated_state, /datum/ui_state/not_incapacitated_state, new)
@@ -25,7 +27,7 @@ GLOBAL_DATUM_INIT(not_incapacitated_turf_state, /datum/ui_state/not_incapacitate
turf_check = no_turfs
/datum/ui_state/not_incapacitated_state/can_use_topic(src_object, mob/user)
- if(user.stat)
+ if(user.stat != CONSCIOUS)
return UI_CLOSE
if(user.incapacitated() || (turf_check && !isturf(user.loc)))
return UI_DISABLED
diff --git a/code/modules/tgui/states/notcontained.dm b/code/modules/tgui/states/notcontained.dm
index 1d4e6aec19..018e0fa030 100644
--- a/code/modules/tgui/states/notcontained.dm
+++ b/code/modules/tgui/states/notcontained.dm
@@ -1,11 +1,13 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: notcontained_state
*
* Checks that the user is not inside src_object, and then makes the
* default checks.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(notcontained_state, /datum/ui_state/notcontained_state, new)
diff --git a/code/modules/tgui/states/observer.dm b/code/modules/tgui/states/observer.dm
index d105de1c0c..b749afa894 100644
--- a/code/modules/tgui/states/observer.dm
+++ b/code/modules/tgui/states/observer.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: observer_state
*
* Checks that the user is an observer/ghost.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(observer_state, /datum/ui_state/observer_state, new)
diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm
index 3073039d14..b559758f72 100644
--- a/code/modules/tgui/states/physical.dm
+++ b/code/modules/tgui/states/physical.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: physical_state
*
* Short-circuits the default state to only check physical distance.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(physical_state, /datum/ui_state/physical, new)
diff --git a/code/modules/tgui/states/self.dm b/code/modules/tgui/states/self.dm
index 4b6e3b9fd9..f7cef3f600 100644
--- a/code/modules/tgui/states/self.dm
+++ b/code/modules/tgui/states/self.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: self_state
*
* Only checks that the user and src_object are the same.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(self_state, /datum/ui_state/self_state, new)
diff --git a/code/modules/tgui/states/zlevel.dm b/code/modules/tgui/states/zlevel.dm
index 64ea2fa1c0..f1a2282b3c 100644
--- a/code/modules/tgui/states/zlevel.dm
+++ b/code/modules/tgui/states/zlevel.dm
@@ -1,10 +1,12 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
/**
* tgui state: z_state
*
* Only checks that the Z-level of the user and src_object are the same.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
*/
GLOBAL_DATUM_INIT(z_state, /datum/ui_state/z_state, new)
diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm
index 9393b9641f..b99783f67a 100644
--- a/code/modules/tgui/tgui.dm
+++ b/code/modules/tgui/tgui.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
@@ -50,7 +50,7 @@
*/
/datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y)
log_tgui(user,
- "new [interface] fancy [user.client.prefs.tgui_fancy]",
+ "new [interface] fancy [user?.client?.prefs.tgui_fancy]",
src_object = src_object)
src.user = user
src.src_object = src_object
@@ -67,18 +67,20 @@
* public
*
* Open this UI (and initialize it with data).
+ *
+ * return bool - TRUE if a new pooled window is opened, FALSE in all other situations including if a new pooled window didn't open because one already exists.
*/
/datum/tgui/proc/open()
if(!user.client)
- return null
+ return FALSE
if(window)
- return null
+ return FALSE
process_status()
if(status < UI_UPDATE)
- return null
+ return FALSE
window = SStgui.request_pooled_window(user)
if(!window)
- return null
+ return FALSE
opened_at = world.time
window.acquire_lock(src)
if(!window.is_ready())
@@ -101,6 +103,8 @@
with_static_data = TRUE))
SStgui.on_open(src)
+ return TRUE
+
/**
* public
*
@@ -156,7 +160,7 @@
*/
/datum/tgui/proc/send_asset(datum/asset/asset)
if(!window)
- CRASH("send_asset() can only be called after open().")
+ CRASH("send_asset() was called either without calling open() first or when open() did not return TRUE.")
return window.send_asset(asset)
/**
@@ -237,7 +241,7 @@
* Run an update cycle for this UI. Called internally by SStgui
* every second or so.
*/
-/datum/tgui/process(force = FALSE)
+/datum/tgui/process(delta_time, force = FALSE)
if(closing)
return
var/datum/host = src_object.ui_host(user)
diff --git a/code/modules/tgui/tgui_alert.dm b/code/modules/tgui/tgui_alert.dm
new file mode 100644
index 0000000000..1a86cca705
--- /dev/null
+++ b/code/modules/tgui/tgui_alert.dm
@@ -0,0 +1,160 @@
+/**
+ * Creates a TGUI alert window and returns the user's response.
+ *
+ * This proc should be used to create alerts that the caller will wait for a response from.
+ * Arguments:
+ * * user - The user to show the alert to.
+ * * message - The content of the alert, shown in the body of the TGUI window.
+ * * title - The of the alert modal, shown on the top of the TGUI window.
+ * * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
+ * * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
+ */
+/proc/tgui_alert(mob/user, message, title, list/buttons, timeout = 60 SECONDS)
+ if (!user)
+ user = usr
+ if (!istype(user))
+ if (istype(user, /client))
+ var/client/client = user
+ user = client.mob
+ else
+ return
+ var/datum/tgui_modal/alert = new(user, message, title, buttons, timeout)
+ alert.ui_interact(user)
+ alert.wait()
+ if (alert)
+ . = alert.choice
+ qdel(alert)
+
+/**
+ * Creates an asynchronous TGUI alert window with an associated callback.
+ *
+ * This proc should be used to create alerts that invoke a callback with the user's chosen option.
+ * Arguments:
+ * * user - The user to show the alert to.
+ * * message - The content of the alert, shown in the body of the TGUI window.
+ * * title - The of the alert modal, shown on the top of the TGUI window.
+ * * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
+ * * callback - The callback to be invoked when a choice is made.
+ * * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
+ */
+/proc/tgui_alert_async(mob/user, message, title, list/buttons, datum/callback/callback, timeout = 60 SECONDS)
+ if (!user)
+ user = usr
+ if (!istype(user))
+ if (istype(user, /client))
+ var/client/client = user
+ user = client.mob
+ else
+ return
+ var/datum/tgui_modal/async/alert = new(user, message, title, buttons, callback, timeout)
+ alert.ui_interact(user)
+
+/**
+ * # tgui_modal
+ *
+ * Datum used for instantiating and using a TGUI-controlled modal that prompts the user with
+ * a message and has buttons for responses.
+ */
+/datum/tgui_modal
+ /// The title of the TGUI window
+ var/title
+ /// The textual body of the TGUI window
+ var/message
+ /// The list of buttons (responses) provided on the TGUI window
+ var/list/buttons
+ /// The button that the user has pressed, null if no selection has been made
+ var/choice
+ /// The time at which the tgui_modal was created, for displaying timeout progress.
+ var/start_time
+ /// The lifespan of the tgui_modal, after which the window will close and delete itself.
+ var/timeout
+ /// Boolean field describing if the tgui_modal was closed by the user.
+ var/closed
+
+/datum/tgui_modal/New(mob/user, message, title, list/buttons, timeout)
+ src.title = title
+ src.message = message
+ src.buttons = buttons.Copy()
+ if (timeout)
+ src.timeout = timeout
+ start_time = world.time
+ QDEL_IN(src, timeout)
+
+/datum/tgui_modal/Destroy(force, ...)
+ SStgui.close_uis(src)
+ QDEL_NULL(buttons)
+ . = ..()
+
+/**
+ * Waits for a user's response to the tgui_modal's prompt before returning. Returns early if
+ * the window was closed by the user.
+ */
+/datum/tgui_modal/proc/wait()
+ while (!choice && !closed)
+ stoplag(1)
+
+/datum/tgui_modal/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "AlertModal")
+ ui.open()
+
+/datum/tgui_modal/ui_close(mob/user)
+ . = ..()
+ closed = TRUE
+
+/datum/tgui_modal/ui_state(mob/user)
+ return GLOB.always_state
+
+/datum/tgui_modal/ui_data(mob/user)
+ . = list(
+ "title" = title,
+ "message" = message,
+ "buttons" = buttons
+ )
+
+ if(timeout)
+ .["timeout"] = CLAMP01((timeout - (world.time - start_time) - 1 SECONDS) / (timeout - 1 SECONDS))
+
+/datum/tgui_modal/ui_act(action, list/params)
+ . = ..()
+ if (.)
+ return
+ switch(action)
+ if("choose")
+ if (!(params["choice"] in buttons))
+ return
+ choice = params["choice"]
+ SStgui.close_uis(src)
+ return TRUE
+
+/**
+ * # async tgui_modal
+ *
+ * An asynchronous version of tgui_modal to be used with callbacks instead of waiting on user responses.
+ */
+/datum/tgui_modal/async
+ /// The callback to be invoked by the tgui_modal upon having a choice made.
+ var/datum/callback/callback
+
+/datum/tgui_modal/async/New(mob/user, message, title, list/buttons, callback, timeout)
+ ..(user, title, message, buttons, timeout)
+ src.callback = callback
+
+/datum/tgui_modal/async/Destroy(force, ...)
+ QDEL_NULL(callback)
+ . = ..()
+
+/datum/tgui_modal/async/ui_close(mob/user)
+ . = ..()
+ qdel(src)
+
+/datum/tgui_modal/async/ui_act(action, list/params)
+ . = ..()
+ if (!. || choice == null)
+ return
+ callback.InvokeAsync(choice)
+ qdel(src)
+
+/datum/tgui_modal/async/wait()
+ return
diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm
index f24a46e33d..61e4db27e7 100644
--- a/code/modules/tgui/tgui_window.dm
+++ b/code/modules/tgui/tgui_window.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
diff --git a/code/modules/tgui_panel/audio.dm b/code/modules/tgui_panel/audio.dm
index e62c4b5bc1..6806961599 100644
--- a/code/modules/tgui_panel/audio.dm
+++ b/code/modules/tgui_panel/audio.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
diff --git a/code/modules/tgui_panel/external.dm b/code/modules/tgui_panel/external.dm
index 35aa31eca7..89973a925d 100644
--- a/code/modules/tgui_panel/external.dm
+++ b/code/modules/tgui_panel/external.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
@@ -12,19 +12,21 @@
set name = "Fix chat"
set category = "OOC"
var/action
- log_tgui(src, "Started fixing.",
- context = "verb/fix_tgui_panel")
- // Not ready
- if(!tgui_panel?.is_ready())
- log_tgui(src, "Panel is not ready",
- context = "verb/fix_tgui_panel")
- tgui_panel.window.send_message("ping", force = TRUE)
- action = alert(src, "Method: Pinging the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope")
- if(action == "Fixed")
- log_tgui(src, "Fixed by sending a ping",
- context = "verb/fix_tgui_panel")
- return
- // Catch all solution
+ log_tgui(src, "Started fixing.", context = "verb/fix_tgui_panel")
+
+ nuke_chat()
+
+ // Failed to fix
+ action = alert(src, "Did that work?", "", "Yes", "No, switch to old ui")
+ if (action == "No, switch to old ui")
+ winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
+ winset(src, "browseroutput", "is-disabled=1;is-visible=0")
+ log_tgui(src, "Failed to fix.", context = "verb/fix_tgui_panel")
+
+/client/proc/nuke_chat()
+ // Catch all solution (kick the whole thing in the pants)
+ winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
+ winset(src, "browseroutput", "is-disabled=1;is-visible=0")
if(!tgui_panel || !istype(tgui_panel))
log_tgui(src, "tgui_panel datum is missing",
context = "verb/fix_tgui_panel")
@@ -33,15 +35,3 @@
// Force show the panel to see if there are any errors
winset(src, "output", "is-disabled=1&is-visible=0")
winset(src, "browseroutput", "is-disabled=0;is-visible=1")
- action = alert(src, "Method: Reinitializing the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope")
- if(action == "Fixed")
- log_tgui(src, "Fixed by calling 'initialize'",
- context = "verb/fix_tgui_panel")
- return
- // Failed to fix
- action = alert(src, "Welp, I'm all out of ideas. Try closing BYOND and reconnecting.\nWe could also disable tgui_panel and re-enable the old UI", "", "Thanks anyways", "Switch to old UI")
- if (action == "Switch to old UI")
- winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
- winset(src, "browseroutput", "is-disabled=1;is-visible=0")
- log_tgui(src, "Failed to fix.",
- context = "verb/fix_tgui_panel")
diff --git a/code/modules/tgui_panel/telemetry.dm b/code/modules/tgui_panel/telemetry.dm
index 79087d8500..e1abfb1e12 100644
--- a/code/modules/tgui_panel/telemetry.dm
+++ b/code/modules/tgui_panel/telemetry.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
diff --git a/code/modules/tgui_panel/tgui_panel.dm b/code/modules/tgui_panel/tgui_panel.dm
index b983484046..b2fb120100 100644
--- a/code/modules/tgui_panel/tgui_panel.dm
+++ b/code/modules/tgui_panel/tgui_panel.dm
@@ -1,4 +1,4 @@
-/**
+/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
@@ -55,7 +55,7 @@
*/
/datum/tgui_panel/proc/on_initialize_timed_out()
// Currently does nothing but sending a message to old chat.
- SEND_TEXT(client, "Failed to load fancy chat, reverting to old chat. Certain features won't work.")
+ SEND_TEXT(client, "Failed to load fancy chat, click HERE to attempt to reload it.")
/**
* private
diff --git a/sound/machines/computer/computer_end.ogg b/sound/machines/computer/computer_end.ogg
new file mode 100644
index 0000000000..cd3f770e0b
Binary files /dev/null and b/sound/machines/computer/computer_end.ogg differ
diff --git a/sound/machines/computer/computer_mid1.ogg b/sound/machines/computer/computer_mid1.ogg
new file mode 100644
index 0000000000..d183bf5b7a
Binary files /dev/null and b/sound/machines/computer/computer_mid1.ogg differ
diff --git a/sound/machines/computer/computer_mid2.ogg b/sound/machines/computer/computer_mid2.ogg
new file mode 100644
index 0000000000..15e53ded80
Binary files /dev/null and b/sound/machines/computer/computer_mid2.ogg differ
diff --git a/sound/machines/computer/computer_start.ogg b/sound/machines/computer/computer_start.ogg
new file mode 100644
index 0000000000..80fa526bbb
Binary files /dev/null and b/sound/machines/computer/computer_start.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index b8ab2a32fe..f9de8bc0a0 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3512,6 +3512,7 @@
#include "code\modules\tgui\external.dm"
#include "code\modules\tgui\states.dm"
#include "code\modules\tgui\tgui.dm"
+#include "code\modules\tgui\tgui_alert.dm"
#include "code\modules\tgui\tgui_window.dm"
#include "code\modules\tgui\states\admin.dm"
#include "code\modules\tgui\states\always.dm"
@@ -3524,6 +3525,7 @@
#include "code\modules\tgui\states\human_adjacent.dm"
#include "code\modules\tgui\states\inventory.dm"
#include "code\modules\tgui\states\language_menu.dm"
+#include "code\modules\tgui\states\new_player.dm"
#include "code\modules\tgui\states\not_incapacitated.dm"
#include "code\modules\tgui\states\notcontained.dm"
#include "code\modules\tgui\states\observer.dm"