From a0a07e9f4072d2785c2cd39f8b6c1baf1313586f Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:36:34 -0700 Subject: [PATCH] Unfucks /datum/browse code (#89994) ## About The Pull Request What it was doing was by and large fine, HOW it was doing it SUCKED I've cleaned it up and the nearby code some, notable hits include: - random if check in secrets ui that was totally unused - proc called add that actually set - lists not defined as such - stupid var names - proc args which did nothing - code which did nothing - oververbose code - proc/var names with no spacing at all Note: This might have changed behavior accidentally, I've done my best to test but we'll need to look out for issue reports in coming days. ## Why It's Good For The Game I was working on bitflag code and saw red, now it's 2 hours later. ## Changelog :cl: code: Brought browser code up to standard with the rest of the codebase admin: Hey lads, I cleaned up how non TGUI windows work on the backend, please let me know if anything is broken! PING ME MOTHERFUCKER /:cl: --- code/datums/browser.dm | 506 +++++++++--------- code/game/atom/atom_vv.dm | 41 +- .../game/objects/structures/detectiveboard.dm | 6 +- code/modules/admin/permissionedit.dm | 4 +- code/modules/admin/verbs/ert.dm | 281 +++++----- code/modules/admin/verbs/secrets.dm | 93 ++-- code/modules/admin/verbs/spawnobjasmob.dm | 64 +-- code/modules/discord/accountlink.dm | 2 +- code/modules/error_handler/error_viewer.dm | 2 +- code/modules/tgui_panel/external.dm | 4 +- interface/interface.dm | 4 +- 11 files changed, 504 insertions(+), 503 deletions(-) diff --git a/code/datums/browser.dm b/code/datums/browser.dm index c935a7a9f93..a143be58501 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -1,44 +1,48 @@ /datum/browser var/mob/user - var/title - var/window_id // window_id is used as the window name for browse and onclose + var/title = "" + /// window_id is used as the window name for browse and onclose + var/window_id var/width = 0 var/height = 0 - var/datum/weakref/ref = null - var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id - var/stylesheets[0] - var/scripts[0] + var/datum/weakref/source_ref = null + /// window option is set using window_id + var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" + var/list/stylesheets = list() + var/list/scripts = list() var/head_elements var/body_elements var/head_content = "" var/content = "" -/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null) - if(IS_CLIENT_OR_MOCK(nuser)) - var/client/client_user = nuser +/datum/browser/New(mob/user, window_id, title = "", width = 0, height = 0, atom/source = null) + if(IS_CLIENT_OR_MOCK(user)) + var/client/client_user = user user = client_user.mob - else - user = nuser + src.user = user RegisterSignal(user, COMSIG_QDELETING, PROC_REF(user_deleted)) - window_id = nwindow_id - if (ntitle) - title = format_text(ntitle) - if (nwidth) - width = nwidth - if (nheight) - height = nheight - if (nref) - ref = WEAKREF(nref) + src.window_id = window_id + if (title) + src.title = format_text(title) + if (width) + src.width = width + if (height) + src.height = height + if (source) + src.source_ref = WEAKREF(source) /datum/browser/proc/user_deleted(datum/source) SIGNAL_HANDLER user = null -/datum/browser/proc/add_head_content(nhead_content) - head_content = nhead_content +/datum/browser/proc/add_head_content(head_content) + src.head_content += head_content -/datum/browser/proc/set_window_options(nwindow_options) - window_options = nwindow_options +/datum/browser/proc/set_head_content(head_content) + src.head_content = head_content + +/datum/browser/proc/set_window_options(window_options) + src.window_options = window_options /datum/browser/proc/add_stylesheet(name, file) if (istype(name, /datum/asset/spritesheet)) @@ -59,21 +63,21 @@ scripts["[ckey(name)].js"] = file SSassets.transport.register_asset("[ckey(name)].js", file) -/datum/browser/proc/set_content(ncontent) - content = ncontent +/datum/browser/proc/set_content(content) + src.content = content -/datum/browser/proc/add_content(ncontent) - content += ncontent +/datum/browser/proc/add_content(content) + src.content += content /datum/browser/proc/get_header() var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common) - var/file - head_content += "" - for (file in stylesheets) - head_content += "" + var/list/new_head_content = list() + new_head_content += "" + for (var/file in stylesheets) + new_head_content += "" if(user.client?.window_scaling && user.client?.window_scaling != 1 && !user.client?.prefs.read_preference(/datum/preference/toggle/ui_scale) && width && height) - head_content += {" + new_head_content += {" "} - for (file in scripts) - head_content += "" + for (var/file in scripts) + new_head_content += "" + head_content += new_head_content.Join() return {" @@ -96,6 +101,7 @@ [title ? "
[title]
" : ""]
"} + //" This is here because else the rest of the file looks like a string in notepad++. /datum/browser/proc/get_footer() return {" @@ -106,16 +112,17 @@ /datum/browser/proc/get_content() return {" - [get_header()] - [content] - [get_footer()] + [get_header()] + [content] + [get_footer()] "} -/datum/browser/proc/open(use_onclose = TRUE) +/datum/browser/proc/open(use_on_close = TRUE) if(isnull(window_id)) //null check because this can potentially nuke goonchat WARNING("Browser [title] tried to open with a null ID") to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on GitHub!")) return + var/window_size = "" if(width && height) if(user.client?.prefs?.read_preference(/datum/preference/toggle/ui_scale)) @@ -123,27 +130,28 @@ window_size = "size=[width * scaling]x[height * scaling];" else window_size = "size=[width]x[height];" + var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common) common_asset.send(user) - if (stylesheets.len) + if (length(stylesheets)) SSassets.transport.send_assets(user, stylesheets) - if (scripts.len) + if (length(scripts)) SSassets.transport.send_assets(user, scripts) DIRECT_OUTPUT(user, browse(get_content(), "window=[window_id];[window_size][window_options]")) - if (use_onclose) + if (use_on_close) setup_onclose() /datum/browser/proc/setup_onclose() set waitfor = 0 //winexists sleeps, so we don't need to. for (var/i in 1 to 10) - if (user?.client && winexists(user, window_id)) - var/atom/send_ref - if(ref) - send_ref = ref.resolve() - if(!send_ref) - ref = null - onclose(user, window_id, send_ref) - break + if (!user?.client || !winexists(user, window_id)) + continue + var/atom/send_ref + if(source_ref) + send_ref = source_ref.resolve() + if(!send_ref) + source_ref = null + onclose(user, window_id, send_ref) /datum/browser/proc/close() if(!isnull(window_id))//null check because this can potentially nuke goonchat @@ -151,106 +159,106 @@ else WARNING("Browser [title] tried to close with a null ID") -/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000) - if (!User) +/datum/browser/modal/alert/New(user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS) + if (!user) return - var/output = {"
[Message]

+ var/list/display_list = list() + display_list += {"
[message]

- [Button1]"} + [button_1]"} - if (Button2) - output += {"[Button2]"} + if (button_2) + display_list += {"[button_2]"} - if (Button3) - output += {"[Button3]"} + if (button_3) + display_list += {"[button_3]"} - output += {"
"} + display_list += {"
"} - ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout) - set_content(output) + ..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, 350, 150, src, steal_focus, timeout) + set_content(display_list.Join()) /datum/browser/modal/alert/Topic(href,href_list) if (href_list["close"] || !user || !user.client) - opentime = 0 + open_time = 0 return if (href_list["button"]) var/button = text2num(href_list["button"]) if (button <= 3 && button >= 1) - selectedbutton = button - opentime = 0 + selected_button = button + open_time = 0 close() /** * **DEPRECATED: USE tgui_alert(...) INSTEAD** * - * Designed as a drop in replacement for alert(); functions the same. (outside of needing User specified) + * Designed as a drop in replacement for alert(); functions the same. (outside of needing user specified) * Arguments: - * * User - The user to show the alert to. - * * Message - The textual body of the alert. - * * Title - The title of the alert's window. - * * Button1 - The first button option. - * * Button2 - The second button option. - * * Button3 - The third button option. - * * StealFocus - Boolean operator controlling if the alert will steal the user's window focus. - * * Timeout - The timeout of the window, after which no responses will be valid. + * * user - The user to show the alert to. + * * message - The textual body of the alert. + * * title - The title of the alert's window. + * * button_1 - The first button option. + * * button_2 - The second button option. + * * button_3 - The third button option. + * * steal_focus - Boolean operator controlling if the alert will steal the user's window focus. + * * timeout - The timeout of the window, after which no responses will be valid. */ -/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = TRUE, Timeout = 6000) - if (!User) - User = usr - if (!istype(User)) - if (istype(User, /client)) - var/client/client = User - User = client.mob - else +/proc/tg_alert(mob/user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS) + if (!user) + user = usr + if (!ismob(user)) + if (!istype(user, /client)) return + var/client/user_client = user + user = user_client.mob // Get user's response using a modal - var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout) - A.open() - A.wait() - switch(A.selectedbutton) + var/datum/browser/modal/alert/window = new(user, message, title, button_1, button_2, button_3, steal_focus, timeout) + window.open() + window.wait() + switch(window.selected_button) if (1) - return Button1 + return button_1 if (2) - return Button2 + return button_2 if (3) - return Button3 + return button_3 /datum/browser/modal - var/opentime = 0 + var/open_time = 0 var/timeout - var/selectedbutton = 0 - var/stealfocus + var/selected_button = 0 + var/steal_focus -/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null, StealFocus = 1, Timeout = 6000) +/datum/browser/modal/New(user, window_id, title = 0, width = 0, height = 0, atom/source = null, steal_focus = TRUE, timeout = 600 SECONDS) ..() - stealfocus = StealFocus - if (!StealFocus) + src.steal_focus = steal_focus + if (!src.steal_focus) window_options += "focus=false;" - timeout = Timeout - + src.timeout = timeout /datum/browser/modal/close() - .=..() - opentime = 0 + . = ..() + open_time = 0 -/datum/browser/modal/open(use_onclose) +/datum/browser/modal/open(use_on_close) set waitfor = FALSE - opentime = world.time + open_time = world.time + use_on_close = TRUE - if (stealfocus) - . = ..(use_onclose = 1) + if (steal_focus) + . = ..() else - var/focusedwindow = winget(user, null, "focus") - . = ..(use_onclose = 1) + var/focused_window = winget(user, null, "focus") + . = ..() //waits for the window to show up client side before attempting to un-focus it //winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping for (var/i in 1 to 10) if (user && winexists(user, window_id)) - if (focusedwindow) - winset(user, focusedwindow, "focus=true") + if (focused_window) + winset(user, focused_window, "focus=true") else winset(user, "mapwindow", "focus=true") break @@ -258,239 +266,235 @@ addtimer(CALLBACK(src, PROC_REF(close)), timeout) /datum/browser/modal/proc/wait() - while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time)) + while (open_time && selected_button <= 0 && (!timeout || open_time + timeout > world.time)) stoplag(1) -/datum/browser/modal/listpicker - var/valueslist = list() +/datum/browser/modal/list_picker + var/values_list = list() -/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor) - if (!User) +/datum/browser/modal/list_picker/New(user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = FALSE, list/values, input_type = "checkbox", width, height, slide_color) + if (!user) return - var/output = {"
+ "} - if (Button2) - output += {""} + if (button_2) + display_list += {""} - if (Button3) - output += {""} + if (button_3) + display_list += {""} - output += {"
"} - ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) - set_content(output) + display_list += {""} + ..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, width, height, src, steal_focus, timeout) + set_content(display_list.Join()) -/datum/browser/modal/listpicker/Topic(href,href_list) +/datum/browser/modal/list_picker/Topic(href, list/href_list) if (href_list["close"] || !user || !user.client) - opentime = 0 + open_time = 0 return if (href_list["button"]) var/button = text2num(href_list["button"]) if (button <= 3 && button >= 1) - selectedbutton = button - for (var/item in href_list) - switch(item) - if ("close", "button", "src") - continue - else - valueslist[item] = href_list[item] - opentime = 0 + selected_button = button + values_list = href_list.Copy() + values_list -= list("close", "button", "src") + open_time = 0 close() -/proc/presentpicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor) - if (!istype(User)) - if (istype(User, /client/)) - var/client/C = User - User = C.mob - else +/proc/present_picker(mob/user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS, list/values, input_type = "checkbox", width, height, slide_color) + if (!ismob(user)) + if (!istype(user, /client)) return - var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor) - A.open() - A.wait() - if (A.selectedbutton) - return list("button" = A.selectedbutton, "values" = A.valueslist) + var/client/user_client = user + user = user_client.mob + var/datum/browser/modal/list_picker/window = new(user, message, title, button_1, button_2, button_3, steal_focus, timeout, values, input_type, width, height, slide_color) + window.open() + window.wait() + if (window.selected_button) + return list("button" = window.selected_button, "values" = window.values_list) -/proc/input_bitfield(mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_flags = ALL) +/proc/input_bitfield(mob/user, title, bitfield, current_value, width = 350, height = 350, slide_color, allowed_edit_field = ALL) var/list/bitflags = get_valid_bitflags(bitfield) - if (!User || !length(bitflags)) + if (!user || !length(bitflags)) return var/list/picker_list = list() for (var/bit_name in bitflags) var/bit_value = bitflags[bit_name] - // TRUE/FALSE cast, sorry :) - var/can_edit = !!(allowed_edit_flags & bit_value) - var/flag_set = !!(current_value & bit_value) - picker_list += list(list("checked" = flag_set, "value" = bit_value, "name" = bit_name, "allowed_edit" = can_edit)) + // Gotta make it TRUE/FALSE sorry brother + var/can_edit = !!(allowed_edit_field & bit_value) + var/enabled = !!(current_value & bit_value) + picker_list += list(list("checked" = enabled, "value" = bit_value, "name" = bit_name, "allowed_edit" = can_edit)) - var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = picker_list, width = nwidth, height = nheight, slidecolor = nslidecolor) - if (islist(result)) - if (result["button"] == 2) // If the user pressed the cancel button - return - . = NONE - for (var/flag_name in result["values"]) - . |= bitflags[flag_name] - else + var/list/result = present_picker(user, "", title, button_1 = "Save", button_2 = "Cancel", timeout = FALSE, values = picker_list, width = width, height = height, slide_color = slide_color) + if (!islist(result)) + return + if (result["button"] == 2) // If the user pressed the cancel button return -/datum/browser/modal/preflikepicker + var/result_bitfield = NONE + for (var/flag_name in result["values"]) + result_bitfield |= bitflags[flag_name] + return result_bitfield + +/datum/browser/modal/pref_like_picker var/settings = list() var/icon/preview_icon = null var/datum/callback/preview_update -/datum/browser/modal/preflikepicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/settings,inputtype="checkbox", width = 600, height, slidecolor) - if (!User) +/datum/browser/modal/pref_like_picker/New(mob/user, message, title, steal_focus = TRUE, timeout = 600 SECONDS, list/settings, width, height) + if (!user) return src.settings = settings - ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) - set_content(ShowChoices(User)) + ..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, width, height, src, steal_focus, timeout) + set_content(show_choices(user)) -/datum/browser/modal/preflikepicker/proc/ShowChoices(mob/user) +/datum/browser/modal/pref_like_picker/proc/show_choices(mob/user) if (settings["preview_callback"]) var/datum/callback/callback = settings["preview_callback"] preview_icon = callback.Invoke(settings) if (preview_icon) user << browse_rsc(preview_icon, "previewicon.png") - var/dat = "" + var/list/display_list = list() for (var/name in settings["mainsettings"]) var/setting = settings["mainsettings"][name] if (setting["type"] == "datum") if (setting["subtypesonly"]) - dat += "[setting["desc"]]: [setting["value"]]
" + display_list += "[setting["desc"]]: [setting["value"]]
" else - dat += "[setting["desc"]]: [setting["value"]]
" + display_list += "[setting["desc"]]: [setting["value"]]
" else - dat += "[setting["desc"]]: [setting["value"]]
" + display_list += "[setting["desc"]]: [setting["value"]]
" if (preview_icon) - dat += "" + display_list += "" + display_list += "
" + display_list += "" - dat += "
" + display_list += "" + display_list += "
Ok " + display_list += "
" - dat += "" + return display_list.Join() - dat += "" - - dat += "
Ok " - - dat += "
" - - return dat - -/datum/browser/modal/preflikepicker/Topic(href,href_list) +/datum/browser/modal/pref_like_picker/Topic(href,href_list) if (href_list["close"] || !user || !user.client) - opentime = 0 + open_time = 0 return + if (href_list["task"] == "input") - var/setting = href_list["setting"] + var/setting_key = href_list["setting"] + var/list/setting = settings["mainsettings"][setting_key] switch (href_list["type"]) if ("datum") - var/oldval = settings["mainsettings"][setting]["value"] + var/parent_path = text2path(href_list["path"]) + var/list/paths if (href_list["subtypesonly"]) - settings["mainsettings"][setting]["value"] = pick_closest_path(null, make_types_fancy(subtypesof(text2path(href_list["path"])))) + paths = subtypesof(parent_path) else - settings["mainsettings"][setting]["value"] = pick_closest_path(null, make_types_fancy(typesof(text2path(href_list["path"])))) - if (isnull(settings["mainsettings"][setting]["value"])) - settings["mainsettings"][setting]["value"] = oldval + paths = typesof(parent_path) + + var/new_value = pick_closest_path(null, make_types_fancy(paths)) + if (!isnull(new_value)) + setting["value"] = new_value + if ("string") - settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) + setting["value"] = stripped_input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]", setting["value"]) if ("number") - settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") as num + setting["value"] = input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]") as num if ("color") - settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) as color + setting["value"] = input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]", setting["value"]) as color if ("boolean") - settings["mainsettings"][setting]["value"] = (settings["mainsettings"][setting]["value"] == "Yes") ? "No" : "Yes" + setting["value"] = (setting["value"] == "Yes") ? "No" : "Yes" if ("ckey") - settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("none") + GLOB.directory - if (settings["mainsettings"][setting]["callback"]) - var/datum/callback/callback = settings["mainsettings"][setting]["callback"] + setting["value"] = input(user, "[setting["desc"]]?") in (list("none") + GLOB.directory) + if (setting["callback"]) + var/datum/callback/callback = setting["callback"] settings = callback.Invoke(settings) + if (href_list["button"]) var/button = text2num(href_list["button"]) if (button <= 3 && button >= 1) - selectedbutton = button - if (selectedbutton != 1) - set_content(ShowChoices(user)) + selected_button = button + + if (selected_button != 1) + set_content(show_choices(user)) open() return - for (var/item in href_list) - switch(item) - if ("close", "button", "src") - continue - opentime = 0 + + open_time = 0 close() -/proc/presentpreflikepicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor) - if (!istype(User)) - if (istype(User, /client/)) - var/client/C = User - User = C.mob - else +/proc/present_pref_like_picker(mob/user, message, title, steal_focus = TRUE, timeout = 600 SECONDS, list/settings, width, height) + if (!ismob(user)) + if (!istype(user, /client)) return - var/datum/browser/modal/preflikepicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, settings, width, height, slidecolor) - A.open() - A.wait() - if (A.selectedbutton) - return list("button" = A.selectedbutton, "settings" = A.settings) + var/client/user_client = user + user = user_client.mob + var/datum/browser/modal/pref_like_picker/window = new(user, message, title, steal_focus, timeout, settings, width, height) + window.open() + window.wait() + if (window.selected_button) + return list("button" = window.selected_button, "settings" = window.settings) -// Registers the on-close verb for a browse window (client/verb/.windowclose) -// this will be called when the close-button of a window is pressed. -// -// This is usually only needed for devices that regularly update the browse window, -// e.g. canisters, timers, etc. -// -// windowid should be the specified window name -// e.g. code is : user << browse(text, "window=fred") -// then use : onclose(user, "fred") -// -// Optionally, specify the "ref" parameter as the controlled atom (usually src) +/// Registers the on-close verb for a browse window (client/verb/windowclose) +/// this will be called when the close-button of a window is pressed. +/// +/// This is usually only needed for devices that regularly update the browse window, +/// e.g. canisters, timers, etc. +/// +/// windowid should be the specified window name +/// e.g. code is : user << browse(text, "window=fred") +/// then use : onclose(user, "fred") +/// +/// Optionally, specify the "source" parameter as the controlled atom (usually src) // to pass a "close=1" parameter to the atom's Topic() proc for special handling. -// Otherwise, the user mob's machine var will be reset directly. -// -/proc/onclose(mob/user, windowid, atom/ref=null) +/// Otherwise, the user mob's machine var will be reset directly. +/// +/proc/onclose(mob/user, windowid, atom/source = null) if(!user.client) return var/param = "null" - if(ref) - param = "[REF(ref)]" + if(source) + param = "[REF(source)]" winset(user, windowid, "on-close=\".windowclose [param]\"") - - -// the on-close client verb -// called when a browser popup window is closed after registering with proc/onclose() -// if a valid atom reference is supplied, call the atom's Topic() with "close=1" -// otherwise, just reset the client mob's machine var. -// +/// the on-close client verb +/// called when a browser popup window is closed after registering with proc/onclose() +/// if a valid atom reference is supplied, call the atom's Topic() with "close=1" +/// otherwise, just reset the client mob's machine var. /client/verb/windowclose(atomref as text) set hidden = TRUE // hide this verb from the user's panel set name = ".windowclose" // no autocomplete on cmd line - if(atomref != "null") // if passed a real atomref - var/hsrc = locate(atomref) // find the reffed atom - var/href = "close=1" - if(hsrc) - usr = src.mob - src.Topic(href, params2list(href), hsrc) // this will direct to the atom's - return // Topic() proc via client.Topic() + if(atomref == "null") + return + // if passed a real atomref + var/atom/hsrc = locate(atomref) // find the reffed atom + var/href = "close=1" + if(!hsrc) + return + usr = src.mob + src.Topic(href, params2list(href), hsrc) // this will direct to the atom's diff --git a/code/game/atom/atom_vv.dm b/code/game/atom/atom_vv.dm index 796397736b7..92f8be528c6 100644 --- a/code/game/atom/atom_vv.dm +++ b/code/game/atom/atom_vv.dm @@ -80,25 +80,30 @@ if(href_list[VV_HK_ARMOR_MOD]) if(!check_rights(NONE)) return - var/list/pickerlist = list() - var/list/armorlist = get_armor().get_rating_list() - for (var/i in armorlist) - pickerlist += list(list("value" = armorlist[i], "name" = i)) - var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [src]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist) + var/list/picker_list = list() + var/list/armor_list = get_armor().get_rating_list() + for (var/rating in armor_list) + picker_list += list(list("value" = armor_list[rating], "name" = rating)) + + var/list/result = present_picker(usr, "Modify armor", "Modify armor: [src]", button_1 = "Save", button_2 = "Cancel", timeout = FALSE, input_type = "text", values = picker_list) + if(!islist(result)) + return + if(result["button"] == 2) // If the user pressed the cancel button + return + var/list/armor_all = ARMOR_LIST_ALL() - if(islist(result)) - if(result["button"] != 2) // If the user pressed the cancel button - // text2num conveniently returns a null on invalid values - var/list/converted = list() - for(var/armor_key in armor_all) - converted[armor_key] = text2num(result["values"][armor_key]) - set_armor(get_armor().generate_new_with_specific(converted)) - var/message = "[key_name(usr)] modified the armor on [src] ([type]) to: " - for(var/armor_key in armor_all) - message += "[armor_key]=[get_armor_rating(armor_key)]," - message = copytext(message, 1, -1) - log_admin(span_notice(message)) - message_admins(span_notice(message)) + // text2num conveniently returns a null on invalid values + var/list/converted = list() + for(var/armor_key in armor_all) + converted[armor_key] = text2num(result["values"][armor_key]) + set_armor(get_armor().generate_new_with_specific(converted)) + + var/message = "[key_name(usr)] modified the armor on [src] ([type]) to: " + for(var/armor_key in armor_all) + message += "[armor_key]=[get_armor_rating(armor_key)]," + message = copytext(message, 1, -1) + log_admin(span_notice(message)) + message_admins(span_notice(message)) if(href_list[VV_HK_ADD_AI]) if(!check_rights(R_VAREDIT)) diff --git a/code/game/objects/structures/detectiveboard.dm b/code/game/objects/structures/detectiveboard.dm index b2c0565bc9c..2f9aae546a2 100644 --- a/code/game/objects/structures/detectiveboard.dm +++ b/code/game/objects/structures/detectiveboard.dm @@ -189,9 +189,9 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/detectiveboard, 32) for(var/datum/paper_input/text_input as anything in paper.raw_text_inputs) paper_text += text_input.raw_text user << browse("[paper.name]" \ - + "" \ - + "[paper_text]" \ - + "", "window=photo_showing;size=480x608") + + "" \ + + "[paper_text]" \ + + "", "window=photo_showing;size=480x608") onclose(user, "[name]") if("remove_evidence") var/datum/case/case = cases[current_case] diff --git a/code/modules/admin/permissionedit.dm b/code/modules/admin/permissionedit.dm index f0ffe85aa2d..b2605fea270 100644 --- a/code/modules/admin/permissionedit.dm +++ b/code/modules/admin/permissionedit.dm @@ -471,8 +471,10 @@ ADMIN_VERB(edit_admin_permissions, R_PERMISSIONS, "Permissions Panel", "Edit adm admin_holder.rank_flags(), 350, 590, - allowed_edit_flags = usr.client.holder.can_edit_rights_flags(), + allowed_edit_field = usr.client.holder.can_edit_rights_flags(), ) + if(isnull(new_flags)) + return admin_holder.disassociate() diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index 7ee51a895ab..c7b13469333 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -71,7 +71,7 @@ unset_busy_human_dummy(DUMMY_HUMAN_SLOT_ADMIN) return preview_icon -/datum/admins/proc/makeEmergencyresponseteam(datum/ert/ertemplate = null) +/datum/admins/proc/make_emergency_response_team(datum/ert/ertemplate = null) if (ertemplate) ertemplate = new ertemplate else @@ -96,182 +96,181 @@ ) ) - var/list/prefreturn = presentpreflikepicker(usr, "Customize ERT", "Customize ERT", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings) + var/list/pref_return = present_pref_like_picker(usr, "Customize ERT", "Customize ERT", width = 600, timeout = 0, settings = settings) - if (isnull(prefreturn)) + if (isnull(pref_return)) return FALSE - if (prefreturn["button"] == 1) - var/list/prefs = settings["mainsettings"] + if (pref_return["button"] != 1) + return FALSE - var/templtype = prefs["template"]["value"] - if (!ispath(prefs["template"]["value"])) - templtype = text2path(prefs["template"]["value"]) // new text2path ... doesn't compile in 511 + var/list/prefs = settings["mainsettings"] - if (ertemplate.type != templtype) - ertemplate = new templtype + var/templtype = prefs["template"]["value"] + if (!ispath(prefs["template"]["value"])) + templtype = text2path(prefs["template"]["value"]) // new text2path ... doesn't compile in 511 - ertemplate.teamsize = prefs["teamsize"]["value"] - ertemplate.mission = prefs["mission"]["value"] - ertemplate.polldesc = prefs["polldesc"]["value"] - ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" // these next 6 are effectively toggles - ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes" - ertemplate.leader_experience = prefs["leader_experience"]["value"] == "Yes" - ertemplate.random_names = prefs["random_names"]["value"] == "Yes" - ertemplate.spawn_admin = prefs["spawn_admin"]["value"] == "Yes" - ertemplate.use_custom_shuttle = prefs["use_custom_shuttle"]["value"] == "Yes" - ertemplate.mob_type = prefs["mob_type"]["value"] + if (ertemplate.type != templtype) + ertemplate = new templtype - var/list/spawnpoints = GLOB.emergencyresponseteamspawn - var/index = 0 + ertemplate.teamsize = prefs["teamsize"]["value"] + ertemplate.mission = prefs["mission"]["value"] + ertemplate.polldesc = prefs["polldesc"]["value"] + ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" // these next 6 are effectively toggles + ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes" + ertemplate.leader_experience = prefs["leader_experience"]["value"] == "Yes" + ertemplate.random_names = prefs["random_names"]["value"] == "Yes" + ertemplate.spawn_admin = prefs["spawn_admin"]["value"] == "Yes" + ertemplate.use_custom_shuttle = prefs["use_custom_shuttle"]["value"] == "Yes" + ertemplate.mob_type = prefs["mob_type"]["value"] - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for [span_notice(ertemplate.polldesc)]?", check_jobban = "deathsquad", alert_pic = /obj/item/card/id/advanced/centcom/ert, role_name_text = "emergency response team") - var/teamSpawned = FALSE + var/list/spawn_points = GLOB.emergencyresponseteamspawn - // This list will take priority over spawnpoints if not empty - var/list/spawn_turfs = list() + var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for [span_notice(ertemplate.polldesc)]?", check_jobban = "deathsquad", alert_pic = /obj/item/card/id/advanced/centcom/ert, role_name_text = "emergency response team") + var/team_spawned = 0 - // Takes precedence over spawnpoints[1] if not null - var/turf/brief_spawn + // This list will take priority over spawn_points if not empty + var/list/spawn_turfs = list() - if(!length(candidates)) - return FALSE + // Takes precedence over spawn_points[1] if not null + var/turf/brief_spawn - if(ertemplate.use_custom_shuttle && ertemplate.ert_template) - to_chat(usr, span_boldnotice("Attempting to spawn ERT custom shuttle, this may take a few seconds...")) - var/datum/map_template/shuttle/ship = new ertemplate.ert_template - var/x = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE - ship.width) - var/y = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE - ship.height) - var/z = SSmapping.empty_space.z_value - var/turf/located_turf = locate(x, y, z) - if(!located_turf) - CRASH("ERT shuttle found no place to load in") + if(!length(candidates)) + return FALSE - if(!ship.load(located_turf)) - CRASH("Loading ERT shuttle failed!") + if(ertemplate.use_custom_shuttle && ertemplate.ert_template) + to_chat(usr, span_boldnotice("Attempting to spawn ERT custom shuttle, this may take a few seconds...")) + var/datum/map_template/shuttle/ship = new ertemplate.ert_template + var/x = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE - ship.width) + var/y = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE - ship.height) + var/z = SSmapping.empty_space.z_value + var/turf/located_turf = locate(x, y, z) + if(!located_turf) + CRASH("ERT shuttle found no place to load in") - var/list/shuttle_turfs = ship.get_affected_turfs(located_turf) + if(!ship.load(located_turf)) + CRASH("Loading ERT shuttle failed!") - for(var/turf/affected_turf as anything in shuttle_turfs) - for(var/obj/effect/landmark/ert_shuttle_spawn/spawner in affected_turf) - spawn_turfs += get_turf(spawner) + var/list/shuttle_turfs = ship.get_affected_turfs(located_turf) - if(!brief_spawn) - brief_spawn = get_turf(locate(/obj/effect/landmark/ert_shuttle_brief_spawn) in affected_turf) + for(var/turf/affected_turf as anything in shuttle_turfs) + for(var/obj/effect/landmark/ert_shuttle_spawn/spawner in affected_turf) + spawn_turfs += get_turf(spawner) - if(!length(spawn_turfs)) - stack_trace("ERT shuttle loaded but found no spawnpoints, placing the ERT at wherever inside the shuttle instead.") + if(!brief_spawn) + brief_spawn = get_turf(locate(/obj/effect/landmark/ert_shuttle_brief_spawn) in affected_turf) - for(var/turf/open/floor/open_turf in shuttle_turfs) - if(!is_safe_turf(open_turf)) - continue - spawn_turfs += open_turf + if(!length(spawn_turfs)) + stack_trace("ERT shuttle loaded but found no spawn points, placing the ERT at wherever inside the shuttle instead.") + + for(var/turf/open/floor/open_turf in shuttle_turfs) + if(!is_safe_turf(open_turf)) + continue + spawn_turfs += open_turf - if(ertemplate.spawn_admin) - if(isobserver(usr)) - var/mob/living/carbon/human/admin_officer = new (brief_spawn || spawnpoints[1]) - var/chosen_outfit = usr.client?.prefs?.read_preference(/datum/preference/choiced/brief_outfit) - usr.client.prefs.safe_transfer_prefs_to(admin_officer, is_antag = TRUE) - admin_officer.equipOutfit(chosen_outfit) - admin_officer.PossessByPlayer(usr.key) + if(ertemplate.spawn_admin) + if(isobserver(usr)) + var/mob/living/carbon/human/admin_officer = new (brief_spawn || spawn_points[1]) + var/chosen_outfit = usr.client?.prefs?.read_preference(/datum/preference/choiced/brief_outfit) + usr.client.prefs.safe_transfer_prefs_to(admin_officer, is_antag = TRUE) + admin_officer.equipOutfit(chosen_outfit) + admin_officer.PossessByPlayer(usr.key) - else - to_chat(usr, span_warning("Could not spawn you in as briefing officer as you are not a ghost!")) - - //Pick the (un)lucky players - var/numagents = min(ertemplate.teamsize, length(candidates)) - - //Create team - var/datum/team/ert/ert_team = new ertemplate.team() - if(ertemplate.rename_team) - ert_team.name = ertemplate.rename_team - - //Assign team objective - var/datum/objective/missionobj = new () - missionobj.team = ert_team - missionobj.explanation_text = ertemplate.mission - missionobj.completed = TRUE - ert_team.objectives += missionobj - ert_team.mission = missionobj - - var/mob/dead/observer/earmarked_leader - var/leader_spawned = FALSE // just in case the earmarked leader disconnects or becomes unavailable, we can try giving leader to the last guy to get chosen - - if(ertemplate.leader_experience) - var/list/candidate_living_exps = list() - for(var/i in candidates) - var/mob/dead/observer/potential_leader = i - candidate_living_exps[potential_leader] = potential_leader.client?.get_exp_living(TRUE) - - candidate_living_exps = sort_list(candidate_living_exps, cmp=/proc/cmp_numeric_dsc) - if(candidate_living_exps.len > ERT_EXPERIENCED_LEADER_CHOOSE_TOP) - candidate_living_exps.Cut(ERT_EXPERIENCED_LEADER_CHOOSE_TOP+1) // pick from the top ERT_EXPERIENCED_LEADER_CHOOSE_TOP contenders in playtime - earmarked_leader = pick(candidate_living_exps) else - earmarked_leader = pick(candidates) + to_chat(usr, span_warning("Could not spawn you in as briefing officer as you are not a ghost!")) - while(numagents && candidates.len) - var/turf/spawnloc - if(length(spawn_turfs)) - spawnloc = pick(spawn_turfs) - else - spawnloc = spawnpoints[index+1] - //loop through spawnpoints one at a time - index = (index + 1) % spawnpoints.len + //Pick the (un)lucky players + var/numagents = min(ertemplate.teamsize, length(candidates)) - var/mob/dead/observer/chosen_candidate = earmarked_leader || pick(candidates) // this way we make sure that our leader gets chosen - candidates -= chosen_candidate - if(!chosen_candidate?.key) - continue + //Create team + var/datum/team/ert/ert_team = new ertemplate.team() + if(ertemplate.rename_team) + ert_team.name = ertemplate.rename_team - //Spawn the body - var/mob/living/carbon/human/ert_operative - if(ertemplate.mob_type) - ert_operative = new ertemplate.mob_type(spawnloc) - else - ert_operative = new /mob/living/carbon/human(spawnloc) - chosen_candidate.client.prefs.safe_transfer_prefs_to(ert_operative, is_antag = TRUE) - ert_operative.PossessByPlayer(chosen_candidate.key) + //Assign team objective + var/datum/objective/missionobj = new () + missionobj.team = ert_team + missionobj.explanation_text = ertemplate.mission + missionobj.completed = TRUE + ert_team.objectives += missionobj + ert_team.mission = missionobj - if(ertemplate.enforce_human || !(ert_operative.dna.species.changesource_flags & ERT_SPAWN)) - ert_operative.set_species(/datum/species/human) + var/mob/dead/observer/earmarked_leader + var/leader_spawned = FALSE // just in case the earmarked leader disconnects or becomes unavailable, we can try giving leader to the last guy to get chosen - //Give antag datum - var/datum/antagonist/ert/ert_antag + if(ertemplate.leader_experience) + var/list/candidate_living_exps = list() + for(var/i in candidates) + var/mob/dead/observer/potential_leader = i + candidate_living_exps[potential_leader] = potential_leader.client?.get_exp_living(TRUE) - if((chosen_candidate == earmarked_leader) || (numagents == 1 && !leader_spawned)) - ert_antag = new ertemplate.leader_role () - earmarked_leader = null - leader_spawned = TRUE - else - ert_antag = ertemplate.roles[WRAP(numagents,1,length(ertemplate.roles) + 1)] - ert_antag = new ert_antag () - ert_antag.random_names = ertemplate.random_names + candidate_living_exps = sort_list(candidate_living_exps, cmp=/proc/cmp_numeric_dsc) + if(candidate_living_exps.len > ERT_EXPERIENCED_LEADER_CHOOSE_TOP) + candidate_living_exps.Cut(ERT_EXPERIENCED_LEADER_CHOOSE_TOP+1) // pick from the top ERT_EXPERIENCED_LEADER_CHOOSE_TOP contenders in playtime + earmarked_leader = pick(candidate_living_exps) + else + earmarked_leader = pick(candidates) - ert_operative.mind.add_antag_datum(ert_antag,ert_team) - ert_operative.mind.set_assigned_role(SSjob.get_job_type(ert_antag.ert_job_path)) + var/spawn_index = 0 + while(numagents && candidates.len) + var/turf/spawnloc + if(length(spawn_turfs)) + spawnloc = pick(spawn_turfs) + else + spawnloc = spawn_points[spawn_index+1] + spawn_index = WRAP_UP(spawn_index, spawn_points.len) - //Logging and cleanup - ert_operative.log_message("has been selected as \a [ert_antag.name].", LOG_GAME) - numagents-- - teamSpawned++ + var/mob/dead/observer/chosen_candidate = earmarked_leader || pick(candidates) // this way we make sure that our leader gets chosen + candidates -= chosen_candidate + if(!chosen_candidate?.key) + continue - if (teamSpawned) - message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]") + //Spawn the body + var/mob/living/carbon/human/ert_operative + if(ertemplate.mob_type) + ert_operative = new ertemplate.mob_type(spawnloc) + else + ert_operative = new /mob/living/carbon/human(spawnloc) + chosen_candidate.client.prefs.safe_transfer_prefs_to(ert_operative, is_antag = TRUE) + ert_operative.PossessByPlayer(chosen_candidate.key) - //Open the Armory doors - if(ertemplate.opendoors) - for(var/obj/machinery/door/poddoor/ert/door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor/ert)) - door.open() - CHECK_TICK - return TRUE + if(ertemplate.enforce_human || !(ert_operative.dna.species.changesource_flags & ERT_SPAWN)) + ert_operative.set_species(/datum/species/human) - return + //Give antag datum + var/datum/antagonist/ert/ert_antag + + if((chosen_candidate == earmarked_leader) || (numagents == 1 && !leader_spawned)) + ert_antag = new ertemplate.leader_role () + earmarked_leader = null + leader_spawned = TRUE + else + ert_antag = ertemplate.roles[WRAP(numagents,1,length(ertemplate.roles) + 1)] + ert_antag = new ert_antag () + ert_antag.random_names = ertemplate.random_names + + ert_operative.mind.add_antag_datum(ert_antag,ert_team) + ert_operative.mind.set_assigned_role(SSjob.get_job_type(ert_antag.ert_job_path)) + + //Logging and cleanup + ert_operative.log_message("has been selected as \a [ert_antag.name].", LOG_GAME) + numagents-- + team_spawned++ + + if (team_spawned != 0) + message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]") + + //Open the Armory doors + if(ertemplate.opendoors) + for(var/obj/machinery/door/poddoor/ert/door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor/ert)) + door.open() + CHECK_TICK + return TRUE ADMIN_VERB(summon_ert, R_FUN, "Summon ERT", "Summons an emergency response team.", ADMIN_CATEGORY_FUN) message_admins("[key_name_admin(user)] is creating a CentCom response team...") - if(user.holder?.makeEmergencyresponseteam()) + if(user.holder?.make_emergency_response_team()) message_admins("[key_name_admin(user)] created a CentCom response team.") log_admin("[key_name(user)] created a CentCom response team.") else diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index 446b5d72219..9ec5ebdbcda 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -47,7 +47,6 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w return if((action != "admin_log" || action != "show_admins") && !check_rights(R_ADMIN)) return - var/datum/round_event/E switch(action) //Generic Buttons anyone can use. if("admin_log") @@ -419,57 +418,59 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w ) message_admins("[key_name(holder)] is creating a custom portal storm...") - var/list/prefreturn = presentpreflikepicker(holder,"Customize Portal Storm", "Customize Portal Storm", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings) + var/list/pref_return = present_pref_like_picker(holder, "Customize Portal Storm", "Customize Portal Storm", width = 600, timeout = 0, settings = settings) - if (prefreturn["button"] == 1) - var/list/prefs = settings["mainsettings"] + if (pref_return["button"] != 1) + return - if (prefs["amount"]["value"] < 1 || prefs["portalnum"]["value"] < 1) - to_chat(holder, span_warning("Number of portals and mobs to spawn must be at least 1."), confidential = TRUE) - return + var/list/prefs = settings["mainsettings"] - var/mob/pathToSpawn = prefs["typepath"]["value"] - if (!ispath(pathToSpawn)) - pathToSpawn = text2path(pathToSpawn) + if (prefs["amount"]["value"] < 1 || prefs["portalnum"]["value"] < 1) + to_chat(holder, span_warning("Number of portals and mobs to spawn must be at least 1."), confidential = TRUE) + return - if (!ispath(pathToSpawn)) - to_chat(holder, span_notice("Invalid path [pathToSpawn]."), confidential = TRUE) - return + var/mob/path_to_spawn = prefs["typepath"]["value"] + if (!ispath(path_to_spawn)) + path_to_spawn = text2path(path_to_spawn) - var/list/candidates = list() + if (!ispath(path_to_spawn)) + to_chat(holder, span_notice("Invalid path [path_to_spawn]."), confidential = TRUE) + return - if (prefs["offerghosts"]["value"] == "Yes") - candidates = SSpolling.poll_ghost_candidates(replacetext(prefs["ghostpoll"]["value"], "%TYPE%", initial(pathToSpawn.name)), check_jobban = ROLE_TRAITOR, alert_pic = pathToSpawn, role_name_text = "portal storm") + var/list/candidates = list() - if (prefs["playersonly"]["value"] == "Yes" && length(candidates) < prefs["minplayers"]["value"]) + if (prefs["offerghosts"]["value"] == "Yes") + candidates = SSpolling.poll_ghost_candidates(replacetext(prefs["ghostpoll"]["value"], "%TYPE%", initial(path_to_spawn.name)), check_jobban = ROLE_TRAITOR, alert_pic = path_to_spawn, role_name_text = "portal storm") + if (length(candidates) < prefs["minplayers"]["value"]) message_admins("Not enough players signed up to create a portal storm, the minimum was [prefs["minplayers"]["value"]] and the number of signups [length(candidates)]") return - if (prefs["announce_players"]["value"] == "Yes") - portalAnnounce(prefs["announcement"]["value"], (prefs["playlightning"]["value"] == "Yes" ? TRUE : FALSE)) + if (prefs["announce_players"]["value"] == "Yes") + portal_announce(prefs["announcement"]["value"], (prefs["playlightning"]["value"] == "Yes" ? TRUE : FALSE)) - var/list/storm_appearances = list() - for(var/offset in 0 to SSmapping.max_plane_offset) - var/mutable_appearance/storm = mutable_appearance('icons/obj/machines/engine/energy_ball.dmi', "energy_ball_fast", FLY_LAYER) - SET_PLANE_W_SCALAR(storm, ABOVE_GAME_PLANE, offset) - storm.color = prefs["color"]["value"] - storm_appearances += storm + var/list/storm_appearances = list() + for(var/offset in 0 to SSmapping.max_plane_offset) + var/mutable_appearance/storm = mutable_appearance('icons/obj/machines/engine/energy_ball.dmi', "energy_ball_fast", FLY_LAYER) + SET_PLANE_W_SCALAR(storm, ABOVE_GAME_PLANE, offset) + storm.color = prefs["color"]["value"] + storm_appearances += storm - message_admins("[key_name_admin(holder)] has created a customized portal storm that will spawn [prefs["portalnum"]["value"]] portals, each of them spawning [prefs["amount"]["value"]] of [pathToSpawn]") - log_admin("[key_name(holder)] has created a customized portal storm that will spawn [prefs["portalnum"]["value"]] portals, each of them spawning [prefs["amount"]["value"]] of [pathToSpawn]") + message_admins("[key_name_admin(holder)] has created a customized portal storm that will spawn [prefs["portalnum"]["value"]] portals, each of them spawning [prefs["amount"]["value"]] of [path_to_spawn]") + log_admin("[key_name(holder)] has created a customized portal storm that will spawn [prefs["portalnum"]["value"]] portals, each of them spawning [prefs["amount"]["value"]] of [path_to_spawn]") - var/outfit = prefs["humanoutfit"]["value"] - if (!ispath(outfit)) - outfit = text2path(outfit) + var/outfit = prefs["humanoutfit"]["value"] + if (!ispath(outfit)) + outfit = text2path(outfit) + + for (var/i in 1 to prefs["portalnum"]["value"]) + if (length(candidates)) // if we're spawning players, gotta be a little tricky and also not spawn players on top of NPCs + var/ghostcandidates = list() + for (var/j in 1 to min(prefs["amount"]["value"], length(candidates))) + ghostcandidates += pick_n_take(candidates) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(do_portal_spawn), get_random_station_turf(), path_to_spawn, length(ghostcandidates), storm_appearances, ghostcandidates, outfit), i * prefs["delay"]["value"]) + else if (prefs["playersonly"]["value"] != "Yes") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(do_portal_spawn), get_random_station_turf(), path_to_spawn, prefs["amount"]["value"], storm_appearances, null, outfit), i * prefs["delay"]["value"]) - for (var/i in 1 to prefs["portalnum"]["value"]) - if (length(candidates)) // if we're spawning players, gotta be a little tricky and also not spawn players on top of NPCs - var/ghostcandidates = list() - for (var/j in 1 to min(prefs["amount"]["value"], length(candidates))) - ghostcandidates += pick_n_take(candidates) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(doPortalSpawn), get_random_station_turf(), pathToSpawn, length(ghostcandidates), storm_appearances, ghostcandidates, outfit), i*prefs["delay"]["value"]) - else if (prefs["playersonly"]["value"] != "Yes") - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(doPortalSpawn), get_random_station_turf(), pathToSpawn, prefs["amount"]["value"], storm_appearances, null, outfit), i*prefs["delay"]["value"]) if("changebombcap") if(!is_funmin) return @@ -680,24 +681,12 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w message_admins("[key_name_admin(holder)] healed everyone.") log_admin("[key_name(holder)] healed everyone.") - if(E) - E.processing = FALSE - if(E.announce_when>0) - switch(tgui_alert(holder, "Would you like to alert the crew?", "Alert", list("Yes", "No", "Cancel"))) - if("Yes") - E.announce_chance = 100 - if("Cancel") - E.kill() - return - if("No") - E.announce_chance = 0 - E.processing = TRUE if(holder) log_admin("[key_name(holder)] used secret: [action].") #undef THUNDERDOME_TEMPLATE_FILE #undef HIGHLANDER_DELAY_TEXT -/proc/portalAnnounce(announcement, playlightning) +/proc/portal_announce(announcement, playlightning) set waitfor = FALSE if (playlightning) sound_to_playing_players('sound/effects/magic/lightning_chargeup.ogg') @@ -709,7 +698,7 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w /// Spawns a portal storm that spawns in sentient/non sentient mobs /// portal_appearance is a list in the form (turf's plane offset + 1) -> appearance to use -/proc/doPortalSpawn(turf/loc, mobtype, numtospawn, list/portal_appearance, players, humanoutfit) +/proc/do_portal_spawn(turf/loc, mobtype, numtospawn, list/portal_appearance, players, humanoutfit) for (var/i in 1 to numtospawn) var/mob/spawnedMob = new mobtype(loc) if (length(players)) diff --git a/code/modules/admin/verbs/spawnobjasmob.dm b/code/modules/admin/verbs/spawnobjasmob.dm index c8d9ba3719d..56fe8fbf84f 100644 --- a/code/modules/admin/verbs/spawnobjasmob.dm +++ b/code/modules/admin/verbs/spawnobjasmob.dm @@ -64,44 +64,46 @@ ADMIN_VERB(spawn_obj_as_mob, R_SPAWN, "Spawn Object-Mob", "Spawn an object as if ), )) - var/list/prefreturn = presentpreflikepicker(user.mob,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings) - if (prefreturn["button"] == 1) - settings = prefreturn["settings"] - var/mainsettings = settings["mainsettings"] - chosen_obj = text2path(mainsettings["objtype"]["value"]) + var/list/pref_return = present_pref_like_picker(user.mob, "Customize mob", "Customize mob", width = 450, timeout = 0, settings = settings) + if (pref_return["button"] != 1) + return - basemob = text2path(mainsettings["mobtype"]["value"]) - if (!ispath(basemob, /mob/living/basic/mimic/copy) || !ispath(chosen_obj, /obj)) - to_chat(user.mob, "Mob or object path invalid", confidential = TRUE) + settings = pref_return["settings"] + var/mainsettings = settings["mainsettings"] + chosen_obj = text2path(mainsettings["objtype"]["value"]) - basemob = new basemob(get_turf(user.mob), new chosen_obj(get_turf(user.mob)), user.mob, mainsettings["dropitem"]["value"] == "Yes" ? FALSE : TRUE, (mainsettings["googlyeyes"]["value"] == "Yes" ? FALSE : TRUE)) + basemob = text2path(mainsettings["mobtype"]["value"]) + if (!ispath(basemob, /mob/living/basic/mimic/copy) || !ispath(chosen_obj, /obj)) + to_chat(user.mob, "Mob or object path invalid", confidential = TRUE) - if (mainsettings["disableai"]["value"] == "Yes") - qdel(basemob.ai_controller) - basemob.ai_controller = null + basemob = new basemob(get_turf(user.mob), new chosen_obj(get_turf(user.mob)), user.mob, mainsettings["dropitem"]["value"] == "Yes" ? FALSE : TRUE, (mainsettings["googlyeyes"]["value"] == "Yes" ? FALSE : TRUE)) - if (mainsettings["idledamage"]["value"] == "No") - basemob.idledamage = FALSE + if (mainsettings["disableai"]["value"] == "Yes") + qdel(basemob.ai_controller) + basemob.ai_controller = null - if (mainsettings["access"]) - var/newaccess = text2path(mainsettings["access"]["value"]) - if (ispath(newaccess)) - var/obj/item/card/id/id = new newaccess //cant do initial on lists - basemob.AddComponent(/datum/component/simple_access, id.access) - qdel(id) + if (mainsettings["idledamage"]["value"] == "No") + basemob.idledamage = FALSE - if (mainsettings["maxhealth"]["value"]) - if (!isnum(mainsettings["maxhealth"]["value"])) - mainsettings["maxhealth"]["value"] = text2num(mainsettings["maxhealth"]["value"]) - if (mainsettings["maxhealth"]["value"] > 0) - basemob.maxHealth = basemob.maxHealth = mainsettings["maxhealth"]["value"] + if (mainsettings["access"]) + var/newaccess = text2path(mainsettings["access"]["value"]) + if (ispath(newaccess)) + var/obj/item/card/id/id = new newaccess //cant do initial on lists + basemob.AddComponent(/datum/component/simple_access, id.access) + qdel(id) - if (mainsettings["name"]["value"]) - basemob.name = basemob.real_name = html_decode(mainsettings["name"]["value"]) + if (mainsettings["maxhealth"]["value"]) + if (!isnum(mainsettings["maxhealth"]["value"])) + mainsettings["maxhealth"]["value"] = text2num(mainsettings["maxhealth"]["value"]) + if (mainsettings["maxhealth"]["value"] > 0) + basemob.maxHealth = basemob.maxHealth = mainsettings["maxhealth"]["value"] - if (mainsettings["ckey"]["value"] != "none") - basemob.ckey = mainsettings["ckey"]["value"] + if (mainsettings["name"]["value"]) + basemob.name = basemob.real_name = html_decode(mainsettings["name"]["value"]) + + if (mainsettings["ckey"]["value"] != "none") + basemob.ckey = mainsettings["ckey"]["value"] - log_admin("[key_name(user.mob)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(user.mob)]") - BLACKBOX_LOG_ADMIN_VERB("Spawn object-mob") + log_admin("[key_name(user.mob)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(user.mob)]") + BLACKBOX_LOG_ADMIN_VERB("Spawn object-mob") diff --git a/code/modules/discord/accountlink.dm b/code/modules/discord/accountlink.dm index e3227ae9004..3ef8ff527e4 100644 --- a/code/modules/discord/accountlink.dm +++ b/code/modules/discord/accountlink.dm @@ -32,7 +32,7 @@ message = "Your one time token is: [one_time_token]. Assuming you have the required living minutes in game, you can now verify yourself on Discord by using the command: [prefix]verify [one_time_token]" //Now give them a browse window so they can't miss whatever we told them - var/datum/browser/window = new/datum/browser(usr, "discordverification", "Discord Verification") + var/datum/browser/window = new /datum/browser(usr, "discordverification", "Discord Verification") window.set_content("
[message]
") window.open() diff --git a/code/modules/error_handler/error_viewer.dm b/code/modules/error_handler/error_viewer.dm index 8080f3005dd..fa0d1dcc981 100644 --- a/code/modules/error_handler/error_viewer.dm +++ b/code/modules/error_handler/error_viewer.dm @@ -27,7 +27,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) /datum/error_viewer/proc/browse_to(client/user, html) var/datum/browser/browser = new(user.mob, "error_viewer", null, 600, 400) browser.set_content(html) - browser.add_head_content({" + browser.set_head_content({"