diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml index b3f02e955a..d0ab3fe4f6 100644 --- a/.github/workflows/autochangelog.yml +++ b/.github/workflows/autochangelog.yml @@ -22,7 +22,7 @@ jobs: - name: Ensure +x on CI directory run: | chmod -R +x ./tools/ci - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.7' - name: Generate Changelog diff --git a/code/__defines/chat.dm b/code/__defines/chat.dm index 37624e1f4d..70ac35bada 100644 --- a/code/__defines/chat.dm +++ b/code/__defines/chat.dm @@ -3,6 +3,11 @@ * SPDX-License-Identifier: MIT */ +/// How many chat payloads to keep in history +#define CHAT_RELIABILITY_HISTORY_SIZE 5 +/// How many resends to allow before giving up +#define CHAT_RELIABILITY_MAX_RESENDS 3 + #define MESSAGE_TYPE_SYSTEM "system" #define MESSAGE_TYPE_LOCALCHAT "localchat" #define MESSAGE_TYPE_PLOCALCHAT "plocalchat" @@ -10,6 +15,7 @@ #define MESSAGE_TYPE_NIF "nif" #define MESSAGE_TYPE_INFO "info" #define MESSAGE_TYPE_WARNING "warning" +#define MESSAGE_TYPE_VORE "vore" #define MESSAGE_TYPE_DEADCHAT "deadchat" #define MESSAGE_TYPE_OOC "ooc" #define MESSAGE_TYPE_LOOC "looc" diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index 31970b792f..47be30be4e 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -519,6 +519,37 @@ GLOBAL_LIST_EMPTY(cached_examine_icons) return list(rsc_ref, hash, "asset.[hash]") +/// Gets a dummy savefile for usage in icon generation. +/// Savefiles generated from this proc will be empty. +/proc/get_dummy_savefile(from_failure = FALSE) + var/static/next_id = 0 + if(next_id++ > 9) + next_id = 0 + var/savefile_path = "tmp/dummy-save-[next_id].sav" + try + if(fexists(savefile_path)) + fdel(savefile_path) + return new /savefile(savefile_path) + catch(var/exception/error) + // if we failed to create a dummy once, try again; maybe someone slept somewhere they shouldnt have + if(from_failure) // this *is* the retry, something fucked up + CRASH("get_dummy_savefile failed to create a dummy savefile: '[error]'") + return get_dummy_savefile(from_failure = TRUE) + +/** + * Converts an icon to base64. Operates by putting the icon in the iconCache savefile, + * exporting it as text, and then parsing the base64 from that. + * (This relies on byond automatically storing icons in savefiles as base64) + */ +/proc/icon2base64(icon/icon) + if (!isicon(icon)) + return FALSE + var/savefile/dummySave = get_dummy_savefile() + WRITE_FILE(dummySave["dummy"], icon) + var/iconData = dummySave.ExportText("dummy") + var/list/partial = splittext(iconData, "{") + return replacetext(copytext_char(partial[2], 3, -5), "\n", "") //if cleanup fails we want to still return the correct base64 + ///given a text string, returns whether it is a valid dmi icons folder path /proc/is_valid_dmi_file(icon_path) if(!istext(icon_path) || !length(icon_path)) @@ -673,6 +704,39 @@ GLOBAL_LIST_EMPTY(cached_examine_icons) return get_asset_url(key) return "" +/proc/icon2base64html(target, var/custom_classes = "") + if (!target) + return + var/static/list/bicon_cache = list() + if (isicon(target)) + var/icon/target_icon = target + var/icon_base64 = icon2base64(target_icon) + + if (target_icon.Height() > world.icon_size || target_icon.Width() > world.icon_size) + var/icon_md5 = md5(icon_base64) + icon_base64 = bicon_cache[icon_md5] + if (!icon_base64) // Doesn't exist yet, make it. + bicon_cache[icon_md5] = icon_base64 = icon2base64(target_icon) + + + return "" + + // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with. + var/atom/target_atom = target + var/key = "[istype(target_atom.icon, /icon) ? "[REF(target_atom.icon)]" : target_atom.icon]:[target_atom.icon_state]" + + + if (!bicon_cache[key]) // Doesn't exist, make it. + var/icon/target_icon = icon(target_atom.icon, target_atom.icon_state, SOUTH, 1) + if (ishuman(target)) // Shitty workaround for a BYOND issue. + var/icon/temp = target_icon + target_icon = icon() + target_icon.Insert(temp, dir = SOUTH) + + bicon_cache[key] = icon2base64(target_icon) + + return "" + //Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs. /proc/costly_icon2html(thing, target, sourceonly = FALSE) if (!thing) diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index 737b00a7d0..fb1ba7fa07 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -46,7 +46,9 @@ for(var/client/C in GLOB.admins) if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs)) - to_chat(C, "DEBUG: [text]") + to_chat(C, + type = MESSAGE_TYPE_DEBUG, + html = "DEBUG: [text]") /proc/log_game(text) if (config.log_game) diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index c0b6bd5001..07a2bfaceb 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -345,7 +345,7 @@ if(!text_tag_cache[tagname]) var/icon/tag = icon(text_tag_icons, tagname) text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag") - if(C.chatOutput.broken) + if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat) return "[tagdesc]" return text_tag_cache[tagname] diff --git a/code/_macros.dm b/code/_macros.dm index 737b317abe..169a897881 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -12,7 +12,7 @@ // #define to_chat(target, message) target << message Not anymore! //#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat -#define to_chat __to_chat +//#define to_chat __to_chat #define to_world(message) to_chat(world, message) #define to_world_log(message) world.log << message // TODO - Baystation has this log to crazy places. For now lets just world.log, but maybe look into it later. diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 213fe57b90..a7ff03177d 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -89,7 +89,7 @@ // cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc)) if(isturf(A) || isturf(A.loc)) - if(A.Adjacent(src)) // see adjacent.dm + if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach))) // see adjacent.dm, allows robots to use ranged melee weapons var/resolved = A.attackby(W, src, 1) if(!resolved && A && W) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 114f178653..c494fd685e 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -217,13 +217,13 @@ var/obj/screen/robot_inventory update_robot_modules_display() -/datum/hud/proc/update_robot_modules_display() +/datum/hud/proc/update_robot_modules_display(var/reset = FALSE) if(!isrobot(mymob)) return var/mob/living/silicon/robot/r = mymob - if(r.shown_robot_modules) + if(r.shown_robot_modules && !reset) //Modules display is shown //r.client.screen += robot_inventory //"store" icon @@ -292,4 +292,4 @@ var/obj/screen/robot_inventory return sprite_datum.sprite_hud_icon_state if(modtype) return lowertext(modtype) - return "nomod" \ No newline at end of file + return "nomod" diff --git a/code/controllers/subsystems/chat.dm b/code/controllers/subsystems/chat.dm index 92a1be2757..b8b2917c8d 100644 --- a/code/controllers/subsystems/chat.dm +++ b/code/controllers/subsystems/chat.dm @@ -1,77 +1,100 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + SUBSYSTEM_DEF(chat) name = "Chat" - flags = SS_TICKER - wait = 1 // SS_TICKER means this runs every tick + flags = SS_TICKER|SS_NO_INIT + wait = 1 priority = FIRE_PRIORITY_CHAT init_order = INIT_ORDER_CHAT - var/list/list/msg_queue = list() //List of lists + /// Assosciates a ckey with a list of messages to send to them. + var/list/list/datum/chat_payload/client_to_payloads = list() -/datum/controller/subsystem/chat/Initialize(timeofday) - init_vchat() - ..() + /// Associates a ckey with an assosciative list of their last CHAT_RELIABILITY_HISTORY_SIZE messages. + var/list/list/datum/chat_payload/client_to_reliability_history = list() + + /// Assosciates a ckey with their next sequence number. + var/list/client_to_sequence_number = list() + +/datum/controller/subsystem/chat/proc/generate_payload(client/target, message_data) + var/sequence = client_to_sequence_number[target.ckey] + client_to_sequence_number[target.ckey] += 1 + + var/datum/chat_payload/payload = new + payload.sequence = sequence + payload.content = message_data + + if(!(target.ckey in client_to_reliability_history)) + client_to_reliability_history[target.ckey] = list() + var/list/client_history = client_to_reliability_history[target.ckey] + client_history["[sequence]"] = payload + + if(length(client_history) > CHAT_RELIABILITY_HISTORY_SIZE) + var/oldest = text2num(client_history[1]) + for(var/index in 2 to length(client_history)) + var/test = text2num(client_history[index]) + if(test < oldest) + oldest = test + client_history -= "[oldest]" + return payload + +/datum/controller/subsystem/chat/proc/send_payload_to_client(client/target, datum/chat_payload/payload) + target.tgui_panel.window.send_message("chat/message", payload.into_message()) + SEND_TEXT(target, payload.get_content_as_html()) /datum/controller/subsystem/chat/fire() - var/list/msg_queue = src.msg_queue // Local variable for sanic speed. - for(var/client/C as anything in msg_queue) - var/list/messages = msg_queue[C] - msg_queue -= C - if (C) - C << output(jsEncode(messages), "htmloutput:putmessage") + for(var/ckey in client_to_payloads) + var/client/target = GLOB.directory[ckey] + if(isnull(target)) // verify client still exists + LAZYREMOVE(client_to_payloads, ckey) + continue + + for(var/datum/chat_payload/payload as anything in client_to_payloads[ckey]) + send_payload_to_client(target, payload) + LAZYREMOVE(client_to_payloads, ckey) if(MC_TICK_CHECK) return -/datum/controller/subsystem/chat/stat_entry() - ..("C:[msg_queue.len]") +/datum/controller/subsystem/chat/proc/queue(queue_target, list/message_data) + var/list/targets = islist(queue_target) ? queue_target : list(queue_target) + for(var/target in targets) + var/client/client = CLIENT_FROM_VAR(target) + if(isnull(client)) + continue + LAZYADDASSOCLIST(client_to_payloads, client.ckey, generate_payload(client, message_data)) -/datum/controller/subsystem/chat/proc/queue(target, time, message, handle_whitespace = TRUE) - if(!target || !message) +/datum/controller/subsystem/chat/proc/send_immediate(send_target, list/message_data) + var/list/targets = islist(send_target) ? send_target : list(send_target) + for(var/target in targets) + var/client/client = CLIENT_FROM_VAR(target) + if(isnull(client)) + continue + send_payload_to_client(client, generate_payload(client, message_data)) + +/datum/controller/subsystem/chat/proc/handle_resend(client/client, sequence) + var/list/client_history = client_to_reliability_history[client.ckey] + sequence = "[sequence]" + if(isnull(client_history) || !(sequence in client_history)) return - if(!istext(message)) - stack_trace("to_chat called with invalid input type") - return + var/datum/chat_payload/payload = client_history[sequence] + if(payload.resends > CHAT_RELIABILITY_MAX_RESENDS) + return // we tried but byond said no - // Currently to_chat(world, ...) gets sent individually to each client. Consider. - if(target == world) - target = GLOB.clients - - //Some macros remain in the string even after parsing and fuck up the eventual output - var/original_message = message - message = replacetext(message, "\n", "
") - message = replacetext(message, "\improper", "") - message = replacetext(message, "\proper", "") - - if(isnull(time)) - time = world.time - - var/list/messageStruct = list("time" = time, "message" = message); - - if(islist(target)) - for(var/I in target) - var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible - - if(!C || !C.chatOutput) - continue // No client? No care. - else if(C.chatOutput.broken) - DIRECT_OUTPUT(C, original_message) - continue - else if(!C.chatOutput.loaded) - continue // If not loaded yet, do nothing and history-sending on load will get it. - - LAZYINITLIST(msg_queue[C]) - msg_queue[C][++msg_queue[C].len] = messageStruct - else - var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible - - if(!C || !C.chatOutput) - return // No client? No care. - else if(C.chatOutput.broken) - DIRECT_OUTPUT(C, original_message) - return - else if(!C.chatOutput.loaded) - return // If not loaded yet, do nothing and history-sending on load will get it. - - LAZYINITLIST(msg_queue[C]) - msg_queue[C][++msg_queue[C].len] = messageStruct + payload.resends += 1 + send_payload_to_client(client, client_history[sequence]) + /* + SSblackbox.record_feedback( + "nested tally", + "chat_resend_byond_version", + 1, + list( + "[client.byond_version]", + "[client.byond_build]", + ), + ) + */ diff --git a/code/controllers/subsystems/ping.dm b/code/controllers/subsystems/ping.dm new file mode 100644 index 0000000000..00e3effe02 --- /dev/null +++ b/code/controllers/subsystems/ping.dm @@ -0,0 +1,44 @@ +/*! + * Copyright (c) 2022 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +SUBSYSTEM_DEF(ping) + name = "Ping" + priority = FIRE_PRIORITY_PING + // init_stage = INITSTAGE_EARLY + wait = 4 SECONDS + flags = SS_NO_INIT + runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + var/list/currentrun = list() + +/datum/controller/subsystem/ping/stat_entry() + ..("P:[GLOB.clients.len]") + +/datum/controller/subsystem/ping/fire(resumed = FALSE) + // Prepare the new batch of clients + if (!resumed) + src.currentrun = GLOB.clients.Copy() + + // De-reference the list for sanic speeds + var/list/currentrun = src.currentrun + + while (currentrun.len) + var/client/client = currentrun[currentrun.len] + currentrun.len-- + + if(!client.is_preference_enabled(/datum/client_preference/vchat_enable)) + winset(client, "output", "on-show=&is-disabled=0&is-visible=1") + winset(client, "browseroutput", "is-disabled=1;is-visible=0") + client.tgui_panel.oldchat = TRUE + + if (client?.tgui_panel?.is_ready()) + // Send a soft ping + client.tgui_panel.window.send_message("ping/soft", list( + // Slightly less than the subsystem timer (somewhat arbitrary) + // to prevent incoming pings from resetting the afk state + "afk" = client.is_afk(3.5 SECONDS), + )) + + if (MC_TICK_CHECK) + return diff --git a/code/controllers/subsystems/tgui.dm b/code/controllers/subsystems/tgui.dm index 51459ccfc5..578e3c486a 100644 --- a/code/controllers/subsystems/tgui.dm +++ b/code/controllers/subsystems/tgui.dm @@ -2,6 +2,7 @@ * Copyright (c) 2020 Aleksej Komarov * SPDX-License-Identifier: MIT */ + /** * tgui subsystem * @@ -37,7 +38,7 @@ SUBSYSTEM_DEF(tgui) /datum/controller/subsystem/tgui/stat_entry() ..("P:[all_uis.len]") -/datum/controller/subsystem/tgui/fire(resumed = 0) +/datum/controller/subsystem/tgui/fire(resumed = FALSE) if(!resumed) src.current_run = all_uis.Copy() // Cache for sanic speed (lists are references anyways) @@ -46,8 +47,8 @@ SUBSYSTEM_DEF(tgui) var/datum/tgui/ui = current_run[current_run.len] current_run.len-- // TODO: Move user/src_object check to process() - if(ui && ui.user && ui.src_object) - ui.process() + if(ui?.user && ui.src_object) + ui.process(wait * 0.1) else ui.close(0) if(MC_TICK_CHECK) @@ -86,6 +87,8 @@ SUBSYSTEM_DEF(tgui) window_found = TRUE break if(!window_found) + log_tgui(user, "Error: Pool exhausted", + context = "SStgui/request_pooled_window") return null return window @@ -97,6 +100,7 @@ SUBSYSTEM_DEF(tgui) * required user mob */ /datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user) + log_tgui(user, context = "SStgui/force_close_all_windows") if(user.client) user.client.tgui_windows = list() for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT) @@ -112,6 +116,7 @@ SUBSYSTEM_DEF(tgui) * required window_id string */ /datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id) + log_tgui(user, context = "SStgui/force_close_window") // Close all tgui datums based on window_id. for(var/datum/tgui/ui in user.tgui_open_uis) if(ui.window && ui.window.id == window_id) @@ -121,22 +126,23 @@ SUBSYSTEM_DEF(tgui) // Close window directly just to be sure. user << browse(null, "window=[window_id]") - /** - * public - * - * Get a open UI given a user, src_object, and ui_key and try to update it with data. - * - * required user mob The mob who opened/is using the UI. - * required src_object datum The object/datum which owns the UI. - * required ui_key string The ui_key of the UI. - * - * return datum/tgui The found UI. - **/ +/** + * public + * + * Try to find an instance of a UI, and push an update to it. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object/datum which owns the UI. + * optional ui datum/tgui The UI to be updated, if it exists. + * optional force_open bool If the UI should be re-opened instead of updated. + * + * return datum/tgui The found UI. + */ /datum/controller/subsystem/tgui/proc/try_update_ui( mob/user, datum/src_object, datum/tgui/ui) - // Look up a UI if it wasn't passed. + // Look up a UI if it wasn't passed if(isnull(ui)) ui = get_open_ui(user, src_object) // Couldn't find a UI. @@ -152,17 +158,16 @@ SUBSYSTEM_DEF(tgui) ui.send_update() return ui - /** - * private - * - * Get a open UI given a user, src_object, and ui_key. - * - * required user mob The mob who opened/is using the UI. - * required src_object datum The object/datum which owns the UI. - * required ui_key string The ui_key of the UI. - * - * return datum/tgui The found UI. - **/ +/** + * public + * + * Get a open UI given a user and src_object. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object/datum which owns the UI. + * + * return datum/tgui The found UI. + */ /datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object) // No UIs opened for this src_object if(!LAZYLEN(src_object?.open_uis)) @@ -171,56 +176,57 @@ SUBSYSTEM_DEF(tgui) // Make sure we have the right user if(ui.user == user) return ui - return null // Couldn't find a UI! + return null - /** - * private - * - * Update all UIs attached to src_object. - * - * required src_object datum The object/datum which owns the UIs. - * - * return int The number of UIs updated. - **/ +/** + * public + * + * Update all UIs attached to src_object. + * + * required src_object datum The object/datum which owns the UIs. + * + * return int The number of UIs updated. + */ /datum/controller/subsystem/tgui/proc/update_uis(datum/src_object) // No UIs opened for this src_object if(!LAZYLEN(src_object?.open_uis)) return 0 var/count = 0 for(var/datum/tgui/ui in src_object.open_uis) - // Check the UI is valid. - if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) + // Check if UI is valid. + if(ui?.src_object && ui.user && ui.src_object.tgui_host(ui.user)) INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), wait * 0.1, TRUE) - count++ // Count each UI we update. + count++ return count - /** - * private - * - * Close all UIs attached to src_object. - * - * required src_object datum The object/datum which owns the UIs. - * - * return int The number of UIs closed. - **/ +/** + * public + * + * Close all UIs attached to src_object. + * + * required src_object datum The object/datum which owns the UIs. + * + * return int The number of UIs closed. + */ /datum/controller/subsystem/tgui/proc/close_uis(datum/src_object) // No UIs opened for this src_object if(!LAZYLEN(src_object?.open_uis)) return 0 var/count = 0 for(var/datum/tgui/ui in src_object.open_uis) - if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid. - ui.close() // Close the UI. - count++ // Count each UI we close. + // Check if UI is valid. + if(ui?.src_object && ui.user && ui.src_object.tgui_host(ui.user)) + ui.close() + count++ return count - /** - * private - * - * Close all UIs regardless of their attachment to src_object. - * - * return int The number of UIs closed. - **/ +/** + * public + * + * Close all UIs regardless of their attachment to src_object. + * + * return int The number of UIs closed. + */ /datum/controller/subsystem/tgui/proc/close_all_uis() var/count = 0 for(var/datum/tgui/ui in all_uis) @@ -230,67 +236,67 @@ SUBSYSTEM_DEF(tgui) count++ return count - /** - * private - * - * Update all UIs belonging to a user. - * - * required user mob The mob who opened/is using the UI. - * optional src_object datum If provided, only update UIs belonging this src_object. - * - * return int The number of UIs updated. - **/ +/** + * public + * + * Update all UIs belonging to a user. + * + * required user mob The mob who opened/is using the UI. + * optional src_object datum If provided, only update UIs belonging this src_object. + * + * return int The number of UIs updated. + */ /datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object) var/count = 0 if(length(user?.tgui_open_uis) == 0) return count for(var/datum/tgui/ui in user.tgui_open_uis) if(isnull(src_object) || ui.src_object == src_object) - ui.process(force = 1) + ui.process(wait * 0.1, force = 1) count++ return count - /** - * private - * - * Close all UIs belonging to a user. - * - * required user mob The mob who opened/is using the UI. - * optional src_object datum If provided, only close UIs belonging this src_object. - * - * return int The number of UIs closed. - **/ -/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object, logout = FALSE) +/** + * public + * + * Close all UIs belonging to a user. + * + * required user mob The mob who opened/is using the UI. + * optional src_object datum If provided, only close UIs belonging this src_object. + * + * return int The number of UIs closed. + */ +/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object) var/count = 0 if(length(user?.tgui_open_uis) == 0) return count for(var/datum/tgui/ui in user.tgui_open_uis) if(isnull(src_object) || ui.src_object == src_object) - ui.close(logout = logout) + ui.close() count++ return count - /** - * private - * - * Add a UI to the list of open UIs. - * - * required ui datum/tgui The UI to be added. - **/ +/** + * private + * + * Add a UI to the list of open UIs. + * + * required ui datum/tgui The UI to be added. + */ /datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui) ui.user?.tgui_open_uis |= ui LAZYOR(ui.src_object.open_uis, ui) all_uis |= ui - /** - * private - * - * Remove a UI from the list of open UIs. - * - * required ui datum/tgui The UI to be removed. - * - * return bool If the UI was removed or not. - **/ +/** + * private + * + * Remove a UI from the list of open UIs. + * + * required ui datum/tgui The UI to be removed. + * + * return bool If the UI was removed or not. + */ /datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui) // Remove it from the list of processing UIs. all_uis -= ui @@ -302,28 +308,28 @@ SUBSYSTEM_DEF(tgui) LAZYREMOVE(ui.src_object.open_uis, ui) return TRUE - /** - * private - * - * Handle client logout, by closing all their UIs. - * - * required user mob The mob which logged out. - * - * return int The number of UIs closed. - **/ +/** + * private + * + * Handle client logout, by closing all their UIs. + * + * required user mob The mob which logged out. + * + * return int The number of UIs closed. + */ /datum/controller/subsystem/tgui/proc/on_logout(mob/user) - return close_user_uis(user, logout = TRUE) + close_user_uis(user) - /** - * private - * - * Handle clients switching mobs, by transferring their UIs. - * - * required user source The client's original mob. - * required user target The client's new mob. - * - * return bool If the UIs were transferred. - **/ +/** + * private + * + * Handle clients switching mobs, by transferring their UIs. + * + * required user source The client's original mob. + * required user target The client's new mob. + * + * return bool If the UIs were transferred. + */ /datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target) // The old mob had no open UIs. if(length(source?.tgui_open_uis) == 0) diff --git a/code/datums/chat_payload.dm b/code/datums/chat_payload.dm new file mode 100644 index 0000000000..fd35bbc4ee --- /dev/null +++ b/code/datums/chat_payload.dm @@ -0,0 +1,16 @@ +/// Stores information about a chat payload +/datum/chat_payload + /// Sequence number of this payload + var/sequence = 0 + /// Message we are sending + var/list/content + /// Resend count + var/resends = 0 + +/// Converts the chat payload into a JSON string +/datum/chat_payload/proc/into_message() + return "{\"sequence\":[sequence],\"content\":[json_encode(content)]}" + +/// Returns an HTML-encoded message from our contents. +/datum/chat_payload/proc/get_content_as_html() + return message_to_html(content) diff --git a/code/datums/underwear/bottom.dm b/code/datums/underwear/bottom.dm index 358fe20104..d32d7952c1 100644 --- a/code/datums/underwear/bottom.dm +++ b/code/datums/underwear/bottom.dm @@ -95,4 +95,14 @@ /datum/category_item/underwear/bottom/onepiece name = "Swimming One Piece" icon_state = "onepiece" - has_color = TRUE \ No newline at end of file + has_color = TRUE + +/datum/category_item/underwear/top/onepiece_alt + name = "Swimming One Piece, Alt" + icon_state = "swim_onepiece" + has_color = TRUE + +/datum/category_item/underwear/top/onepiece_strapless + name = "Swimming One Piece, Strapless" + icon_state = "swim_strapless_onepiece" + has_color = TRUE diff --git a/code/datums/underwear/socks.dm b/code/datums/underwear/socks.dm index ac29b579d1..e06782b8d2 100644 --- a/code/datums/underwear/socks.dm +++ b/code/datums/underwear/socks.dm @@ -208,4 +208,8 @@ /datum/category_item/underwear/socks/stirrup_thigh_black name = "Black Stirrup Stockings" icon_state = "leggings-stir-black" - has_color = TRUE \ No newline at end of file + has_color = TRUE + +/datum/category_item/underwear/socks/stirrup_pantyhose + name = "Pantyhose, stirrup" + icon_state = "pantyhose-stir" diff --git a/code/datums/underwear/top.dm b/code/datums/underwear/top.dm index 5af7870f04..336bebd1cc 100644 --- a/code/datums/underwear/top.dm +++ b/code/datums/underwear/top.dm @@ -51,10 +51,20 @@ name = "Fishnet top" icon_state = "fishnet_body" +/datum/category_item/underwear/top/fishnet_base_alt + name = "Fishnet top, alt" + icon_state = "fishnet_body_alt" + has_color = TRUE + /datum/category_item/underwear/top/fishnet_sleeves name = "Fishnet with sleeves" icon_state = "fishnet_sleeves" +/datum/category_item/underwear/top/fishnet_sleeves_alt + name = "Fishnet with sleeves, alt" + icon_state = "fishnet_sleeves_alt" + has_color = TRUE + /datum/category_item/underwear/top/fishnet_gloves name = "Fishnet with gloves" icon_state = "fishnet_gloves" @@ -95,4 +105,4 @@ /datum/category_item/underwear/top/swimtop name = "Swimming Top" icon_state = "swimtop" - has_color = TRUE \ No newline at end of file + has_color = TRUE diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm index 2c32ad8e76..6611092b38 100644 --- a/code/datums/underwear/undershirts.dm +++ b/code/datums/underwear/undershirts.dm @@ -189,13 +189,38 @@ icon_state = "pinkblack_tshirt" /datum/category_item/underwear/undershirt/turtle + name = "Turtleneck, Old" + icon_state = "turtleneck_old" + has_color = TRUE + +/datum/category_item/underwear/undershirt/sleevelessturtle + name = "Turtleneck, Sleeveless, Old" + icon_state = "turtleneck_sleeveless_old" + has_color = TRUE + +/datum/category_item/underwear/undershirt/turtleneck name = "Turtleneck" icon_state = "turtleneck" has_color = TRUE -/datum/category_item/underwear/undershirt/sleevelessturtle +/datum/category_item/underwear/undershirt/turtleneck_smooth + name = "Turtleneck, Smooth" + icon_state = "turtleneck_smooth" + has_color = TRUE + +/datum/category_item/underwear/undershirt/turtlesleeveless name = "Turtleneck, Sleeveless" - icon_state = "sleevelessturtle" + icon_state = "turtleneck_sleeveless" + has_color = TRUE + +/datum/category_item/underwear/undershirt/leotardturtle + name = "Leotard Turtleneck" + icon_state = "leotard_turtleneck" + has_color = TRUE + +/datum/category_item/underwear/undershirt/leotardturtlesleeveless + name = "Leotard Turtleneck, Sleeveless" + icon_state = "leotard_turtleneck_sleeveless" has_color = TRUE /datum/category_item/underwear/undershirt/dress_shirt_fem @@ -226,4 +251,4 @@ /datum/category_item/underwear/undershirt/leotard name = "Leotard" icon_state = "leotard" - has_color = TRUE \ No newline at end of file + has_color = TRUE diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index f5ea5d0cbf..ad2e49e5c4 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -374,7 +374,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //17 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //18 @@ -656,7 +656,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //17 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //18 @@ -919,7 +919,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //12 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //13 @@ -1159,7 +1159,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //17 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //18 @@ -1417,7 +1417,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //11 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //12 @@ -1650,7 +1650,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //17 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //18 @@ -1937,7 +1937,7 @@ "backkey"=IS_SCREWDRIVER, "desc"="The wiring is adjusted"), //19 - list("key"=/obj/item/weapon/tool/wirecutters, + list("key"=IS_WIRECUTTER, "backkey"=IS_SCREWDRIVER, "desc"="The wiring is added"), //20 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 5c0e31a4c6..609822a756 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -226,6 +226,7 @@ /obj/item/attack_hand(mob/living/user as mob) if (!user) return + ..() if(anchored) to_chat(user, span("notice", "\The [src] won't budge, you can't pick it up!")) return @@ -1020,4 +1021,4 @@ Note: This proc can be overwritten to allow for different types of auto-alignmen return /obj/item/proc/get_welder() - return \ No newline at end of file + return diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm index 6e4379367f..42134cb638 100644 --- a/code/game/objects/items/weapons/gift_wrappaper.dm +++ b/code/game/objects/items/weapons/gift_wrappaper.dm @@ -132,13 +132,14 @@ to_chat(user, "You MUST put the paper on a table!") if (W.w_class < ITEMSIZE_LARGE) var/obj/item/I = user.get_inactive_hand() - if(I.has_tool_quality(TOOL_WIRECUTTER)) + if(I && I.has_tool_quality(TOOL_WIRECUTTER)) var/a_used = 2 ** (src.w_class - 1) if (src.amount < a_used) to_chat(user, "You need more paper!") return else if(istype(W, /obj/item/smallDelivery) || istype(W, /obj/item/weapon/gift)) //No gift wrapping gifts! + to_chat(user, "You can't wrap something that's already wrapped!") return src.amount -= a_used diff --git a/code/game/objects/items/weapons/tools/transforming.dm b/code/game/objects/items/weapons/tools/transforming.dm index 41cf89a9c3..9089a71423 100644 --- a/code/game/objects/items/weapons/tools/transforming.dm +++ b/code/game/objects/items/weapons/tools/transforming.dm @@ -55,6 +55,7 @@ desc = initial(desc) + " It's fitted with a prying head." icon_state = "jaws_pry" usesound = 'sound/items/jaws_pry.ogg' + pry = 1 tool_qualities = list(TOOL_CROWBAR) if(user) playsound(src, 'sound/items/change_jaws.ogg', 50, 1) @@ -63,6 +64,7 @@ desc = initial(desc) + " It's fitted with a cutting head." icon_state = "jaws_cutter" usesound = 'sound/items/jaws_cut.ogg' + pry = 0 tool_qualities = list(TOOL_WIRECUTTER) if(user) playsound(src, 'sound/items/change_jaws.ogg', 50, 1) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index e6ec740aa0..2260f42fb9 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -185,22 +185,22 @@ user.do_attack_animation(src) shatter() - else if (usr.a_intent == I_HURT) + else if (user.a_intent == I_HURT) - if (istype(usr,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = usr + if (istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) attack_generic(H,25) return playsound(src, 'sound/effects/glassknock.ogg', 80, 1) user.do_attack_animation(src) - usr.visible_message("\The [usr] bangs against \the [src]!", + user.visible_message("\The [user] bangs against \the [src]!", "You bang against \the [src]!", "You hear a banging sound.") else playsound(src, 'sound/effects/glassknock.ogg', 80, 1) - usr.visible_message("[usr.name] knocks on the [src.name].", + user.visible_message("[user.name] knocks on the [src.name].", "You knock on the [src.name].", "You hear a knocking sound.") return diff --git a/code/game/world.dm b/code/game/world.dm index a6cbb73385..9f08a33380 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -33,7 +33,6 @@ GLOB.timezoneOffset = get_timezone_offset() callHook("startup") - init_vchat() //Emergency Fix load_mods() //end-emergency fix @@ -507,7 +506,7 @@ var/world_topic_spam_protect_time = world.timeofday s += "[station_name()]"; s += " (" - s += "" //Change this to wherever you want the hub to link to. + s += "" //Change this to wherever you want the hub to link to. // s += "[game_version]" s += "Default" //Replace this with something else. Or ever better, delete it and uncomment the game version. s += "" diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 8fdc8edc13..b9ec670640 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -8,7 +8,10 @@ var/global/floorIsLava = 0 for(var/client/C in GLOB.admins) if((R_ADMIN|R_MOD) & C.holder.rights) - to_chat(C,msg) + to_chat(C, + type = MESSAGE_TYPE_ADMINLOG, + html = msg, + confidential = TRUE) /proc/msg_admin_attack(var/text) //Toggleable Attack Messages var/rendered = "ATTACK: [text]" @@ -16,7 +19,10 @@ var/global/floorIsLava = 0 if((R_ADMIN|R_MOD) & C.holder.rights) if(C.is_preference_enabled(/datum/client_preference/mod/show_attack_logs)) var/msg = rendered - to_chat(C,msg) + to_chat(C, + type = MESSAGE_TYPE_ATTACKLOG, + html = msg, + confidential = TRUE) /proc/admin_notice(var/message, var/rights) for(var/mob/M in mob_list) diff --git a/code/modules/admin/verbs/modify_robot.dm b/code/modules/admin/verbs/modify_robot.dm index 2562d891b3..9413353cf7 100644 --- a/code/modules/admin/verbs/modify_robot.dm +++ b/code/modules/admin/verbs/modify_robot.dm @@ -6,7 +6,7 @@ if(!check_rights(R_ADMIN)) return - if(!istype(target)) + if(!istype(target) || !target.module) return if(!target.module.modules) @@ -45,6 +45,7 @@ robot.module.contents.Remove(add_item) target.module.modules.Add(add_item) target.module.contents.Add(add_item) + target.hud_used.update_robot_modules_display() to_chat(usr, "You added \"[add_item]\" to [target].") if(istype(add_item, /obj/item/stack/)) var/obj/item/stack/item_with_synth = add_item @@ -94,6 +95,8 @@ if(!istype(selected_module_module, /obj/item/)) break to_chat(usr, "You removed \"[selected_module_module]\" from [target]") + target.uneq_all() + target.hud_used.update_robot_modules_display(TRUE) target.module.emag.Remove(selected_module_module) target.module.modules.Remove(selected_module_module) target.module.contents.Remove(selected_module_module) diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index b2be689721..ffac68a6f9 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -22,9 +22,9 @@ for(var/client/C in GLOB.admins) if(R_ADMIN|R_EVENT & C.holder.rights) if(C.is_preference_enabled(/datum/client_preference/admin/show_chat_prayers)) - to_chat(C,msg) + to_chat(C, msg, type = MESSAGE_TYPE_PRAYER, confidential = TRUE) C << 'sound/effects/ding.ogg' - to_chat(usr, "Your prayers have been received by the gods.") + to_chat(usr, "Your prayers have been received by the gods.", confidential = TRUE) feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! log_pray(raw_msg, src) diff --git a/code/modules/asset_cache/assets/chat.dm b/code/modules/asset_cache/assets/chat.dm new file mode 100644 index 0000000000..eba0e5418e --- /dev/null +++ b/code/modules/asset_cache/assets/chat.dm @@ -0,0 +1,2 @@ +/datum/asset/spritesheet/chat + name = "chat" diff --git a/code/modules/asset_cache/assets/tgui.dm b/code/modules/asset_cache/assets/tgui.dm index 6874c24eea..6446471a30 100644 --- a/code/modules/asset_cache/assets/tgui.dm +++ b/code/modules/asset_cache/assets/tgui.dm @@ -5,11 +5,9 @@ "tgui.bundle.css" = file("tgui/public/tgui.bundle.css"), ) -/* Comment will be removed in later part /datum/asset/simple/tgui_panel // keep_local_name = TRUE assets = list( "tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"), "tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"), ) -*/ diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index a68740e965..e3e23af110 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -41,8 +41,10 @@ var/datum/admins/deadmin_holder = null var/buildmode = 0 - var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming. - var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent. + ///Contains the last message sent by this client - used to protect against copy-paste spamming. + var/last_message = "" + ///contins a number of how many times a message identical to last_message was sent. + var/last_message_count = 0 var/ircreplyamount = 0 var/entity_narrate_holder //Holds /datum/entity_narrate when using the relevant admin verbs. @@ -56,9 +58,7 @@ var/area = null var/time_died_as_mouse = null //when the client last died as a mouse var/datum/tooltip/tooltips = null - var/datum/chatOutput/chatOutput var/datum/volume_panel/volume_panel = null // Initialized by /client/verb/volume_panel() - var/chatOutputLoadedAt var/seen_news = 0 var/adminhelped = 0 diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index ed652ad8ea..1efa62c77c 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -133,7 +133,6 @@ if("usr") hsrc = mob if("prefs") return prefs.process_link(usr,href_list) if("vars") return view_var_Topic(href,href_list,hsrc) - if("chat") return chatOutput.Topic(href, href_list) switch(href_list["action"]) if("openLink") @@ -168,15 +167,10 @@ return null if(!config.guests_allowed && IsGuestKey(key)) - alert(src,"This server doesn't allow guest accounts to play. Please go to http://www.byond.com/ and register for a key.","Guest") // Not tgui_alert + alert(src,"This server doesn't allow guest accounts to play. Please go to https://www.byond.com/ and register for a key.","Guest") // Not tgui_alert del(src) return - chatOutput = new /datum/chatOutput(src) //veechat - chatOutput.send_resources() - spawn() - chatOutput.start() - //Only show this if they are put into a new_player mob. Otherwise, "what title screen?" if(isnewplayer(src.mob)) to_chat(src, "If the title screen is black, resources are still downloading. Please be patient until the title screen appears.") @@ -184,6 +178,9 @@ GLOB.clients += src GLOB.directory[ckey] = src + // Instantiate tgui panel + tgui_panel = new(src, "browseroutput") + GLOB.ahelp_tickets.ClientLogin(src) GLOB.mhelp_tickets.ClientLogin(src) @@ -213,6 +210,9 @@ if(prefs) prefs.selecting_slots = FALSE + // Initialize tgui panel + tgui_panel.initialize() + connection_time = world.time connection_realtime = world.realtime connection_timeofday = world.timeofday @@ -484,34 +484,11 @@ return FALSE return ..() -/client/verb/reload_vchat() - set name = "Reload VChat" - set category = "OOC" - - //Timing - if(src.chatOutputLoadedAt > (world.time - 10 SECONDS)) - tgui_alert_async(src, "You can only try to reload VChat every 10 seconds at most.") - return - - verbs -= /client/proc/vchat_export_log - - //Log, disable - log_debug("[key_name(src)] reloaded VChat.") - winset(src, null, "outputwindow.htmloutput.is-visible=false;outputwindow.oldoutput.is-visible=false;outputwindow.chatloadlabel.is-visible=true") - - //The hard way - qdel_null(src.chatOutput) - chatOutput = new /datum/chatOutput(src) //veechat - chatOutput.send_resources() - spawn() - chatOutput.start() - - //This is for getipintel.net. //You're welcome to replace this proc with your own that does your own cool stuff. //Just set the client's ip_reputation var and make sure it makes sense with your config settings (higher numbers are worse results) /client/proc/update_ip_reputation() - var/request = "http://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]" + var/request = "https://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]" var/http[] = world.Export(request) /* Debug diff --git a/code/modules/client/client procs_vr.dm b/code/modules/client/client procs_vr.dm index 830521f20d..7cea3d5776 100644 --- a/code/modules/client/client procs_vr.dm +++ b/code/modules/client/client procs_vr.dm @@ -20,7 +20,7 @@ if(!config.ipr_email) return -1 - var/request = "http://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]" + var/request = "https://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]" var/http[] = world.Export(request) if(!http || !islist(http)) //If we couldn't check, the service might be down, fail-safe. @@ -74,7 +74,7 @@ if(!config.ipqualityscore_apikey) return -1 - var/request = "http://www.ipqualityscore.com/api/json/ip/[config.ipqualityscore_apikey]/[address]?strictness=1&fast=true&byond_key=[key]" + var/request = "https://www.ipqualityscore.com/api/json/ip/[config.ipqualityscore_apikey]/[address]?strictness=1&fast=true&byond_key=[key]" var/http[] = world.Export(request) if(!http || !islist(http)) //If we couldn't check, the service might be down, fail-safe. @@ -97,4 +97,4 @@ else score = response["fraud_score"] - return score/100 //To normalize with the 0.0 to 1.0 scores. \ No newline at end of file + return score/100 //To normalize with the 0.0 to 1.0 scores. diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm index af786e7d64..2e3e2ab7f4 100644 --- a/code/modules/client/preference_setup/general/04_equipment.dm +++ b/code/modules/client/preference_setup/general/04_equipment.dm @@ -22,6 +22,33 @@ S["communicator_visibility"] << pref.communicator_visibility S["ringtone"] << pref.ringtone +var/global/list/valid_ringtones = list( + "beep", + "boom", + "slip", + "honk", + "SKREE", + "xeno", + "spark", + "rad", + "servo", + "buh-boop", + "trombone", + "whistle", + "chirp", + "slurp", + "pwing", + "clack", + "bzzt", + "chimes", + "prbt", + "bark", + "bork", + "roark", + "chitter", + "squish" + ) + // Moved from /datum/preferences/proc/copy_to() /datum/category_item/player_setup_item/general/equipment/copy_to_mob(var/mob/living/carbon/human/character) character.all_underwear.Cut() @@ -151,8 +178,15 @@ pref.communicator_visibility = !pref.communicator_visibility return TOPIC_REFRESH else if(href_list["set_ringtone"]) - if(CanUseTopic(user)) - pref.ringtone = sanitize(input(user, "Please enter a new ringtone.", "Character Preference") as null|text, 20) - return TOPIC_REFRESH + var/choice = tgui_input_list(user, "Please select a ringtone. All of these choices come with an associated preset sound. Alternately, select \"Other\" to specify manually.", "Character Preference", valid_ringtones + "Other", pref.ringtone) + if(!choice || !CanUseTopic(user)) + return TOPIC_NOACTION + if(choice == "Other") + var/raw_choice = sanitize(tgui_input_text(user, "Please enter a custom ringtone. If this doesn't match any of the other listed choices, your PDA will use the default (\"beep\") sound.", "Character Preference", null, 20), 20) + if(raw_choice && CanUseTopic(user)) + pref.ringtone = raw_choice + else + pref.ringtone = choice + return TOPIC_REFRESH return ..() diff --git a/code/modules/client/preference_setup/global/setting_datums.dm b/code/modules/client/preference_setup/global/setting_datums.dm index 21f8037506..fd1ebc2ebc 100644 --- a/code/modules/client/preference_setup/global/setting_datums.dm +++ b/code/modules/client/preference_setup/global/setting_datums.dm @@ -289,7 +289,7 @@ var/list/_client_preferences_by_type key = "SOUND_INSTRUMENT" /datum/client_preference/vchat_enable - description = "Enable/Disable VChat" + description = "Enable/Disable TGChat" key = "VCHAT_ENABLE" enabled_description = "Enabled" disabled_description = "Disabled" diff --git a/code/modules/client/preference_setup/loadout/loadout_mask.dm b/code/modules/client/preference_setup/loadout/loadout_mask.dm index 3531cfff72..de4aad90d2 100644 --- a/code/modules/client/preference_setup/loadout/loadout_mask.dm +++ b/code/modules/client/preference_setup/loadout/loadout_mask.dm @@ -76,3 +76,7 @@ /datum/gear/mask/lace/New() gear_tweaks += gear_tweak_free_color_choice + +/datum/gear/mask/half + display_name = "black half-mask" + path = /obj/item/clothing/accessory/gaiter/half diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index e7ea6ce7e3..55f72d248d 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -497,6 +497,10 @@ ) gear_tweaks += new/datum/gear_tweak/path(cowboy_outfits) +/datum/gear/uniform/hightrousers + display_name = "high-waisted trousers" + path = /obj/item/clothing/under/dress/hightrousers + /* * 80s */ @@ -586,3 +590,16 @@ /datum/gear/uniform/fienddress display_name = "fiendish dress" path = /obj/item/clothing/under/fienddress + +//tabard dresses +/datum/gear/uniform/tabarddress + display_name = "tabard-dress selection" + path = /obj/item/clothing/under/dress/tabard + +/datum/gear/uniform/tabarddress/New() + ..() + var/list/tabarddress = list( + "white tabard-dress"=/obj/item/clothing/under/dress/tabard, + "black tabard-dress"=/obj/item/clothing/under/dress/tabard/black + ) + gear_tweaks += list(new/datum/gear_tweak/path(tabarddress)) diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm index e89d12f2cc..14b0775363 100644 --- a/code/modules/client/preference_setup/vore/07_traits.dm +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -5,7 +5,7 @@ #define ORGANICS 1 #define SYNTHETICS 2 -var/global/list/valid_bloodreagents = list("iron","copper","phoron","silver","gold","slimejelly") //allowlist-based so people don't make their blood restored by alcohol or something really silly. use reagent IDs! +var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","silver","gold","slimejelly") //allowlist-based so people don't make their blood restored by alcohol or something really silly. use reagent IDs! /datum/preferences var/custom_species // Custom species name, can't be changed due to it having been used in savefiles already. @@ -258,7 +258,8 @@ var/global/list/valid_bloodreagents = list("iron","copper","phoron","silver","go //Any additional non-trait settings can be applied here new_S.blood_color = pref.blood_color - new_S.blood_reagents = pref.blood_reagents + if(!(pref.blood_reagents == "default")) + new_S.blood_reagents = pref.blood_reagents if(pref.species == SPECIES_CUSTOM) //Statistics for this would be nice diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 4603e8840c..810dab44bf 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -48,7 +48,7 @@ var/list/preferences_datums = list() var/bday_announce = FALSE //Public announcement for birthdays var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2). var/b_type = "A+" //blood type (not-chooseable) - var/blood_reagents = "iron" //blood restoration reagents + var/blood_reagents = "default" //blood restoration reagents var/backbag = 2 //backpack type var/pdachoice = 1 //PDA type var/h_style = "Bald" //Hair type diff --git a/code/modules/client/preferences_toggle_procs.dm b/code/modules/client/preferences_toggle_procs.dm index 454a5ec6ac..8ce75698ba 100644 --- a/code/modules/client/preferences_toggle_procs.dm +++ b/code/modules/client/preferences_toggle_procs.dm @@ -367,17 +367,17 @@ feedback_add_details("admin_verb","THInstm") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/verb/toggle_vchat() - set name = "Toggle VChat" + set name = "Toggle TGChat" set category = "Preferences" - set desc = "Toggles VChat. Reloading VChat and/or reconnecting required to affect changes." + set desc = "Toggles TGChat. Reloading TGChat and/or reconnecting required to affect changes." var/pref_path = /datum/client_preference/vchat_enable toggle_preference(pref_path) SScharacter_setup.queue_preferences_save(prefs) - to_chat(src, "You have toggled VChat [is_preference_enabled(pref_path) ? "on" : "off"]. \ - You will have to reload VChat and/or reconnect to the server for these changes to take place. \ - VChat message persistence is not guaranteed if you change this again before the start of the next round.") + to_chat(src, "You have toggled TGChat [is_preference_enabled(pref_path) ? "on" : "off"]. \ + You will have to reload TGChat and/or reconnect to the server for these changes to take place. \ + TGChat message persistence is not guaranteed if you change this again before the start of the next round.") /client/verb/toggle_tgui_inputlock() set name = "Toggle TGUI Input Lock" diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index f40deb8f6b..759d17d892 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -341,7 +341,17 @@ "X" = image(icon = src.icon, icon_state = "xmask"), "Bugeyes" = image(icon = src.icon, icon_state = "bugmask"), "Double" = image(icon = src.icon, icon_state = "doublemask"), - "Mark" = image(icon = src.icon, icon_state = "markmask") + "Mark" = image(icon = src.icon, icon_state = "markmask"), + "Line" = image(icon = src.icon, icon_state = "linemask"), + "Minus" = image(icon = src.icon, icon_state = "minusmask"), + "Four" = image(icon = src.icon, icon_state = "fourmask"), + "Diamond" = image(icon = src.icon, icon_state = "diamondmask"), + "Cat" = image(icon = src.icon, icon_state = "catmask"), + "Big Eyes" = image(icon = src.icon, icon_state = "bigeyemask"), + "Good" = image(icon = src.icon, icon_state = "goodmask"), + "Bad" = image(icon = src.icon, icon_state = "badmask"), + "Happy" = image(icon = src.icon, icon_state = "happymask"), + "Sad" = image(icon = src.icon, icon_state = "sadmask") ) /obj/item/clothing/mask/paper/attack_self(mob/user) @@ -353,7 +363,11 @@ "Sleeping" ="sleepingmask", "Heart" = "heartmask", "Core" = "coremask", "Plus" = "plusmask", "Square" ="squaremask", "Bullseye" = "bullseyemask", "Vertical" = "verticalmask", "Horizontal" = "horizontalmask", "X" ="xmask", - "Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask") + "Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask", + "Line" = "linemask", "Minus" = "minusmask", "Four" = "fourmask", + "Diamond" = "diamondmask", "Cat" = "catmask", "Big Eyes" = "bigeyemask", + "Good" = "goodmask", "Bad" = "badmask", "Happy" = "happymask", "Sad" = "sadmask" + ) var/choice = show_radial_menu(user, src, papermask_designs, custom_check = FALSE, radius = 36, require_near = TRUE) @@ -405,4 +419,4 @@ desc = "100% synthetic \"Country Girls LLC.\" brand mouth wheat. Warning: not for actual consumption." icon_state = "mouthwheat" w_class = ITEMSIZE_SMALL - body_parts_covered = 0 \ No newline at end of file + body_parts_covered = 0 diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 0c70e7d5f5..8eefbcbcea 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -562,6 +562,10 @@ name = "white neck gaiter" icon_state = "gaiter_snow" +/obj/item/clothing/accessory/gaiter/half //functions like a gaiter + name = "black half-mask" + icon_state = "half_mask" + /* * Pride Pins */ diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index e378c8f195..e55c8587ba 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -614,6 +614,16 @@ desc = "Just looking at this makes you want to sing." icon_state = "ysing" +/obj/item/clothing/under/dress/tabard + name = "white tabard-dress" + desc = "A gold-trimmed white tabard-dress with a large V-shaped boob window. For when you want to show off your hips and look classy at the same time." + icon_state = "white_tabard" + +/obj/item/clothing/under/dress/tabard/black + name = "black tabard-dress" + desc = "A gold-trimmed black tabard-dress with a large circular boob window. For when you want to show off your hips and look classy at the same time." + icon_state = "black_tabard" + /* * Wedding Stuff */ diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index d168ddc1eb..18622cb4d8 100644 --- a/code/modules/clothing/under/shorts.dm +++ b/code/modules/clothing/under/shorts.dm @@ -75,6 +75,10 @@ name = "black jeans short shorts" icon_state = "black_shorts_f" +/obj/item/clothing/under/shorts/black/ripped + name = "black ripped shorts" + icon_state = "black_shorts_ripped" + /obj/item/clothing/under/shorts/jeans/grey name = "grey jeans shorts" icon_state = "greyshorts" diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm index 6b2998c2b3..b3bb6d1655 100644 --- a/code/modules/events/electrical_storm.dm +++ b/code/modules/events/electrical_storm.dm @@ -46,7 +46,7 @@ if(shield_gen.deal_shield_damage(30 * severity, SHIELD_DAMTYPE_EM) <= SHIELD_BREACHED_MINOR) return if(!valid_apcs.len) - log_debug("No valid APCs found for electrical storm event ship=[victim]!") + // log_debug("No valid APCs found for electrical storm event ship=[victim]!") // Let's not spam poor people with debug logs on (me) return var/list/picked_apcs = list() for(var/i=0, i< severity * 2, i++) // up to 2/4/6 APCs per tick depending on severity diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index a8668e561a..b084efe773 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -34,6 +34,8 @@ SSradiation.z_radiate(locate(1, 1, z), radiation_level, 1) for(var/mob/living/carbon/C in living_mob_list) + if(!(C.z in using_map.station_levels) || C.isSynthetic() || isbelly(C.loc)) + continue var/area/A = get_area(C) if(!A) continue @@ -41,7 +43,9 @@ continue if(istype(C,/mob/living/carbon/human)) var/mob/living/carbon/human/H = C - if(prob(5)) + var/chance = 5.0 + chance -= (chance / 100) * C.getarmor(null, "rad") + if(prob(chance)) if (prob(75)) randmutb(H) // Applies bad mutation domutcheck(H,null,MUTCHK_FORCED) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 4918df39f0..9ee08bf8a7 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -276,8 +276,8 @@ default behaviour is: is_shifted = FALSE pixel_x = default_pixel_x pixel_y = default_pixel_y - layer = MOB_LAYER - plane = MOB_PLANE + layer = initial(layer) + plane = initial(plane) // End VOREstation edit if(pulling) // we were pulling a thing and didn't lose it during our move. diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm index 48d5b89cee..978f8744c8 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm @@ -1,4 +1,4 @@ -/obj/item/weapon/dogborg/jaws/big +/obj/item/weapon/melee/dogborg/jaws/big name = "combat jaws" icon = 'icons/mob/dogborg_vr.dmi' icon_state = "jaws" @@ -9,7 +9,7 @@ attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") w_class = ITEMSIZE_NORMAL -/obj/item/weapon/dogborg/jaws/small +/obj/item/weapon/melee/dogborg/jaws/small name = "puppy jaws" icon = 'icons/mob/dogborg_vr.dmi' icon_state = "smalljaws" @@ -21,7 +21,7 @@ w_class = ITEMSIZE_NORMAL var/emagged = 0 -/obj/item/weapon/dogborg/jaws/small/attack_self(mob/user) +/obj/item/weapon/melee/dogborg/jaws/small/attack_self(mob/user) var/mob/living/silicon/robot/R = user if(R.emagged || R.emag_items) emagged = !emagged @@ -48,7 +48,7 @@ update_icon() // Baton chompers -/obj/item/weapon/borg_combat_shocker +/obj/item/weapon/melee/borg_combat_shocker name = "combat shocker" icon = 'icons/mob/dogborg_vr.dmi' icon_state = "combatshocker" @@ -61,7 +61,7 @@ var/charge_cost = 15 var/dogborg = FALSE -/obj/item/weapon/borg_combat_shocker/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone) +/obj/item/weapon/melee/borg_combat_shocker/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone) if(isrobot(target)) return ..() @@ -237,6 +237,7 @@ icon_state = "synthtongue" hitsound = 'sound/effects/attackblob.ogg' var/emagged = 0 + var/busy = 0 //prevents abuse and runtimes /obj/item/device/robot_tongue/New() ..() @@ -263,21 +264,27 @@ return user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(busy) + to_chat(user, "You are already licking something else.") + return if(user.client && (target in user.client.screen)) to_chat(user, "You need to take \the [target.name] off before cleaning it!") return else if(istype(target,/obj/item)) if(istype(target,/obj/item/trash)) user.visible_message("[user] nibbles away at \the [target.name].", "You begin to nibble away at \the [target.name]...") + busy = 1 if(do_after (user, 50)) user.visible_message("[user] finishes eating \the [target.name].", "You finish eating \the [target.name].") to_chat(user, "You finish off \the [target.name].") qdel(target) var/mob/living/silicon/robot/R = user R.cell.charge += 250 + busy = 0 return if(istype(target,/obj/item/weapon/cell)) user.visible_message("[user] begins cramming \the [target.name] down its throat.", "You begin cramming \the [target.name] down your throat...") + busy = 1 if(do_after (user, 50)) user.visible_message("[user] finishes gulping down \the [target.name].", "You finish swallowing \the [target.name].") to_chat(user, "You finish off \the [target.name], and gain some charge!") @@ -285,6 +292,7 @@ var/obj/item/weapon/cell/C = target R.cell.charge += C.charge / 3 qdel(target) + busy = 0 return else if(ishuman(target)) if(src.emagged) @@ -340,12 +348,13 @@ recharge_time = 10 //Takes ten ticks to recharge a shot, so don't waste them all! //cell_type = null //Same cell as a taser until edits are made. -/obj/item/weapon/combat_borgblade +/obj/item/weapon/melee/combat_borgblade name = "energy blade" icon = 'icons/mob/dogborg_vr.dmi' icon_state = "swordtail" desc = "A glowing dagger. It appears to be extremely sharp." - force = 20 //Takes 5 hits to 100-0 + force = 35 //Takes 3 hits to 100-0 + armor_penetration = 70 sharp = TRUE edge = TRUE throwforce = 0 //This shouldn't be thrown in the first place. @@ -466,4 +475,4 @@ var/armor_soak = get_armor_soak(T, "melee") T.apply_damage(20, HALLOSS,, armor_block, armor_soak) if(prob(75)) //75% chance to stun for 5 seconds, really only going to be 4 bcus click cooldown+animation. - T.apply_effect(5, WEAKEN, armor_block) \ No newline at end of file + T.apply_effect(5, WEAKEN, armor_block) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 438bc52a27..8c235d87ab 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -341,6 +341,7 @@ hands.icon_state = get_hud_module_icon() feedback_inc("cyborg_[lowertext(modtype)]",1) updatename() + hud_used.update_robot_modules_display() notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name) /mob/living/silicon/robot/proc/update_braintype() @@ -767,6 +768,7 @@ to_chat(usr, "You apply the upgrade to [src]!") usr.drop_item() U.loc = src + hud_used.update_robot_modules_display() else to_chat(usr, "Upgrade error!") @@ -804,12 +806,13 @@ /mob/living/silicon/robot/proc/module_reset() transform_with_anim() //VOREStation edit: sprite animation uneq_all() + hud_used.update_robot_modules_display(TRUE) modtype = initial(modtype) hands.icon_state = get_hud_module_icon() notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, module.name) module.Reset(src) - qdel(module) + module.Destroy() module = null updatename("Default") @@ -1374,6 +1377,7 @@ laws.show_laws(src) to_chat(src, "ALERT: [user.real_name] is your new master. Obey your new laws and [TU.his] commands.") update_icon() + hud_used.update_robot_modules_display() else to_chat(user, "You fail to hack [src]'s interface.") to_chat(src, "Hack attempt detected.") diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index 62a965d089..2622ff4ae3 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -760,10 +760,10 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/gun/energy/laser/mounted(src) src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg/ertgun(src) src.modules += new /obj/item/weapon/pickaxe/plasmacutter/borg(src) - src.modules += new /obj/item/weapon/combat_borgblade(src) + src.modules += new /obj/item/weapon/melee/combat_borgblade(src) src.modules += new /obj/item/borg/combat/shield(src) src.modules += new /obj/item/borg/combat/mobility(src) - src.modules += new /obj/item/weapon/borg_combat_shocker(src) + src.modules += new /obj/item/weapon/melee/borg_combat_shocker(src) src.modules += new /obj/item/device/ticket_printer(src) src.emag += new /obj/item/weapon/gun/energy/lasercannon/mounted(src) diff --git a/code/modules/mob/living/silicon/robot/sprites/combat.dm b/code/modules/mob/living/silicon/robot/sprites/combat.dm index 32c8b09fcc..a451a70e79 100644 --- a/code/modules/mob/living/silicon/robot/sprites/combat.dm +++ b/code/modules/mob/living/silicon/robot/sprites/combat.dm @@ -101,11 +101,11 @@ ..() - var/obj/item/weapon/combat_borgblade/CBB = locate() in module.modules + var/obj/item/weapon/melee/combat_borgblade/CBB = locate() in module.modules if(CBB) CBB.name = "sword tail" CBB.desc = "A glowing dagger normally attached to the end of a cyborg's tail. It appears to be extremely sharp." - var/obj/item/weapon/borg_combat_shocker/BCS = locate() in module.modules + var/obj/item/weapon/melee/borg_combat_shocker/BCS = locate() in module.modules if(BCS) BCS.name = "combat jaws" BCS.desc = "Shockingly chompy!" @@ -132,4 +132,4 @@ sprite_hud_icon_state = "ert" rest_sprite_options = list("Default") has_eye_sprites = FALSE - has_eye_light_sprites = TRUE \ No newline at end of file + has_eye_light_sprites = TRUE diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm index a7a9d45db7..4ac26e4e13 100644 --- a/code/modules/mob/mob_grab_specials.dm +++ b/code/modules/mob/mob_grab_specials.dm @@ -1,4 +1,3 @@ - /obj/item/weapon/grab/proc/inspect_organ(mob/living/carbon/human/H, mob/user, var/target_zone) var/obj/item/organ/external/E = H.get_organ(target_zone) @@ -163,12 +162,12 @@ if(can_eat) var/mob/living/carbon/attacker = user - user.visible_message("[user] is attempting to devour [target]!") + user.visible_message("[user] is attempting to devour [target]!") if(can_eat == 2) if(!do_mob(user, target)||!do_after(user, 30)) return else if(!do_mob(user, target)||!do_after(user, 70)) return - user.visible_message("[user] devours [target]!") + user.visible_message("[user] devours [target]!") target.loc = user attacker.stomach_contents.Add(target) - qdel(src) \ No newline at end of file + qdel(src) diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index 1fe31e965d..d2be34e921 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -86,7 +86,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image tgui_alert_async(src, message, "BYOND Client Version Warning") // So we can be more wordy and give links. - to_chat(src, "Your client version has known issues. Please consider using a different version: http://www.byond.com/download/build/.") + to_chat(src, "Your client version has known issues. Please consider using a different version: https://www.byond.com/download/build/.") var/chat_message = "" if(config.suggested_byond_version) chat_message += "We suggest using version [config.suggested_byond_version]." diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index feef4aef9b..fdae1d2f36 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -234,6 +234,48 @@ species_allowed = list(SPECIES_HUMAN,SPECIES_PROMETHEAN,SPECIES_HUMAN_VATBORN,SPECIES_UNATHI) flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/bobcutovereye + name = "Bobcut Over Eye" + icon_state = "hair_bobcutovereye1" + +/datum/sprite_accessory/hair/bobcutovereye2 + name = "Bobcut Over Eye 2" + icon_state = "hair_bobcutovereye2" + +/datum/sprite_accessory/hair/bobcutovereye3 + name = "Bobcut Over Eye 3" + icon_state = "hair_bobcutovereye3" + +/datum/sprite_accessory/hair/bonnie + name = "Bonnie" + icon_state = "hair_bonnie" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/bonniealt + name = "Bonnie Alt" + icon_state = "hair_bonniealt" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/bonnielong + name = "Bonnie, Long" + icon_state = "hair_bonnie_long" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/bonniealtlong + name = "Bonnie Alt, Long" + icon_state = "hair_bonniealt_long" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/bonnieshort + name = "Bonnie, Short" + icon_state = "hair_bonnie_short" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/bonniealtshort + name = "Bonnie Alt, Short" + icon_state = "hair_bonniealt_short" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/bowl name = "Bowl" icon_state = "hair_bowlcut" @@ -407,6 +449,10 @@ name = "Dave" icon_state = "hair_dave" +/datum/sprite_accessory/hair/dawn + name = "Dawn" + icon_state = "hair_dawn" + /datum/sprite_accessory/hair/devillock name = "Devil Lock" icon_state = "hair_devilock" @@ -444,6 +490,10 @@ icon_state = "hair_drillruru" flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/eagle + name = "Eagle" + icon_state = "hair_eagle" + /datum/sprite_accessory/hair/elize name = "Elize" icon_state = "hair_elize" @@ -513,6 +563,11 @@ gender = MALE flags = HAIR_VERY_SHORT +/datum/sprite_accessory/hair/falcon + name = "Falcon" + icon_state = "hair_falcon" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/familyman name = "Family Man" icon_state = "hair_thefamilyman" @@ -555,6 +610,15 @@ name = "Flow Hair" icon_state = "hair_f" +/datum/sprite_accessory/hair/fluffy + name = "Fluffy" + icon_state = "hair_fluffy" + +/datum/sprite_accessory/hair/fluffylong + name = "Fluffy, Long" + icon_state = "hair_fluffy_long" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/longfringe name = "Fringe Long" icon_state = "hair_longfringe" @@ -636,6 +700,16 @@ name = "Hitop" icon_state = "hair_hitop" +/datum/sprite_accessory/hair/hummingbird + name = "Hummingbird" + icon_state = "hair_hummingbird" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/inari + name = "Inari" + icon_state = "hair_inari" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/jade name = "Jade" icon_state = "hair_jade" @@ -716,6 +790,16 @@ icon_state = "hair_hbraid" flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/macaw + name = "Macaw" + icon_state = "hair_macaw" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/magpie + name = "Magpie" + icon_state = "hair_magpie" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/manbun name = "Manbun" icon_state = "hair_manbun" @@ -816,6 +900,21 @@ name = "Overeye Very Short" icon_state = "hair_veryshortovereye" +/datum/sprite_accessory/hair/overear + name = "Over Ear, Right" + icon_state = "hair_overear1" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/overear2 + name = "Over Ear, Left" + icon_state = "hair_overear2" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/owl + name = "Owl" + icon_state = "hair_owl" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/parted name = "Parted" icon_state = "hair_parted" @@ -879,6 +978,16 @@ icon_state = "hair_spikyponytail" flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/thinponytail + name = "Ponytail Thin" + icon_state = "hair_thinponytail" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/thinponytaillong + name = "Ponytail Thin, Long" + icon_state = "hair_thinponytail_long" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/poofy name = "Poofy" icon_state = "hair_poofy" @@ -889,6 +998,11 @@ icon_state = "hair_poofy2" flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/princess + name = "Princess" + icon_state = "hair_princess" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/proper name = "Proper" icon_state = "hair_proper" @@ -1065,6 +1179,16 @@ icon_state = "hair_spikey" species_allowed = list(SPECIES_HUMAN,SPECIES_PROMETHEAN,SPECIES_HUMAN_VATBORN,SPECIES_UNATHI) +/datum/sprite_accessory/hair/starling + name = "Starling" + icon_state = "hair_starling" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/stork + name = "Stork" + icon_state = "hair_stork" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/straightlong name = "Straight Long" icon_state = "hair_straightlong" @@ -1087,6 +1211,11 @@ icon_state = "hair_sweptfringe" flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/taro + name = "Taro" + icon_state = "hair_taro" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/terezi name = "Terezi" icon_state = "hair_terezi" @@ -1135,6 +1264,21 @@ icon_state = "hair_twintail" flags = HAIR_TIEABLE +/datum/sprite_accessory/hair/twintails + name = "Twintails" + icon_state = "hair_twintails" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/twintailslong + name = "Twintails, Long" + icon_state = "hair_twintails_long" + flags = HAIR_TIEABLE + +/datum/sprite_accessory/hair/twintailsshort + name = "Twintails, Short" + icon_state = "hair_twintails_short" + flags = HAIR_TIEABLE + /datum/sprite_accessory/hair/twinbob name = "Twinbun Bob" icon_state = "hair_bunbob" diff --git a/code/modules/mob/new_player/sprite_accessories_tail.dm b/code/modules/mob/new_player/sprite_accessories_tail.dm index 1821ffe6aa..a4f1e457f5 100644 --- a/code/modules/mob/new_player/sprite_accessories_tail.dm +++ b/code/modules/mob/new_player/sprite_accessories_tail.dm @@ -380,6 +380,54 @@ do_colouration = 1 color_blend_mode = ICON_MULTIPLY +/datum/sprite_accessory/tail/bigsnaketail + name = "large snake tail (vwag)" + desc = "" + icon_state = "bigsnaketail" + do_colouration = TRUE + color_blend_mode = ICON_MULTIPLY + ani_state = "bigsnaketail_w" + +/datum/sprite_accessory/tail/bigsnaketailstripes + name = "large snake tail, striped (vwag)" + desc = "" + icon_state = "bigsnaketailstripes" + extra_overlay = "bigsnaketailstripes-tips" + do_colouration = TRUE + color_blend_mode = ICON_MULTIPLY + ani_state = "bigsnaketailstripes_w" + extra_overlay_w = "bigsnaketailstripes-tips_w" + +/datum/sprite_accessory/tail/bigsnaketailstripes_alt + name = "large snake tail, striped, alt (vwag)" + desc = "" + icon_state = "bigsnaketailstripesalt" + extra_overlay = "bigsnaketailstripesalt-tips" + do_colouration = TRUE + color_blend_mode = ICON_MULTIPLY + ani_state = "bigsnaketailstripesalt_w" + extra_overlay_w = "bigsnaketailstripesalt-tips_w" + +/datum/sprite_accessory/tail/bigsnaketaildual + name = "large snake tail, dual color (vwag)" + desc = "" + icon_state = "bigsnaketaildual" + extra_overlay = "bigsnaketaildual-tips" + do_colouration = TRUE + color_blend_mode = ICON_MULTIPLY + ani_state = "bigsnaketaildual_w" + extra_overlay_w = "bigsnaketaildual-tips_w" + +/datum/sprite_accessory/tail/bigsnaketailunder + name = "large snake tail, under (vwag)" + desc = "" + icon_state = "bigsnaketailunder" + extra_overlay = "bigsnaketailunder-tips" + do_colouration = TRUE + color_blend_mode = ICON_MULTIPLY + ani_state = "bigsnaketailunder_w" + extra_overlay_w = "bigsnaketailunder-tips_w" + /datum/sprite_accessory/tail/vulpan_alt name = "vulpkanin alt style, colorable" desc = "" @@ -1009,4 +1057,4 @@ extra_overlay = "zorgoia_fluff" extra_overlay2 = "zorgoia_fluff_top" do_colouration = 1 - color_blend_mode = ICON_MULTIPLY \ No newline at end of file + color_blend_mode = ICON_MULTIPLY diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm index e6223a85a7..20172ac924 100644 --- a/code/modules/nifsoft/software/13_soulcatcher.dm +++ b/code/modules/nifsoft/software/13_soulcatcher.dm @@ -72,11 +72,15 @@ /datum/nifsoft/soulcatcher/proc/notify_into(var/message) var/sound = nif.good_sound - to_chat(nif.human,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"") + to_chat(nif.human, + type = MESSAGE_TYPE_NIF, + html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"") nif.human << sound for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs) - to_chat(CS,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"") + to_chat(CS, + type = MESSAGE_TYPE_NIF, + html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"") CS << sound /datum/nifsoft/soulcatcher/proc/say_into(var/message, var/mob/living/sender, var/mob/eyeobj) @@ -88,9 +92,13 @@ //Not AR Projecting else - to_chat(nif.human,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"") + to_chat(nif.human, + type = MESSAGE_TYPE_NIF, + html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"") for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs) - to_chat(CS,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"") + to_chat(CS, + type = MESSAGE_TYPE_NIF, + html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"") log_nsay(message,nif.human.real_name,sender) @@ -103,9 +111,13 @@ //Not AR Projecting else - to_chat(nif.human,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]") + to_chat(nif.human, + type = MESSAGE_TYPE_NIF, + html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]") for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs) - to_chat(CS,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]") + to_chat(CS, + type = MESSAGE_TYPE_NIF, + html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]") log_nme(message,nif.human.real_name,sender) diff --git a/code/modules/tgchat/README.md b/code/modules/tgchat/README.md new file mode 100644 index 0000000000..71acb47c45 --- /dev/null +++ b/code/modules/tgchat/README.md @@ -0,0 +1,30 @@ +## /TG/ Chat + +/TG/ Chat, which will be referred to as TgChat from this point onwards, is a system in which we can send messages to clients in a controlled and semi-reliable manner. The standard way of sending messages to BYOND clients simply dumps whatever you output to them directly into their chat window, however BYOND allows us to load our own code on the client to change this behaviour in a way that allows us to do some pretty neat things. + +### Message Format + +TgChat handles sending messages from the server to the client through the use of JSON payloads, of which the format will change depending on the type of message and the intended client endpoint. An example of the payload for chat messages is as follows: +```json +{ + "sequence": 0, + "content": { + "type": ". . .", // ?optional + "text": ". . .", // ?optional !atleast-one + "html": ". . .", // ?optional !atleast-one + "avoidHighlighting": 0 // ?optional + }, +} +``` + +### Reliability + +In the past there have been issues where BYOND will silently and without reason lose a message we sent to the client, to detect this and recover from it seamlessly TgChat also has a baked in reliability layer. This reliability layer is very primitive, and simply keeps track of received sequence numbers. Should the client receive an unexpected sequence number TgChat asks the server to resend any missing packets. + +### Ping System + +TgChat supports a round trip time ping measurement, which is displayed to the client so they can know how long it takes for their commands and inputs to reach the server. This is done by sending the client a ping request, `ping/soft`, which tells the client to send a ping to the server. When the server receives said ping it sends a reply, `ping/reply`, to the client with a payload containing the current DateTime which the client can reference against the initial ping request. + +### Chat Tabs, Local Storage, and Highlighting + +To make organizing and managing chat easier and more functional for both players and admins, TgChat has the ability to filter out messages based on their primary tag, such as individual departmental radios, to a dedicated chat tab for easier reading and comprehension. These tabs can also be configured to highlist messages based on a simple keyword search. You can set a multitude of different keywords to search for and they will be highlighting for instant alerting of the client. Said tabs, highlighting rules, and your chat history will persist thanks to use of local storage on the client. Using local storage TgChat can ensure that your preferences are saved and maintained between client restarts and switching between other /TG/ servers. Local Storage is also used to keep your chat history aswell, should you need to scroll through your chat logs. diff --git a/code/modules/tgchat/_legacy.dm b/code/modules/tgchat/_legacy.dm new file mode 100644 index 0000000000..fe01936540 --- /dev/null +++ b/code/modules/tgchat/_legacy.dm @@ -0,0 +1,48 @@ +/// Old VChat Code Stuff + +/* Old bicon code +/proc/expire_bicon_cache(key) + if(GLOB.bicon_cache[key]) + GLOB.bicon_cache -= key + return TRUE + return FALSE + +GLOBAL_LIST_EMPTY(bicon_cache) // Cache of the tag results, not the icons +*/ + +/proc/bicon(var/obj, var/use_class = 1, var/custom_classes = "") + return icon2base64html(obj, custom_classes) + + /* Old bicon code + var/class = use_class ? "class='icon misc [custom_classes]'" : null + if(!obj) + return + + // Try to avoid passing bicon an /icon directly. It is better to pass it an atom so it can cache. + if(isicon(obj)) // Passed an icon directly, nothing to cache-key on, as icon refs get reused *often* + return "" + + // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with. + var/atom/A = obj + var/key + var/changes_often = ishuman(A) || isobserver(A) // If this ends up with more, move it into a proc or var on atom. + + if(changes_often) + key = "\ref[A]" + else + key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]" + + var/base64 = GLOB.bicon_cache[key] + // Non-human atom, no cache + if(!base64) // Doesn't exist, make it. + base64 = icon2base64(A.examine_icon(), key) + GLOB.bicon_cache[key] = base64 + if(changes_often) + addtimer(CALLBACK(GLOBAL_PROC, .proc/expire_bicon_cache, key), 50 SECONDS, TIMER_UNIQUE) + + // May add a class to the img tag created by bicon + if(use_class) + class = "class='icon [A.icon_state] [custom_classes]'" + + return "" + */ diff --git a/code/modules/tgchat/message.dm b/code/modules/tgchat/message.dm new file mode 100644 index 0000000000..69d3a6faf5 --- /dev/null +++ b/code/modules/tgchat/message.dm @@ -0,0 +1,17 @@ +/** + * Message-related procs + * + * Message format (/list): + * - type - Message type, must be one of defines in `code/__DEFINES/chat.dm` + * - text - Plain message text + * - html - HTML message text + * - Optional metadata, can be any key/value pair. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/proc/message_to_html(message) + // Here it is possible to add a switch statement + // to custom-handle various message types. + return message["html"] || message["text"] diff --git a/code/modules/tgchat/to_chat.dm b/code/modules/tgchat/to_chat.dm new file mode 100644 index 0000000000..ae434b36f1 --- /dev/null +++ b/code/modules/tgchat/to_chat.dm @@ -0,0 +1,85 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * Circumvents the message queue and sends the message + * to the recipient (target) as soon as possible. + */ +/proc/to_chat_immediate( + target, + html, + type = null, + text = null, + avoid_highlighting = FALSE, + // FIXME: These flags are now pointless and have no effect + handle_whitespace = TRUE, + trailing_newline = TRUE, + confidential = FALSE +) + // Useful where the integer 0 is the entire message. Use case is enabling to_chat(target, some_boolean) while preventing to_chat(target, "") + html = "[html]" + text = "[text]" + + if(!target) + return + if(!html && !text) + CRASH("Empty or null string in to_chat proc call.") + if(target == world) + target = GLOB.clients + + // Build a message + var/message = list() + if(type) message["type"] = type + if(text) message["text"] = text + if(html) message["html"] = html + if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting + + // send it immediately + SSchat.send_immediate(target, message) + +/** + * Sends the message to the recipient (target). + * + * Recommended way to write to_chat calls: + * ``` + * to_chat(client, + * type = MESSAGE_TYPE_INFO, + * html = "You have found [object]") + * ``` + */ +/proc/to_chat( + target, + html, + type = null, + text = null, + avoid_highlighting = FALSE, + // FIXME: These flags are now pointless and have no effect + handle_whitespace = TRUE, + trailing_newline = TRUE, + confidential = FALSE +) + //if(isnull(Master) || !SSchat?.initialized || !MC_RUNNING(SSchat.init_stage)) + if(isnull(Master) || !SSchat?.subsystem_initialized) + to_chat_immediate(target, html, type, text, avoid_highlighting) + return + + // Useful where the integer 0 is the entire message. Use case is enabling to_chat(target, some_boolean) while preventing to_chat(target, "") + html = "[html]" + text = "[text]" + + if(!target) + return + if(!html && !text) + CRASH("Empty or null string in to_chat proc call.") + if(target == world) + target = GLOB.clients + + // Build a message + var/message = list() + if(type) message["type"] = type + if(text) message["text"] = text + if(html) message["html"] = html + if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting + SSchat.queue(target, message) diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm index 180e18a518..73dfdf2803 100644 --- a/code/modules/tgui/tgui_window.dm +++ b/code/modules/tgui/tgui_window.dm @@ -380,6 +380,8 @@ // Resend the assets for(var/asset in sent_assets) send_asset(asset) + if("chat/resend") + SSchat.handle_resend(client, payload) /datum/tgui_window/vv_edit_var(var_name, var_value) return var_name != NAMEOF(src, id) && ..() diff --git a/code/modules/tgui_panel/audio.dm b/code/modules/tgui_panel/audio.dm new file mode 100644 index 0000000000..32ecd93ab8 --- /dev/null +++ b/code/modules/tgui_panel/audio.dm @@ -0,0 +1,42 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/// Admin music volume, from 0 to 1. +/client/var/admin_music_volume = 1 + +/** + * public + * + * Sends music data to the browser. + * + * Optional settings: + * - pitch: the playback rate + * - start: the start time of the sound + * - end: when the musics stops playing + * + * required url string Must be an https URL. + * optional extra_data list Optional settings. + */ +/datum/tgui_panel/proc/play_music(url, extra_data) + if(!is_ready()) + return + if(!findtext(url, GLOB.is_http_protocol)) + return + var/list/payload = list() + if(length(extra_data) > 0) + for(var/key in extra_data) + payload[key] = extra_data[key] + payload["url"] = url + window.send_message("audio/playMusic", payload) + +/** + * public + * + * Stops playing music through the browser. + */ +/datum/tgui_panel/proc/stop_music() + if(!is_ready()) + return + window.send_message("audio/stopMusic") diff --git a/code/modules/tgui_panel/external.dm b/code/modules/tgui_panel/external.dm new file mode 100644 index 0000000000..a4ce4444ca --- /dev/null +++ b/code/modules/tgui_panel/external.dm @@ -0,0 +1,45 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/client/var/datum/tgui_panel/tgui_panel + +/** + * tgui panel / chat troubleshooting verb + */ +/client/verb/fix_tgui_panel() + set name = "Fix chat" + set category = "OOC" + var/action + log_tgui(src, "Started fixing.", context = "verb/fix_tgui_panel") + + nuke_chat() + + // Failed to fix, using tgalert as fallback + action = tgalert(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") + tgui_panel = new(src) + tgui_panel.initialize(force = TRUE) + // 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") + +/client/verb/refresh_tgui() + set name = "Refresh TGUI" + set category = "OOC" + + for(var/window_id in tgui_windows) + var/datum/tgui_window/window = tgui_windows[window_id] + window.reinitialize() diff --git a/code/modules/tgui_panel/telemetry.dm b/code/modules/tgui_panel/telemetry.dm new file mode 100644 index 0000000000..4dabcbb01a --- /dev/null +++ b/code/modules/tgui_panel/telemetry.dm @@ -0,0 +1,146 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * Maximum number of connection records allowed to analyze. + * Should match the value set in the browser. + */ +#define TGUI_TELEMETRY_MAX_CONNECTIONS 5 + +/** + * Maximum time allocated for sending a telemetry packet. + */ +#define TGUI_TELEMETRY_RESPONSE_WINDOW (30 SECONDS) + +/// Time of telemetry request +/datum/tgui_panel/var/telemetry_requested_at +/// Time of telemetry analysis completion +/datum/tgui_panel/var/telemetry_analyzed_at +/// List of previous client connections +/datum/tgui_panel/var/list/telemetry_connections + +/** + * private + * + * Requests some telemetry from the client. + */ +/datum/tgui_panel/proc/request_telemetry() + telemetry_requested_at = world.time + telemetry_analyzed_at = null + window.send_message("telemetry/request", list( + "limits" = list( + "connections" = TGUI_TELEMETRY_MAX_CONNECTIONS, + ), + )) + +/** + * private + * + * Analyzes a telemetry packet. + * + * Is currently only useful for detecting ban evasion attempts. + */ +/datum/tgui_panel/proc/analyze_telemetry(payload) + if(world.time > telemetry_requested_at + TGUI_TELEMETRY_RESPONSE_WINDOW) + message_admins("[key_name(client)] sent telemetry outside of the allocated time window.") + return + if(telemetry_analyzed_at) + message_admins("[key_name(client)] sent telemetry more than once.") + return + telemetry_analyzed_at = world.time + if(!payload) + return + telemetry_connections = payload["connections"] + var/len = length(telemetry_connections) + if(len == 0) + return + if(len > TGUI_TELEMETRY_MAX_CONNECTIONS) + message_admins("[key_name(client)] was kicked for sending a huge telemetry payload") + qdel(client) + return + + var/ckey = client?.ckey + if (!ckey) + return + + /* FIXME: Stuff we dont have > Can be reimplemented later on + var/list/all_known_alts = GLOB.known_alts.load_known_alts() + var/list/our_known_alts = list() + + for (var/known_alt in all_known_alts) + if (known_alt[1] == ckey) + our_known_alts += known_alt[2] + else if (known_alt[2] == ckey) + our_known_alts += known_alt[1] + + var/list/found + + var/list/query_data = list() + + for(var/i in 1 to len) + if(QDELETED(client)) + // He got cleaned up before we were done + return + var/list/row = telemetry_connections[i] + + // Check for a malformed history object + if (!row || row.len < 3 || (!row["ckey"] || !row["address"] || !row["computer_id"])) + return + + if (!isnull(GLOB.round_id)) + query_data += list(list( + "telemetry_ckey" = row["ckey"], + "address" = row["address"], + "computer_id" = row["computer_id"], + )) + + if (row["ckey"] in our_known_alts) + continue + + if (world.IsBanned(row["ckey"], row["address"], row["computer_id"], real_bans_only = TRUE)) + found = row + break + + CHECK_TICK + + // This fucker has a history of playing on a banned account. + if(found) + var/msg = "[key_name(client)] has a banned account in connection history! (Matched: [found["ckey"]], [found["address"]], [found["computer_id"]])" + message_admins(msg) + send2tgs_adminless_only("Banned-user", msg) + log_admin_private(msg) + log_suspicious_login(msg, access_log_mirror = FALSE) + + // Only log them all at the end, since it's not as important as reporting an evader + for (var/list/one_query as anything in query_data) + var/datum/db_query/query = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("telemetry_connections")] ( + ckey, + telemetry_ckey, + address, + computer_id, + first_round_id, + latest_round_id + ) VALUES( + :ckey, + :telemetry_ckey, + INET_ATON(:address), + :computer_id, + :round_id, + :round_id + ) ON DUPLICATE KEY UPDATE latest_round_id = :round_id + "}, list( + "ckey" = ckey, + "telemetry_ckey" = one_query["telemetry_ckey"], + "address" = one_query["address"], + "computer_id" = one_query["computer_id"], + "round_id" = GLOB.round_id, + )) + query.Execute() + qdel(query) + */ + +#undef TGUI_TELEMETRY_MAX_CONNECTIONS +#undef TGUI_TELEMETRY_RESPONSE_WINDOW diff --git a/code/modules/tgui_panel/tgui_panel.dm b/code/modules/tgui_panel/tgui_panel.dm new file mode 100644 index 0000000000..ffb31cd788 --- /dev/null +++ b/code/modules/tgui_panel/tgui_panel.dm @@ -0,0 +1,102 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * tgui_panel datum + * Hosts tgchat and other nice features. + */ +/datum/tgui_panel + var/client/client + var/datum/tgui_window/window + var/broken = FALSE + var/initialized_at + var/oldchat = FALSE + +/datum/tgui_panel/New(client/client, id) + src.client = client + window = new(client, id) + window.subscribe(src, PROC_REF(on_message)) + +/datum/tgui_panel/Del() + window.unsubscribe(src) + window.close() + return ..() + +/** + * public + * + * TRUE if panel is initialized and ready to receive messages. + */ +/datum/tgui_panel/proc/is_ready() + return !broken && window.is_ready() + +/** + * public + * + * Initializes tgui panel. + */ +/datum/tgui_panel/proc/initialize(force = FALSE) + set waitfor = FALSE + // Minimal sleep to defer initialization to after client constructor + sleep(1 TICKS) + initialized_at = world.time + // Perform a clean initialization + window.initialize( + strict_mode = TRUE, + assets = list( + get_asset_datum(/datum/asset/simple/tgui_panel), + )) + window.send_asset(get_asset_datum(/datum/asset/simple/fontawesome)) + window.send_asset(get_asset_datum(/datum/asset/simple/tgfont)) + window.send_asset(get_asset_datum(/datum/asset/spritesheet/chat)) + // Other setup + request_telemetry() + addtimer(CALLBACK(src, PROC_REF(on_initialize_timed_out)), 5 SECONDS) + +/** + * private + * + * Called when initialization has timed out. + */ +/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, click HERE to attempt to reload it.") + +/** + * private + * + * Callback for handling incoming tgui messages. + */ +/datum/tgui_panel/proc/on_message(type, payload) + if(type == "ready") + broken = FALSE + window.send_message("update", list( + "config" = list( + "client" = list( + "ckey" = client.ckey, + "address" = client.address, + "computer_id" = client.computer_id, + ), + "window" = list( + "fancy" = FALSE, + "locked" = FALSE, + ), + ), + )) + return TRUE + if(type == "audio/setAdminMusicVolume") + client.admin_music_volume = payload["volume"] + return TRUE + if(type == "telemetry") + analyze_telemetry(payload) + return TRUE + +/** + * public + * + * Sends a round restart notification. + */ +/datum/tgui_panel/proc/send_roundrestart() + window.send_message("roundrestart") diff --git a/code/modules/vchat/css/ss13styles.css b/code/modules/vchat/css/ss13styles.css index 0b0f14425c..08cea0956a 100644 --- a/code/modules/vchat/css/ss13styles.css +++ b/code/modules/vchat/css/ss13styles.css @@ -129,6 +129,7 @@ body.inverted { .emote {color: #000000;} .inverted .emote {color: #FFFFFF;} .alert {color: #ff0000;} +.valert {color: #ff0000;} h1.alert, h2.alert {color: #000000;} /* VOREStation Add Start */ .nif {} @@ -147,12 +148,16 @@ h1.alert, h2.alert {color: #000000;} .critical {color: #ff0000; font-weight: bold; font-size: 150%;} .danger {color: #ff0000; font-weight: bold;} +.vdanger {color: #ff0000; font-weight: bold;} .warning {color: #ff0000; font-style: italic;} +.vwarning {color: #ff0000; font-style: italic;} .rose {color: #ff5050;} .info {color: #0000CC;} .inverted .info {color: #6060c9;} /* Dark mode */ .notice {color: #000099;} .inverted .notice {color: #6060c9;} /* Dark mode */ +.vnotice {color: #000099;} +.inverted .vnotice {color: #6060c9;} /* Dark mode */ .alium {color: #00ff00;} .cult {color: #800080; font-weight: bold; font-style: italic;} diff --git a/code/modules/vchat/js/vchat.js b/code/modules/vchat/js/vchat.js index 9b9f9b6dba..414f047891 100644 --- a/code/modules/vchat/js/vchat.js +++ b/code/modules/vchat/js/vchat.js @@ -176,6 +176,14 @@ function start_vue() { required: false, admin: false }, + { + matches: ".valert, .vwarning, .vnotice, .vdanger", + becomes: "vc_vore_message", + pretty: "Vore Messages", + tooltip: "Vore Messages", + required: false, + admin: false + }, { matches: ".filter_deadsay, .deadsay", becomes: "vc_deadchat", diff --git a/code/modules/vchat/js/vchat.min.js b/code/modules/vchat/js/vchat.min.js index 4a220ec820..16b7753747 100644 --- a/code/modules/vchat/js/vchat.min.js +++ b/code/modules/vchat/js/vchat.min.js @@ -1 +1 @@ -!function(){var e=console.log;console.log=function(t){send_debug(t),e.apply(console,arguments)};var t=console.error;console.error=function(e){send_debug(e),t.apply(console,arguments)},window.onerror=function(e,t,s,a,n){var o="";return n&&n.stack&&(o=n.stack),send_debug(e+" ("+t+"@"+s+":"+a+") "+n+"|UA: "+navigator.userAgent+"|Stack: "+o),!0}}();var vueapp,vchat_opts={msBeforeDropped:3e4,cookiePrefix:"vst-",alwaysShow:["vc_looc","vc_system"],vchatTabsVer:1},DARKMODE_COLORS={buttonBgColor:"#40628a",buttonTextColor:"#FFFFFF",windowBgColor:"#272727",highlightColor:"#009900",tabTextColor:"#FFFFFF",tabBackgroundColor:"#272727"},LIGHTMODE_COLORS={buttonBgColor:"none",buttonTextColor:"#000000",windowBgColor:"none",highlightColor:"#007700",tabTextColor:"#000000",tabBackgroundColor:"none"},set_storage=set_cookie,get_storage=get_cookie,domparser=new DOMParser;storageAvailable("localStorage")&&(set_storage=set_localstorage,get_storage=get_localstorage);var vchat_state={ready:!1,byond_ip:null,byond_cid:null,byond_ckey:null,lastPingReceived:0,latency_sent:0,lastId:0};function start_vchat(){start_vue(),vchat_state.ready=!0,push_Topic("done_loading"),push_Topic_showingnum(this.showingnum),doWinset("htmloutput",{"is-visible":!0}),doWinset("oldoutput",{"is-visible":!1}),doWinset("chatloadlabel",{"is-visible":!1}),setInterval(check_ping,vchat_opts.msBeforeDropped),send_debug("VChat Loaded!")}function start_vue(){vueapp=new Vue({el:"#app",data:{messages:[],shown_messages:[],unshown_messages:0,archived_messages:[],tabs:[{name:"Main",categories:[],immutable:!0,active:!0}],unread_messages:{},editing:!1,paused:!1,latency:0,reconnecting:!1,ext_styles:"",is_admin:!1,inverted:!1,crushing:3,animated:!1,fontsize:.9,lineheight:130,showingnum:200,type_table:[{matches:".filter_say, .say, .emote, .emotesubtle",becomes:"vc_localchat",pretty:"Local Chat",tooltip:"In-character local messages (say, emote, etc)",required:!1,admin:!1},{matches:".filter_radio, .alert, .syndradio, .centradio, .airadio, .entradio, .comradio, .secradio, .engradio, .medradio, .sciradio, .supradio, .srvradio, .expradio, .radio, .deptradio, .newscaster",becomes:"vc_radio",pretty:"Radio Comms",tooltip:"All departments of radio messages",required:!1,admin:!1},{matches:".filter_notice, .notice:not(.pm), .adminnotice, .info, .sinister, .cult",becomes:"vc_info",pretty:"Notices",tooltip:"Non-urgent messages from the game and items",required:!1,admin:!1},{matches:".filter_warning, .warning:not(.pm), .critical, .userdanger, .italics",becomes:"vc_warnings",pretty:"Warnings",tooltip:"Urgent messages from the game and items",required:!1,admin:!1},{matches:".filter_deadsay, .deadsay",becomes:"vc_deadchat",pretty:"Deadchat",tooltip:"All of deadchat",required:!1,admin:!1},{matches:".filter_pray",becomes:"vc_pray",pretty:"Pray",tooltip:"Prayer messages",required:!1,admin:!1},{matches:".ooc, .filter_ooc",becomes:"vc_globalooc",pretty:"Global OOC",tooltip:"The bluewall of global OOC messages",required:!1,admin:!1},{matches:".nif",becomes:"vc_nif",pretty:"NIF Messages",tooltip:"Messages from the NIF itself and people inside",required:!1,admin:!1},{matches:".psay, .pemote",becomes:"vc_pmessage",pretty:"Pred/Prey Messages",tooltip:"Messages from / to absorbed or dominated prey",required:!1,admin:!1},{matches:".mentor_channel, .mentor",becomes:"vc_mentor",pretty:"Mentor messages",tooltip:"Mentorchat and mentor pms",required:!1,admin:!1},{matches:".filter_pm, .pm",becomes:"vc_adminpm",pretty:"Admin PMs",tooltip:"Messages to/from admins ('adminhelps')",required:!1,admin:!1},{matches:".filter_ASAY, .admin_channel",becomes:"vc_adminchat",pretty:"Admin Chat",tooltip:"ASAY messages",required:!1,admin:!0},{matches:".filter_MSAY, .mod_channel",becomes:"vc_modchat",pretty:"Mod Chat",tooltip:"MSAY messages",required:!1,admin:!0},{matches:".filter_ESAY, .event_channel",becomes:"vc_eventchat",pretty:"Event Chat",tooltip:"ESAY messages",required:!1,admin:!0},{matches:".filter_combat, .danger",becomes:"vc_combat",pretty:"Combat Logs",tooltip:"Urist McTraitor has stabbed you with a knife!",required:!1,admin:!1},{matches:".filter_adminlogs, .log_message",becomes:"vc_adminlogs",pretty:"Admin Logs",tooltip:"ADMIN LOG: Urist McAdmin has jumped to coordinates X, Y, Z",required:!1,admin:!0},{matches:".filter_attacklogs",becomes:"vc_attacklogs",pretty:"Attack Logs",tooltip:"Urist McTraitor has shot John Doe",required:!1,admin:!0},{matches:".filter_debuglogs",becomes:"vc_debuglogs",pretty:"Debug Logs",tooltip:"DEBUG: SSPlanets subsystem Recover().",required:!1,admin:!0},{matches:".looc",becomes:"vc_looc",pretty:"Local OOC",tooltip:"Local OOC messages, always enabled",required:!0},{matches:".rlooc",becomes:"vc_rlooc",pretty:"Remote LOOC",tooltip:"Remote LOOC messages",required:!1,admin:!0},{matches:".boldannounce, .filter_system",becomes:"vc_system",pretty:"System Messages",tooltip:"Messages from your client, always enabled",required:!0},{matches:".unsorted",becomes:"vc_unsorted",pretty:"Unsorted",tooltip:"Messages that don't have any filters.",required:!1,admin:!1}]},mounted:function(){this.load_settings();var e=new XMLHttpRequest;e.open("GET","ss13styles.css"),e.onreadystatechange=(function(){this.ext_styles=e.responseText}).bind(this),e.send()},updated:function(){this.editing||this.paused||window.scrollTo(0,document.getElementById("messagebox").scrollHeight)},watch:{reconnecting:function(e,t){!0==e&&!1==t?this.internal_message("Your client has lost connection to the server, or there is severe lag. Your client will reconnect if possible."):!1==e&&!0==t&&this.internal_message("Your client has reconnected to the server.")},inverted:function(e){set_storage("darkmode",e),e?(document.body.classList.add("inverted"),switch_ui_mode(DARKMODE_COLORS)):(document.body.classList.remove("inverted"),switch_ui_mode(LIGHTMODE_COLORS))},crushing:function(e){set_storage("crushing",e)},animated:function(e){set_storage("animated",e)},fontsize:function(e,t){if(isNaN(e)){this.fontsize=t;return}e<.2?this.fontsize=.2:e>5&&(this.fontsize=5),set_storage("fontsize",e)},lineheight:function(e,t){if(!isFinite(e)){this.lineheight=t;return}e<100?this.lineheight=100:e>200&&(this.lineheight=200),set_storage("lineheight",e)},showingnum:function(e,t){if(!isFinite(e)){this.showingnum=t;return}(e=Math.floor(e))<50?this.showingnum=50:e>2e3&&(this.showingnum=2e3),set_storage("showingnum",this.showingnum),push_Topic_showingnum(this.showingnum),this.attempt_archive()},current_categories:function(e,t){e.length&&this.apply_filter(e)}},computed:{active_tab:function(){return this.tabs.find(function(e){return e.active})},ping_classes:function(){return this.latency?"?"==this.latency?"grey":this.latency<0?"red":this.latency<=200?"green":this.latency<=400?"yellow":"grey":this.reconnecting?"red":"green"},current_categories:function(){return this.active_tab==this.tabs[0]?[]:this.active_tab.categories.concat(vchat_opts.alwaysShow)}},methods:{load_settings:function(){this.inverted=get_storage("darkmode",!1),this.crushing=get_storage("crushing",3),this.animated=get_storage("animated",!1),this.fontsize=get_storage("fontsize",.9),this.lineheight=get_storage("lineheight",130),this.showingnum=get_storage("showingnum",200),isNaN(this.crushing)&&(this.crushing=3),isNaN(this.fontsize)&&(this.fontsize=.9),this.load_tabs()},load_tabs:function(){var e=get_storage("tabs");if(e){var t=JSON.parse(e);if(!t.version||!t.tabs){this.internal_message("There was a problem loading your tabs. Any new ones you make will be saved, however.");return}if(!t.version==vchat_opts.vchatTabsVer){this.internal_message("Your saved tabs are for an older version of VChat and must be recreated, sorry.");return}this.tabs.push.apply(this.tabs,t.tabs)}},save_tabs:function(){var e={version:vchat_opts.vchatTabsVer,tabs:[]};this.tabs.forEach(function(t){if(!t.immutable){var s=t.name,a=[];t.categories.forEach(function(e){a.push(e)}),e.tabs.push({name:s,categories:a,immutable:!1,active:!1})}}),set_storage("tabs",JSON.stringify(e))},switchtab:function(e){e!=this.active_tab&&(this.active_tab.active=!1,e.active=!0,e.categories.forEach(function(e){this.unread_messages[e]=0},this),this.apply_filter(this.current_categories))},editmode:function(){this.editing=!this.editing,this.save_tabs()},pause:function(){this.paused=!this.paused},newtab:function(){this.tabs.push({name:"New Tab",categories:[],immutable:!1,active:!1}),this.switchtab(this.tabs[this.tabs.length-1])},renametab:function(){if(!this.active_tab.immutable){var e=this.active_tab,t=window.prompt("Type the desired tab name:",e.name);null!==t&&""!==t&&null!==e&&(e.name=t)}},deltab:function(e){e||(e=this.active_tab),!e.immutable&&(this.switchtab(this.tabs[0]),this.tabs.splice(this.tabs.indexOf(e),1))},movetab:function(e,t){if(e&&!e.immutable){var s=this.tabs.indexOf(e);this.tabs.splice(s+t,0,this.tabs.splice(s,1)[0])}},tab_unread_count:function(e){var t=0,s=this.unread_messages;return e.categories.find(function(e){s[e]&&(t+=s[e])}),t},tab_unread_categories:function(e){var t=!1,s=this.unread_messages;return e.categories.find(function(e){if(s[e])return t=!0,!0}),{red:t,grey:!t}},attempt_archive:function(){if(this.messages.length>this.showingnum){var e=this.messages.splice(0,20);Array.prototype.push.apply(this.archived_messages,e)}},apply_filter:function(e){this.shown_messages.splice(0),this.unshown_messages=0,this.messages.forEach(function(t){e.indexOf(t.category)>-1&&this.shown_messages.push(t)},this),this.archived_messages.forEach(function(t){e.indexOf(t.category)>-1&&this.unshown_messages++},this)},add_message:function(e){let t={time:e.time,category:"error",content:e.message,repeats:1};if(t.category=this.get_category(t.content),"vc_unsorted"==t.category&&(t.content=""+t.content+""),this.crushing){let s=this.messages.slice(-this.crushing);for(let a=s.length-1;a>=0;a--){let n=s[a];n.content==t.content&&(t.repeats+=n.repeats,this.messages.splice(this.messages.indexOf(n),1))}}t.content=t.content.replace(/(\b(https?):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/img,'$1'),this.current_categories.length&&0>this.current_categories.indexOf(t.category)?(isNaN(this.unread_messages[t.category])&&(this.unread_messages[t.category]=0),this.unread_messages[t.category]+=1):this.current_categories.length&&this.shown_messages.push(t),t.id=++vchat_state.lastId,this.attempt_archive(),this.messages.push(t)},internal_message:function(e){let t={time:this.messages.length?this.messages.slice(-1).time+1:0,category:"vc_system",content:"[VChat Internal] "+e+""};t.id=++vchat_state.lastId,this.messages.push(t)},on_mouseup:function(e){let t=e.target;"getSelection"in window&&!1===window.getSelection().isCollapsed||t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName)||(focusMapWindow(),e.preventDefault(),e.target.click())},click_message:function(e){let t=e.target;if("A"===t.tagName){e.stopPropagation(),e.preventDefault?e.preventDefault():e.returnValue=!1;var s=t.getAttribute("href");"?"==s[0]||s.length>=8&&"byond://"==s.substring(0,8)?window.location=s:window.location="byond://?action=openLink&link="+encodeURIComponent(s)}},get_category:function(e){if(!vchat_state.ready){push_Topic("not_ready");return}let t=domparser.parseFromString(e,"text/html").querySelector("span"),s="vc_unsorted";return t&&this.type_table.find(function(e){if(t.msMatchesSelector(e.matches))return s=e.becomes,!0}),s},save_chatlog:function(){var e="",t=this.archived_messages.concat(this.messages),s=this.current_categories;t.forEach(function(t){(0==s.length||s.indexOf(t.category)>=0)&&(e+=t.content,t.repeats>1&&(e+="(x"+t.repeats+")"),e+="
\n")}),e+="";var a=new Date,n=String(a.getHours());n.length<2&&(n="0"+n);var o=String(a.getMinutes());o.length<2&&(o="0"+o);var i=String(a.getDate());i.length<2&&(i="0"+i);var r=String(a.getMonth()+1);r.length<2&&(r="0"+r);var c="log"+(" "+String(a.getFullYear())+"-"+r+"-"+i+" ("+n+" "+o)+").html",l=document.createElement("a");if(void 0!==l.download)l.href="data:attachment/text,"+encodeURI(e),l.target="_blank",l.download=c,l.click();else{var h=new Blob([e],{type:"text/html;charset=utf8;"});saved=window.navigator.msSaveOrOpenBlob(h,c)}},do_latency_test:function(){send_latency_check()},blur_this:function(e){e.target.blur()}}})}function check_ping(){Date.now()-vchat_state.lastPingReceived>vchat_opts.msBeforeDropped&&(vueapp.reconnecting=!0)}function send_latency_check(){vchat_state.latency_sent||(vchat_state.latency_sent=Date.now(),vueapp.latency="?",push_Topic("ping"),setTimeout(function(){"?"==vchat_state.latency_ms&&(vchat_state.latency_ms=999)},1e3),setTimeout(function(){vchat_state.latency_sent=0,vueapp.latency=0},5e3))}function get_latency_check(){vchat_state.latency_sent&&(vueapp.latency=Date.now()-vchat_state.latency_sent)}function byondDecode(e){e=e.replace(/\+/g,"%20");try{e=decodeURIComponent(e)}catch(t){e=unescape(e)}return JSON.parse(e)}function putmessage(e){Array.isArray(e=byondDecode(e))?e.forEach(function(e){vueapp.add_message(e)}):"object"==typeof e&&vueapp.add_message(e)}function system_message(e){vueapp.internal_message(e)}function push_Topic(e){window.location="?_src_=chat&proc="+e}function push_Topic_showingnum(e){window.location="?_src_=chat&showingnum="+e}function focusMapWindow(){window.location="byond://winset?mapwindow.map.focus=true"}function send_debug(e){push_Topic("debug¶m[message]="+encodeURIComponent(e))}function get_event(e){if(!vchat_state.ready){push_Topic("not_ready");return}var t={evttype:"internal_error",event:e};switch((t=byondDecode(e)).evttype){case"internal_error":system_message("Event parse error: "+e);break;case"byond_player":send_client_data(),vueapp.is_admin="true"===t.admin,vchat_state.byond_ip=t.address,vchat_state.byond_cid=t.cid,vchat_state.byond_ckey=t.ckey,set_storage("ip",vchat_state.byond_ip),set_storage("cid",vchat_state.byond_cid),set_storage("ckey",vchat_state.byond_ckey);break;case"keepalive":vchat_state.lastPingReceived=Date.now(),vueapp.reconnecting=!1;break;case"pong":get_latency_check();break;case"availability":push_Topic("done_loading");break;default:system_message("Didn't know what to do with event: "+e)}}function send_client_data(){push_Topic("ident¶m[clientdata]="+JSON.stringify({ip:get_storage("ip"),cid:get_storage("cid"),ckey:get_storage("ckey")}))}function set_localstorage(e,t){window.localStorage.setItem(vchat_opts.cookiePrefix+e,t)}function get_localstorage(e,t){let s=window.localStorage.getItem(vchat_opts.cookiePrefix+e);return"null"===s||null===s?s=t:"true"===s?s=!0:"false"===s?s=!1:isNaN(s)||(s=+s),s}function set_cookie(e,t){let s=new Date;s.setFullYear(s.getFullYear()+1);let a=s.toUTCString();document.cookie=vchat_opts.cookiePrefix+e+"="+t+";expires="+a+";path=/"}function get_cookie(e,t){var s={cookie:null,localstorage:null,indexeddb:null};let a=document.cookie.split(";"),n={};a.forEach(function(e){let s=e.replace(vchat_opts.cookiePrefix,"").trim(),a=s.search("="),o=decodeURIComponent(s.substring(0,a)),i=decodeURIComponent(s.substring(a+1));"null"==i||null===i?i=t:"true"===i?i=!0:"false"===i?i=!1:isNaN(i)||(i=+i),n[o]=i}),s.cookie=n[e]}var SKIN_BUTTONS=["rpane.textb","rpane.infob","rpane.wikib","rpane.forumb","rpane.rulesb","rpane.github","rpane.discord","rpane.mapb","rpane.changelog","mainwindow.saybutton","mainwindow.mebutton","mainwindow.hotkey_toggle"],SKIN_ELEMENTS=["mainwindow","mainwindow.mainvsplit","mainwindow.tooltip","rpane","rpane.rpanewindow","rpane.mediapanel",];function switch_ui_mode(e){doWinset(SKIN_BUTTONS.reduce(function(t,s){return t[s+".background-color"]=e.buttonBgColor,t},{})),doWinset(SKIN_BUTTONS.reduce(function(t,s){return t[s+".text-color"]=e.buttonTextColor,t},{})),doWinset(SKIN_ELEMENTS.reduce(function(t,s){return t[s+".background-color"]=e.windowBgColor,t},{})),doWinset("infowindow",{"background-color":e.tabBackgroundColor,"text-color":e.tabTextColor}),doWinset("infowindow.info",{"background-color":e.tabBackgroundColor,"text-color":e.tabTextColor,"highlight-color":e.highlightColor,"tab-text-color":e.tabTextColor,"tab-background-color":e.tabBackgroundColor})}function doWinset(e,t){void 0===t&&(t=e,e=null);var s="byond://winset?";e&&(s+="id="+e+"&"),s+=Object.keys(t).map(function(e){return e+"="+encodeURIComponent(t[e])}).join("&"),window.location=s} +!function(){var e=console.log;console.log=function(t){send_debug(t),e.apply(console,arguments)};var t=console.error;console.error=function(e){send_debug(e),t.apply(console,arguments)},window.onerror=function(e,t,s,a,n){var o="";return n&&n.stack&&(o=n.stack),send_debug(e+" ("+t+"@"+s+":"+a+") "+n+"|UA: "+navigator.userAgent+"|Stack: "+o),!0}}();var vueapp,vchat_opts={msBeforeDropped:3e4,cookiePrefix:"vst-",alwaysShow:["vc_looc","vc_system"],vchatTabsVer:1},DARKMODE_COLORS={buttonBgColor:"#40628a",buttonTextColor:"#FFFFFF",windowBgColor:"#272727",highlightColor:"#009900",tabTextColor:"#FFFFFF",tabBackgroundColor:"#272727"},LIGHTMODE_COLORS={buttonBgColor:"none",buttonTextColor:"#000000",windowBgColor:"none",highlightColor:"#007700",tabTextColor:"#000000",tabBackgroundColor:"none"},set_storage=set_cookie,get_storage=get_cookie,domparser=new DOMParser;storageAvailable("localStorage")&&(set_storage=set_localstorage,get_storage=get_localstorage);var vchat_state={ready:!1,byond_ip:null,byond_cid:null,byond_ckey:null,lastPingReceived:0,latency_sent:0,lastId:0};function start_vchat(){start_vue(),vchat_state.ready=!0,push_Topic("done_loading"),push_Topic_showingnum(this.showingnum),doWinset("htmloutput",{"is-visible":!0}),doWinset("oldoutput",{"is-visible":!1}),doWinset("chatloadlabel",{"is-visible":!1}),setInterval(check_ping,vchat_opts.msBeforeDropped),send_debug("VChat Loaded!")}function start_vue(){vueapp=new Vue({el:"#app",data:{messages:[],shown_messages:[],unshown_messages:0,archived_messages:[],tabs:[{name:"Main",categories:[],immutable:!0,active:!0}],unread_messages:{},editing:!1,paused:!1,latency:0,reconnecting:!1,ext_styles:"",is_admin:!1,inverted:!1,crushing:3,animated:!1,fontsize:.9,lineheight:130,showingnum:200,type_table:[{matches:".filter_say, .say, .emote, .emotesubtle",becomes:"vc_localchat",pretty:"Local Chat",tooltip:"In-character local messages (say, emote, etc)",required:!1,admin:!1},{matches:".filter_radio, .alert, .syndradio, .centradio, .airadio, .entradio, .comradio, .secradio, .engradio, .medradio, .sciradio, .supradio, .srvradio, .expradio, .radio, .deptradio, .newscaster",becomes:"vc_radio",pretty:"Radio Comms",tooltip:"All departments of radio messages",required:!1,admin:!1},{matches:".filter_notice, .notice:not(.pm), .adminnotice, .info, .sinister, .cult",becomes:"vc_info",pretty:"Notices",tooltip:"Non-urgent messages from the game and items",required:!1,admin:!1},{matches:".filter_warning, .warning:not(.pm), .critical, .userdanger, .italics",becomes:"vc_warnings",pretty:"Warnings",tooltip:"Urgent messages from the game and items",required:!1,admin:!1},{matches:".valert, .vwarning, .vnotice, .vdanger",becomes:"vc_vore_message",pretty:"Vore Messages",tooltip:"Vore Messages",required:!1,admin:!1},{matches:".filter_deadsay, .deadsay",becomes:"vc_deadchat",pretty:"Deadchat",tooltip:"All of deadchat",required:!1,admin:!1},{matches:".filter_pray",becomes:"vc_pray",pretty:"Pray",tooltip:"Prayer messages",required:!1,admin:!1},{matches:".ooc, .filter_ooc",becomes:"vc_globalooc",pretty:"Global OOC",tooltip:"The bluewall of global OOC messages",required:!1,admin:!1},{matches:".nif",becomes:"vc_nif",pretty:"NIF Messages",tooltip:"Messages from the NIF itself and people inside",required:!1,admin:!1},{matches:".psay, .pemote",becomes:"vc_pmessage",pretty:"Pred/Prey Messages",tooltip:"Messages from / to absorbed or dominated prey",required:!1,admin:!1},{matches:".mentor_channel, .mentor",becomes:"vc_mentor",pretty:"Mentor messages",tooltip:"Mentorchat and mentor pms",required:!1,admin:!1},{matches:".filter_pm, .pm",becomes:"vc_adminpm",pretty:"Admin PMs",tooltip:"Messages to/from admins ('adminhelps')",required:!1,admin:!1},{matches:".filter_ASAY, .admin_channel",becomes:"vc_adminchat",pretty:"Admin Chat",tooltip:"ASAY messages",required:!1,admin:!0},{matches:".filter_MSAY, .mod_channel",becomes:"vc_modchat",pretty:"Mod Chat",tooltip:"MSAY messages",required:!1,admin:!0},{matches:".filter_ESAY, .event_channel",becomes:"vc_eventchat",pretty:"Event Chat",tooltip:"ESAY messages",required:!1,admin:!0},{matches:".filter_combat, .danger",becomes:"vc_combat",pretty:"Combat Logs",tooltip:"Urist McTraitor has stabbed you with a knife!",required:!1,admin:!1},{matches:".filter_adminlogs, .log_message",becomes:"vc_adminlogs",pretty:"Admin Logs",tooltip:"ADMIN LOG: Urist McAdmin has jumped to coordinates X, Y, Z",required:!1,admin:!0},{matches:".filter_attacklogs",becomes:"vc_attacklogs",pretty:"Attack Logs",tooltip:"Urist McTraitor has shot John Doe",required:!1,admin:!0},{matches:".filter_debuglogs",becomes:"vc_debuglogs",pretty:"Debug Logs",tooltip:"DEBUG: SSPlanets subsystem Recover().",required:!1,admin:!0},{matches:".looc",becomes:"vc_looc",pretty:"Local OOC",tooltip:"Local OOC messages, always enabled",required:!0},{matches:".rlooc",becomes:"vc_rlooc",pretty:"Remote LOOC",tooltip:"Remote LOOC messages",required:!1,admin:!0},{matches:".boldannounce, .filter_system",becomes:"vc_system",pretty:"System Messages",tooltip:"Messages from your client, always enabled",required:!0},{matches:".unsorted",becomes:"vc_unsorted",pretty:"Unsorted",tooltip:"Messages that don't have any filters.",required:!1,admin:!1}]},mounted:function(){this.load_settings();var e=new XMLHttpRequest;e.open("GET","ss13styles.css"),e.onreadystatechange=(function(){this.ext_styles=e.responseText}).bind(this),e.send()},updated:function(){this.editing||this.paused||window.scrollTo(0,document.getElementById("messagebox").scrollHeight)},watch:{reconnecting:function(e,t){!0==e&&!1==t?this.internal_message("Your client has lost connection to the server, or there is severe lag. Your client will reconnect if possible."):!1==e&&!0==t&&this.internal_message("Your client has reconnected to the server.")},inverted:function(e){set_storage("darkmode",e),e?(document.body.classList.add("inverted"),switch_ui_mode(DARKMODE_COLORS)):(document.body.classList.remove("inverted"),switch_ui_mode(LIGHTMODE_COLORS))},crushing:function(e){set_storage("crushing",e)},animated:function(e){set_storage("animated",e)},fontsize:function(e,t){if(isNaN(e)){this.fontsize=t;return}e<.2?this.fontsize=.2:e>5&&(this.fontsize=5),set_storage("fontsize",e)},lineheight:function(e,t){if(!isFinite(e)){this.lineheight=t;return}e<100?this.lineheight=100:e>200&&(this.lineheight=200),set_storage("lineheight",e)},showingnum:function(e,t){if(!isFinite(e)){this.showingnum=t;return}(e=Math.floor(e))<50?this.showingnum=50:e>2e3&&(this.showingnum=2e3),set_storage("showingnum",this.showingnum),push_Topic_showingnum(this.showingnum),this.attempt_archive()},current_categories:function(e,t){e.length&&this.apply_filter(e)}},computed:{active_tab:function(){return this.tabs.find(function(e){return e.active})},ping_classes:function(){return this.latency?"?"==this.latency?"grey":this.latency<0?"red":this.latency<=200?"green":this.latency<=400?"yellow":"grey":this.reconnecting?"red":"green"},current_categories:function(){return this.active_tab==this.tabs[0]?[]:this.active_tab.categories.concat(vchat_opts.alwaysShow)}},methods:{load_settings:function(){this.inverted=get_storage("darkmode",!1),this.crushing=get_storage("crushing",3),this.animated=get_storage("animated",!1),this.fontsize=get_storage("fontsize",.9),this.lineheight=get_storage("lineheight",130),this.showingnum=get_storage("showingnum",200),isNaN(this.crushing)&&(this.crushing=3),isNaN(this.fontsize)&&(this.fontsize=.9),this.load_tabs()},load_tabs:function(){var e=get_storage("tabs");if(e){var t=JSON.parse(e);if(!t.version||!t.tabs){this.internal_message("There was a problem loading your tabs. Any new ones you make will be saved, however.");return}if(!t.version==vchat_opts.vchatTabsVer){this.internal_message("Your saved tabs are for an older version of VChat and must be recreated, sorry.");return}this.tabs.push.apply(this.tabs,t.tabs)}},save_tabs:function(){var e={version:vchat_opts.vchatTabsVer,tabs:[]};this.tabs.forEach(function(t){if(!t.immutable){var s=t.name,a=[];t.categories.forEach(function(e){a.push(e)}),e.tabs.push({name:s,categories:a,immutable:!1,active:!1})}}),set_storage("tabs",JSON.stringify(e))},switchtab:function(e){e!=this.active_tab&&(this.active_tab.active=!1,e.active=!0,e.categories.forEach(function(e){this.unread_messages[e]=0},this),this.apply_filter(this.current_categories))},editmode:function(){this.editing=!this.editing,this.save_tabs()},pause:function(){this.paused=!this.paused},newtab:function(){this.tabs.push({name:"New Tab",categories:[],immutable:!1,active:!1}),this.switchtab(this.tabs[this.tabs.length-1])},renametab:function(){if(!this.active_tab.immutable){var e=this.active_tab,t=window.prompt("Type the desired tab name:",e.name);null!==t&&""!==t&&null!==e&&(e.name=t)}},deltab:function(e){e||(e=this.active_tab),!e.immutable&&(this.switchtab(this.tabs[0]),this.tabs.splice(this.tabs.indexOf(e),1))},movetab:function(e,t){if(e&&!e.immutable){var s=this.tabs.indexOf(e);this.tabs.splice(s+t,0,this.tabs.splice(s,1)[0])}},tab_unread_count:function(e){var t=0,s=this.unread_messages;return e.categories.find(function(e){s[e]&&(t+=s[e])}),t},tab_unread_categories:function(e){var t=!1,s=this.unread_messages;return e.categories.find(function(e){if(s[e])return t=!0,!0}),{red:t,grey:!t}},attempt_archive:function(){if(this.messages.length>this.showingnum){var e=this.messages.splice(0,20);Array.prototype.push.apply(this.archived_messages,e)}},apply_filter:function(e){this.shown_messages.splice(0),this.unshown_messages=0,this.messages.forEach(function(t){e.indexOf(t.category)>-1&&this.shown_messages.push(t)},this),this.archived_messages.forEach(function(t){e.indexOf(t.category)>-1&&this.unshown_messages++},this)},add_message:function(e){let t={time:e.time,category:"error",content:e.message,repeats:1};if(t.category=this.get_category(t.content),"vc_unsorted"==t.category&&(t.content=""+t.content+""),this.crushing){let s=this.messages.slice(-this.crushing);for(let a=s.length-1;a>=0;a--){let n=s[a];n.content==t.content&&(t.repeats+=n.repeats,this.messages.splice(this.messages.indexOf(n),1))}}t.content=t.content.replace(/(\b(https?):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/img,'$1'),this.current_categories.length&&0>this.current_categories.indexOf(t.category)?(isNaN(this.unread_messages[t.category])&&(this.unread_messages[t.category]=0),this.unread_messages[t.category]+=1):this.current_categories.length&&this.shown_messages.push(t),t.id=++vchat_state.lastId,this.attempt_archive(),this.messages.push(t)},internal_message:function(e){let t={time:this.messages.length?this.messages.slice(-1).time+1:0,category:"vc_system",content:"[VChat Internal] "+e+""};t.id=++vchat_state.lastId,this.messages.push(t)},on_mouseup:function(e){let t=e.target;"getSelection"in window&&!1===window.getSelection().isCollapsed||t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName)||(focusMapWindow(),e.preventDefault(),e.target.click())},click_message:function(e){let t=e.target;if("A"===t.tagName){e.stopPropagation(),e.preventDefault?e.preventDefault():e.returnValue=!1;var s=t.getAttribute("href");"?"==s[0]||s.length>=8&&"byond://"==s.substring(0,8)?window.location=s:window.location="byond://?action=openLink&link="+encodeURIComponent(s)}},get_category:function(e){if(!vchat_state.ready){push_Topic("not_ready");return}let t=domparser.parseFromString(e,"text/html").querySelector("span"),s="vc_unsorted";return t&&this.type_table.find(function(e){if(t.msMatchesSelector(e.matches))return s=e.becomes,!0}),s},save_chatlog:function(){var e="",t=this.archived_messages.concat(this.messages),s=this.current_categories;t.forEach(function(t){(0==s.length||s.indexOf(t.category)>=0)&&(e+=t.content,t.repeats>1&&(e+="(x"+t.repeats+")"),e+="
\n")}),e+="";var a=new Date,n=String(a.getHours());n.length<2&&(n="0"+n);var o=String(a.getMinutes());o.length<2&&(o="0"+o);var i=String(a.getDate());i.length<2&&(i="0"+i);var r=String(a.getMonth()+1);r.length<2&&(r="0"+r);var c="log"+(" "+String(a.getFullYear())+"-"+r+"-"+i+" ("+n+" "+o)+").html",l=document.createElement("a");if(void 0!==l.download)l.href="data:attachment/text,"+encodeURI(e),l.target="_blank",l.download=c,l.click();else{var h=new Blob([e],{type:"text/html;charset=utf8;"});saved=window.navigator.msSaveOrOpenBlob(h,c)}},do_latency_test:function(){send_latency_check()},blur_this:function(e){e.target.blur()}}})}function check_ping(){Date.now()-vchat_state.lastPingReceived>vchat_opts.msBeforeDropped&&(vueapp.reconnecting=!0)}function send_latency_check(){vchat_state.latency_sent||(vchat_state.latency_sent=Date.now(),vueapp.latency="?",push_Topic("ping"),setTimeout(function(){"?"==vchat_state.latency_ms&&(vchat_state.latency_ms=999)},1e3),setTimeout(function(){vchat_state.latency_sent=0,vueapp.latency=0},5e3))}function get_latency_check(){vchat_state.latency_sent&&(vueapp.latency=Date.now()-vchat_state.latency_sent)}function byondDecode(e){e=e.replace(/\+/g,"%20");try{e=decodeURIComponent(e)}catch(t){e=unescape(e)}return JSON.parse(e)}function putmessage(e){Array.isArray(e=byondDecode(e))?e.forEach(function(e){vueapp.add_message(e)}):"object"==typeof e&&vueapp.add_message(e)}function system_message(e){vueapp.internal_message(e)}function push_Topic(e){window.location="?_src_=chat&proc="+e}function push_Topic_showingnum(e){window.location="?_src_=chat&showingnum="+e}function focusMapWindow(){window.location="byond://winset?mapwindow.map.focus=true"}function send_debug(e){push_Topic("debug¶m[message]="+encodeURIComponent(e))}function get_event(e){if(!vchat_state.ready){push_Topic("not_ready");return}var t={evttype:"internal_error",event:e};switch((t=byondDecode(e)).evttype){case"internal_error":system_message("Event parse error: "+e);break;case"byond_player":send_client_data(),vueapp.is_admin="true"===t.admin,vchat_state.byond_ip=t.address,vchat_state.byond_cid=t.cid,vchat_state.byond_ckey=t.ckey,set_storage("ip",vchat_state.byond_ip),set_storage("cid",vchat_state.byond_cid),set_storage("ckey",vchat_state.byond_ckey);break;case"keepalive":vchat_state.lastPingReceived=Date.now(),vueapp.reconnecting=!1;break;case"pong":get_latency_check();break;case"availability":push_Topic("done_loading");break;default:system_message("Didn't know what to do with event: "+e)}}function send_client_data(){push_Topic("ident¶m[clientdata]="+JSON.stringify({ip:get_storage("ip"),cid:get_storage("cid"),ckey:get_storage("ckey")}))}function set_localstorage(e,t){window.localStorage.setItem(vchat_opts.cookiePrefix+e,t)}function get_localstorage(e,t){let s=window.localStorage.getItem(vchat_opts.cookiePrefix+e);return"null"===s||null===s?s=t:"true"===s?s=!0:"false"===s?s=!1:isNaN(s)||(s=+s),s}function set_cookie(e,t){let s=new Date;s.setFullYear(s.getFullYear()+1);let a=s.toUTCString();document.cookie=vchat_opts.cookiePrefix+e+"="+t+";expires="+a+";path=/"}function get_cookie(e,t){var s={cookie:null,localstorage:null,indexeddb:null};let a=document.cookie.split(";"),n={};a.forEach(function(e){let s=e.replace(vchat_opts.cookiePrefix,"").trim(),a=s.search("="),o=decodeURIComponent(s.substring(0,a)),i=decodeURIComponent(s.substring(a+1));"null"==i||null===i?i=t:"true"===i?i=!0:"false"===i?i=!1:isNaN(i)||(i=+i),n[o]=i}),s.cookie=n[e]}var SKIN_BUTTONS=["rpane.textb","rpane.infob","rpane.wikib","rpane.forumb","rpane.rulesb","rpane.github","rpane.discord","rpane.mapb","rpane.changelog","mainwindow.saybutton","mainwindow.mebutton","mainwindow.hotkey_toggle"],SKIN_ELEMENTS=["mainwindow","mainwindow.mainvsplit","mainwindow.tooltip","rpane","rpane.rpanewindow","rpane.mediapanel",];function switch_ui_mode(e){doWinset(SKIN_BUTTONS.reduce(function(t,s){return t[s+".background-color"]=e.buttonBgColor,t},{})),doWinset(SKIN_BUTTONS.reduce(function(t,s){return t[s+".text-color"]=e.buttonTextColor,t},{})),doWinset(SKIN_ELEMENTS.reduce(function(t,s){return t[s+".background-color"]=e.windowBgColor,t},{})),doWinset("infowindow",{"background-color":e.tabBackgroundColor,"text-color":e.tabTextColor}),doWinset("infowindow.info",{"background-color":e.tabBackgroundColor,"text-color":e.tabTextColor,"highlight-color":e.highlightColor,"tab-text-color":e.tabTextColor,"tab-background-color":e.tabBackgroundColor})}function doWinset(e,t){void 0===t&&(t=e,e=null);var s="byond://winset?";e&&(s+="id="+e+"&"),s+=Object.keys(t).map(function(e){return e+"="+encodeURIComponent(t[e])}).join("&"),window.location=s} diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index 01651cedf1..e0154da613 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -114,6 +114,81 @@ "Your fruitless mental struggles only shift %pred's %belly a tiny bit.", "You can't make any progress freeing yourself from %pred's %belly.") + var/list/escape_attempt_messages_owner = list( + "%prey is attempting to free themselves from your %belly!") + + var/list/escape_attempt_messages_prey = list( + "You start to climb out of %pred's %belly.") + + var/list/escape_messages_owner = list( + "%prey climbs out of your %belly!") + + var/list/escape_messages_prey = list( + "You climb out of %pred's %belly.") + + var/list/escape_messages_outside = list( + "%prey climbs out of %pred's %belly!") + + var/list/escape_item_messages_owner = list( + "%item suddenly slips out of your %belly!") + + var/list/escape_item_messages_prey = list( + "Your struggles successfully cause %pred to squeeze your %item out of their %belly.") + + var/list/escape_item_messages_outside = list( + "%item suddenly slips out of %pred's %belly!") + + var/list/escape_fail_messages_owner = list( + "%prey's attempt to escape from your %belly has failed!") + + var/list/escape_fail_messages_prey = list( + "Your attempt to escape %pred's %belly has failed!") + + var/list/escape_attempt_absorbed_messages_owner = list( + "%prey is attempting to free themselves from your %belly!") + + var/list/escape_attempt_absorbed_messages_prey = list( + "You try to force yourself out of %pred's %belly.") + + var/list/escape_absorbed_messages_owner = list( + "%prey forces themselves free of your %belly!") + + var/list/escape_absorbed_messages_prey = list( + "You manage to free yourself from %pred's %belly.") + + var/list/escape_absorbed_messages_outside = list( + "%prey climbs out of %pred's %belly!") + + var/list/escape_fail_absorbed_messages_owner = list( + "%prey's attempt to escape form your %belly has failed!") + + var/list/escape_fail_absorbed_messages_prey = list( + "Before you manage to reach freedom, you feel yourself getting dragged back into %pred's %belly!") + + var/list/primary_transfer_messages_owner = list( + "%prey slid into your %dest due to their struggling inside your %belly!") + + var/list/primary_transfer_messages_prey = list( + "Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into pred's %dest!") + + var/list/secondary_transfer_messages_owner = list( + "%prey slid into your %dest due to their struggling inside your %belly!") + + var/list/secondary_transfer_messages_prey = list( + "Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into pred's %dest!") + + var/list/digest_chance_messages_owner = list( + "You feel your %belly beginning to become active!") + + var/list/digest_chance_messages_prey = list( + "In response to your struggling, %owner's %belly begins to get more active...") + + var/list/absorb_chance_messages_owner = list( + "You feel your %belly start to cling onto its contents...") + + var/list/absorb_chance_messages_prey = list( + "In response to your struggling, %owner's %belly begins to cling more tightly...") + var/list/digest_messages_owner = list( "You feel %prey's body succumb to your digestive system, which breaks it apart into soft slurry.", "You hear a lewd glorp as your %belly muscles grind %prey into a warm pulp.", @@ -196,6 +271,7 @@ "digestchance", "absorbchance", "escapechance", + "escapechance_absorbed", "transferchance", "transferchance_secondary", "transferlocation", @@ -207,6 +283,31 @@ "struggle_messages_inside", "absorbed_struggle_messages_outside", "absorbed_struggle_messages_inside", + "escape_attempt_messages_owner", + "escape_attempt_messages_prey", + "escape_messages_owner", + "escape_messages_prey", + "escape_messages_outside", + "escape_item_messages_owner", + "escape_item_messages_prey", + "escape_item_messages_outside", + "escape_fail_messages_owner", + "escape_fail_messages_prey", + "escape_attempt_absorbed_messages_owner", + "escape_attempt_absorbed_messages_prey", + "escape_absorbed_messages_owner", + "escape_absorbed_messages_prey", + "escape_absorbed_messages_outside", + "escape_fail_absorbed_messages_owner", + "escape_fail_absorbed_messages_prey", + "primary_transfer_messages_owner", + "primary_transfer_messages_prey", + "secondary_transfer_messages_owner", + "secondary_transfer_messages_prey", + "digest_chance_messages_owner", + "digest_chance_messages_prey", + "absorb_chance_messages_owner", + "absorb_chance_messages_prey", "digest_messages_owner", "digest_messages_prey", "absorb_messages_owner", @@ -269,7 +370,7 @@ return //Someone dropping something (or being stripdigested) //Generic entered message - to_chat(owner,"[thing] slides into your [lowertext(name)].") + to_chat(owner,"[thing] slides into your [lowertext(name)].") //Sound w/ antispam flag setting if(vore_sound && !recent_sound) @@ -299,11 +400,11 @@ formatted_desc = replacetext(raw_desc, "%belly", lowertext(name)) //replace with this belly's name formatted_desc = replacetext(formatted_desc, "%pred", owner) //replace with this belly's owner formatted_desc = replacetext(formatted_desc, "%prey", M) //replace with whatever mob entered into this belly - to_chat(M, "[formatted_desc]") + to_chat(M, "[formatted_desc]") var/taste if(can_taste && (taste = M.get_taste_message(FALSE))) - to_chat(owner, "[M] tastes of [taste].") + to_chat(owner, "[M] tastes of [taste].") vore_fx(M) //Stop AI processing in bellies if(M.ai_holder) @@ -370,7 +471,7 @@ if(disable_hud) if(L?.hud_used?.hud_shown) - to_chat(L, "((Your pred has disabled huds in their belly. Turn off vore FX and hit F12 to get it back; or relax, and enjoy the serenity.))") + to_chat(L, "((Your pred has disabled huds in their belly. Turn off vore FX and hit F12 to get it back; or relax, and enjoy the serenity.))") L.toggle_hud_vis(TRUE) /obj/belly/proc/vore_preview(mob/living/L) @@ -602,7 +703,7 @@ formatted_message = replacetext(formatted_message, "%countprey", living_count) formatted_message = replacetext(formatted_message, "%count", contents.len) - return("[formatted_message]") + return("[formatted_message]") /obj/belly/proc/get_examine_msg_absorbed() if(!(contents.len) || !(examine_messages_absorbed.len) || !display_absorbed_examine) @@ -626,13 +727,13 @@ formatted_message = replacetext(formatted_message, "%prey", english_list(absorbed_victims)) formatted_message = replacetext(formatted_message, "%countprey", absorbed_count) - return("[formatted_message]") + return("[formatted_message]") // The next function gets the messages set on the belly, in human-readable format. // This is useful in customization boxes and such. The delimiter right now is \n\n so // in message boxes, this looks nice and is easily delimited. /obj/belly/proc/get_messages(type, delim = "\n\n") - ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") + ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") var/list/raw_messages switch(type) @@ -644,6 +745,56 @@ raw_messages = absorbed_struggle_messages_outside if("asmi") raw_messages = absorbed_struggle_messages_inside + if("escao") + raw_messages = escape_attempt_messages_owner + if("escap") + raw_messages = escape_attempt_messages_prey + if("esco") + raw_messages = escape_messages_owner + if("escp") + raw_messages = escape_messages_prey + if("escout") + raw_messages = escape_messages_outside + if("escio") + raw_messages = escape_item_messages_owner + if("escip") + raw_messages = escape_item_messages_prey + if("esciout") + raw_messages = escape_item_messages_outside + if("escfo") + raw_messages = escape_fail_messages_owner + if("escfp") + raw_messages = escape_fail_messages_prey + if("aescao") + raw_messages = escape_attempt_absorbed_messages_owner + if("aescap") + raw_messages = escape_attempt_absorbed_messages_prey + if("aesco") + raw_messages = escape_absorbed_messages_owner + if("aescp") + raw_messages = escape_absorbed_messages_prey + if("aescout") + raw_messages = escape_absorbed_messages_outside + if("aescfo") + raw_messages = escape_fail_absorbed_messages_owner + if("aescfp") + raw_messages = escape_fail_absorbed_messages_prey + if("trnspo") + raw_messages = primary_transfer_messages_owner + if("trnspp") + raw_messages = primary_transfer_messages_prey + if("trnsso") + raw_messages = secondary_transfer_messages_owner + if("trnssp") + raw_messages = secondary_transfer_messages_prey + if("stmodo") + raw_messages = digest_chance_messages_owner + if("stmodp") + raw_messages = digest_chance_messages_prey + if("stmoao") + raw_messages = absorb_chance_messages_owner + if("stmoap") + raw_messages = absorb_chance_messages_prey if("dmo") raw_messages = digest_messages_owner if("dmp") @@ -691,7 +842,7 @@ // replacement strings and linebreaks as delimiters (two \n\n by default). // They also sanitize the messages. /obj/belly/proc/set_messages(raw_text, type, delim = "\n\n") - ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") + ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") var/list/raw_list = splittext(html_encode(raw_text),delim) if(raw_list.len > 10) @@ -724,6 +875,56 @@ absorbed_struggle_messages_outside = raw_list if("asmi") absorbed_struggle_messages_inside = raw_list + if("escao") + escape_attempt_messages_owner = raw_list + if("escap") + escape_attempt_messages_prey = raw_list + if("esco") + escape_messages_owner = raw_list + if("escp") + escape_messages_prey = raw_list + if("escout") + escape_messages_outside = raw_list + if("escio") + escape_item_messages_owner = raw_list + if("escip") + escape_item_messages_prey = raw_list + if("esciout") + escape_item_messages_outside = raw_list + if("escfo") + escape_fail_messages_owner = raw_list + if("escfp") + escape_fail_messages_prey = raw_list + if("aescao") + escape_attempt_absorbed_messages_owner = raw_list + if("aescap") + escape_attempt_absorbed_messages_prey = raw_list + if("aesco") + escape_absorbed_messages_owner = raw_list + if("aescp") + escape_absorbed_messages_prey = raw_list + if("aescout") + escape_absorbed_messages_outside = raw_list + if("aescfo") + escape_fail_absorbed_messages_owner = raw_list + if("aescfp") + escape_fail_absorbed_messages_prey = raw_list + if("trnspo") + primary_transfer_messages_owner = raw_list + if("trnspp") + primary_transfer_messages_prey = raw_list + if("trnsso") + secondary_transfer_messages_owner = raw_list + if("trnssp") + secondary_transfer_messages_prey = raw_list + if("stmodo") + digest_chance_messages_owner = raw_list + if("stmodp") + digest_chance_messages_prey = raw_list + if("stmoao") + absorb_chance_messages_owner = raw_list + if("stmoap") + absorb_chance_messages_prey = raw_list if("dmo") digest_messages_owner = raw_list if("dmp") @@ -840,8 +1041,8 @@ GLOB.prey_absorbed_roundstat++ - to_chat(M, "[absorb_alert_prey]") - to_chat(owner, "[absorb_alert_owner]") + to_chat(M, "[absorb_alert_prey]") + to_chat(owner, "[absorb_alert_owner]") if(M.noisy) //Mute drained absorbee hunger if enabled. M.noisy = FALSE @@ -880,7 +1081,7 @@ formatted_abs_desc = replacetext(absorbed_desc, "%belly", lowertext(name)) //replace with this belly's name formatted_abs_desc = replacetext(formatted_abs_desc, "%pred", owner) //replace with this belly's owner formatted_abs_desc = replacetext(formatted_abs_desc, "%prey", M) //replace with whatever mob entered into this belly - to_chat(M, "[formatted_abs_desc]") + to_chat(M, "[formatted_abs_desc]") //Update owner owner.updateVRPanel() @@ -910,11 +1111,11 @@ M.absorbed = FALSE handle_absorb_langs(M, owner) - to_chat(M, "[unabsorb_alert_prey]") - to_chat(owner, "[unabsorb_alert_owner]") + to_chat(M, "[unabsorb_alert_prey]") + to_chat(owner, "[unabsorb_alert_owner]") if(desc) - to_chat(M, "[desc]") + to_chat(M, "[desc]") //Update owner owner.updateVRPanel() @@ -970,9 +1171,48 @@ R.setClickCooldown(50) + var/living_count = 0 + for(var/mob/living/L in contents) + living_count++ + + var/escape_attempt_owner_message = pick(escape_attempt_messages_owner) + var/escape_attempt_prey_message = pick(escape_attempt_messages_prey) + var/escape_fail_owner_message = pick(escape_fail_messages_owner) + var/escape_fail_prey_message = pick(escape_fail_messages_prey) + + escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%pred", owner) + escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%prey", R) + escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%belly", lowertext(name)) + escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%countprey", living_count) + escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%count", contents.len) + + escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%pred", owner) + escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%prey", R) + escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%belly", lowertext(name)) + escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%countprey", living_count) + escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%count", contents.len) + + escape_fail_owner_message = replacetext(escape_fail_owner_message, "%pred", owner) + escape_fail_owner_message = replacetext(escape_fail_owner_message, "%prey", R) + escape_fail_owner_message = replacetext(escape_fail_owner_message, "%belly", lowertext(name)) + escape_fail_owner_message = replacetext(escape_fail_owner_message, "%countprey", living_count) + escape_fail_owner_message = replacetext(escape_fail_owner_message, "%count", contents.len) + + escape_fail_prey_message = replacetext(escape_fail_prey_message, "%pred", owner) + escape_fail_prey_message = replacetext(escape_fail_prey_message, "%prey", R) + escape_fail_prey_message = replacetext(escape_fail_prey_message, "%belly", lowertext(name)) + escape_fail_prey_message = replacetext(escape_fail_prey_message, "%countprey", living_count) + escape_fail_prey_message = replacetext(escape_fail_prey_message, "%count", contents.len) + + escape_attempt_owner_message = "[escape_attempt_owner_message]" + escape_attempt_prey_message = "[escape_attempt_prey_message]" + escape_fail_owner_message = "[escape_fail_owner_message]" + escape_fail_prey_message = "[escape_fail_prey_message]" + if(owner.stat) //If owner is stat (dead, KO) we can actually escape - to_chat(R, "You attempt to climb out of \the [lowertext(name)]. (This will take around [escapetime/10] seconds.)") - to_chat(owner, "Someone is attempting to climb out of your [lowertext(name)]!") + escape_attempt_prey_message = replacetext(escape_attempt_prey_message, new/regex("^(]*)?>.*)()$", ""), "$1 (This will take around [escapetime/10] seconds.)$2") + to_chat(R, escape_attempt_prey_message) + to_chat(owner, escape_attempt_owner_message) if(do_after(R, escapetime, owner, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED)) if((owner.stat || escapable)) //Can still escape? @@ -985,17 +1225,13 @@ else if(R.loc != src) //Aren't even in the belly. Quietly fail. return else //Belly became inescapable or mob revived - to_chat(R,"Your attempt to escape [lowertext(name)] has failed!") - to_chat(owner,"The attempt to escape from your [lowertext(name)] has failed!") + to_chat(R, escape_fail_prey_message) + to_chat(owner, escape_fail_owner_message) return return var/struggle_outer_message = pick(struggle_messages_outside) var/struggle_user_message = pick(struggle_messages_inside) - var/living_count = 0 - for(var/mob/living/L in contents) - living_count++ - struggle_outer_message = replacetext(struggle_outer_message, "%pred", owner) struggle_outer_message = replacetext(struggle_outer_message, "%prey", R) struggle_outer_message = replacetext(struggle_outer_message, "%belly", lowertext(name)) @@ -1008,8 +1244,8 @@ struggle_user_message = replacetext(struggle_user_message, "%countprey", living_count) struggle_user_message = replacetext(struggle_user_message, "%count", contents.len) - struggle_outer_message = "[struggle_outer_message]" - struggle_user_message = "[struggle_user_message]" + struggle_outer_message = "[struggle_outer_message]" + struggle_user_message = "[struggle_user_message]" for(var/mob/M in hearers(4, owner)) M.show_message(struggle_outer_message, 2) // hearable @@ -1028,28 +1264,82 @@ if(escapable) //If the stomach has escapable enabled. if(prob(escapechance)) //Let's have it check to see if the prey escapes first. - to_chat(R, "You start to climb out of \the [lowertext(name)].") - to_chat(owner, "Someone is attempting to climb out of your [lowertext(name)]!") + to_chat(R, escape_attempt_prey_message) + to_chat(owner, escape_attempt_owner_message) if(do_after(R, escapetime)) if(escapable && C) + var/escape_item_owner_message = pick(escape_item_messages_owner) + var/escape_item_prey_message = pick(escape_item_messages_prey) + var/escape_item_outside_message = pick(escape_item_messages_outside) + + escape_item_owner_message = replacetext(escape_item_owner_message, "%pred", owner) + escape_item_owner_message = replacetext(escape_item_owner_message, "%prey", R) + escape_item_owner_message = replacetext(escape_item_owner_message, "%belly", lowertext(name)) + escape_item_owner_message = replacetext(escape_item_owner_message, "%countprey", living_count) + escape_item_owner_message = replacetext(escape_item_owner_message, "%count", contents.len) + escape_item_owner_message = replacetext(escape_item_owner_message, "%item", C) + + escape_item_prey_message = replacetext(escape_item_prey_message, "%pred", owner) + escape_item_prey_message = replacetext(escape_item_prey_message, "%prey", R) + escape_item_prey_message = replacetext(escape_item_prey_message, "%belly", lowertext(name)) + escape_item_prey_message = replacetext(escape_item_prey_message, "%countprey", living_count) + escape_item_prey_message = replacetext(escape_item_prey_message, "%count", contents.len) + escape_item_prey_message = replacetext(escape_item_prey_message, "%item", C) + + escape_item_outside_message = replacetext(escape_item_outside_message, "%pred", owner) + escape_item_outside_message = replacetext(escape_item_outside_message, "%prey", R) + escape_item_outside_message = replacetext(escape_item_outside_message, "%belly", lowertext(name)) + escape_item_outside_message = replacetext(escape_item_outside_message, "%countprey", living_count) + escape_item_outside_message = replacetext(escape_item_outside_message, "%count", contents.len) + escape_item_outside_message = replacetext(escape_item_outside_message, "%item", C) + + escape_item_owner_message = "[escape_item_owner_message]" + escape_item_prey_message = "[escape_item_prey_message]" + escape_item_outside_message = "[escape_item_outside_message]" + release_specific_contents(C) - to_chat(R,"Your struggles successfully cause [owner] to squeeze your container out of their \the [lowertext(name)].") - to_chat(owner,"[C] suddenly slips out of your [lowertext(name)]!") + to_chat(R, escape_item_prey_message) + to_chat(owner, escape_item_owner_message) for(var/mob/M in hearers(4, owner)) - M.show_message("[C] suddenly slips out of [owner]'s [lowertext(name)]!", 2) + M.show_message(escape_item_outside_message, 2) return if(escapable && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled? + var/escape_owner_message = pick(escape_messages_owner) + var/escape_prey_message = pick(escape_messages_prey) + var/escape_outside_message = pick(escape_messages_outside) + + escape_owner_message = replacetext(escape_owner_message, "%pred", owner) + escape_owner_message = replacetext(escape_owner_message, "%prey", R) + escape_owner_message = replacetext(escape_owner_message, "%belly", lowertext(name)) + escape_owner_message = replacetext(escape_owner_message, "%countprey", living_count) + escape_owner_message = replacetext(escape_owner_message, "%count", contents.len) + + escape_prey_message = replacetext(escape_prey_message, "%pred", owner) + escape_prey_message = replacetext(escape_prey_message, "%prey", R) + escape_prey_message = replacetext(escape_prey_message, "%belly", lowertext(name)) + escape_prey_message = replacetext(escape_prey_message, "%countprey", living_count) + escape_prey_message = replacetext(escape_prey_message, "%count", contents.len) + + escape_outside_message = replacetext(escape_outside_message, "%pred", owner) + escape_outside_message = replacetext(escape_outside_message, "%prey", R) + escape_outside_message = replacetext(escape_outside_message, "%belly", lowertext(name)) + escape_outside_message = replacetext(escape_outside_message, "%countprey", living_count) + escape_outside_message = replacetext(escape_outside_message, "%count", contents.len) + + escape_owner_message = "[escape_owner_message]" + escape_prey_message = "[escape_prey_message]" + escape_outside_message = "[escape_outside_message]" release_specific_contents(R) - to_chat(R,"You climb out of \the [lowertext(name)].") - to_chat(owner,"[R] climbs out of your [lowertext(name)]!") + to_chat(R, escape_prey_message) + to_chat(owner, escape_owner_message) for(var/mob/M in hearers(4, owner)) - M.show_message("[R] climbs out of [owner]'s [lowertext(name)]!", 2) + M.show_message(escape_outside_message, 2) return else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. return else //Belly became inescapable. - to_chat(R,"Your attempt to escape [lowertext(name)] has failed!") - to_chat(owner,"The attempt to escape from your [lowertext(name)] has failed!") + to_chat(R, escape_fail_prey_message) + to_chat(owner, escape_fail_owner_message) return else if(prob(transferchance) && transferlocation) //Next, let's have it see if they end up getting into an even bigger mess then when they started. @@ -1060,13 +1350,32 @@ break if(!dest_belly) - to_chat(owner, "Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.") + to_chat(owner, "Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.") transferchance = 0 transferlocation = null return + var/primary_transfer_owner_message = pick(primary_transfer_messages_owner) + var/primary_transfer_prey_message = pick(primary_transfer_messages_prey) - to_chat(R, "Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation]!") - to_chat(owner, "Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!") + primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%pred", owner) + primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%prey", R) + primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%belly", lowertext(name)) + primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%countprey", living_count) + primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%count", contents.len) + primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%dest", transferlocation) + + primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%pred", owner) + primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%prey", R) + primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%belly", lowertext(name)) + primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%countprey", living_count) + primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%count", contents.len) + primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%dest", transferlocation) + + primary_transfer_owner_message = "[primary_transfer_owner_message]" + primary_transfer_prey_message = "[primary_transfer_prey_message]" + + to_chat(R, primary_transfer_prey_message) + to_chat(owner, primary_transfer_owner_message) if(C) transfer_contents(C, dest_belly) return @@ -1081,13 +1390,33 @@ break if(!dest_belly) - to_chat(owner, "Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.") + to_chat(owner, "Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.") transferchance_secondary = 0 transferlocation_secondary = null return - to_chat(R, "Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation_secondary]!") - to_chat(owner, "Someone slid into your [transferlocation_secondary] due to their struggling inside your [lowertext(name)]!") + var/secondary_transfer_owner_message = pick(secondary_transfer_messages_owner) + var/secondary_transfer_prey_message = pick(secondary_transfer_messages_prey) + + secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%pred", owner) + secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%prey", R) + secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%belly", lowertext(name)) + secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%countprey", living_count) + secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%count", contents.len) + secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%dest", transferlocation_secondary) + + secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%pred", owner) + secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%prey", R) + secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%belly", lowertext(name)) + secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%countprey", living_count) + secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%count", contents.len) + secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%dest", transferlocation_secondary) + + secondary_transfer_owner_message = "[secondary_transfer_owner_message]" + secondary_transfer_prey_message = "[secondary_transfer_prey_message]" + + to_chat(R, secondary_transfer_prey_message) + to_chat(owner, secondary_transfer_owner_message) if(C) transfer_contents(C, dest_belly) return @@ -1095,20 +1424,56 @@ return else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance. - to_chat(R, "In response to your struggling, \the [lowertext(name)] begins to cling more tightly...") - to_chat(owner, "You feel your [lowertext(name)] start to cling onto its contents...") + var/absorb_chance_owner_message = pick(absorb_chance_messages_owner) + var/absorb_chance_prey_message = pick(absorb_chance_messages_prey) + + absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%pred", owner) + absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%prey", R) + absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%belly", lowertext(name)) + absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%countprey", living_count) + absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%count", contents.len) + + absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%pred", owner) + absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%prey", R) + absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%belly", lowertext(name)) + absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%countprey", living_count) + absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%count", contents.len) + + absorb_chance_owner_message = "[absorb_chance_owner_message]" + absorb_chance_prey_message = "[absorb_chance_prey_message]" + + to_chat(R, absorb_chance_prey_message) + to_chat(owner, absorb_chance_owner_message) digest_mode = DM_ABSORB return else if(prob(digestchance) && digest_mode != DM_DIGEST) //Finally, let's see if it should run the digest chance. - to_chat(R, "In response to your struggling, \the [lowertext(name)] begins to get more active...") - to_chat(owner, "You feel your [lowertext(name)] beginning to become active!") + var/digest_chance_owner_message = pick(digest_chance_messages_owner) + var/digest_chance_prey_message = pick(digest_chance_messages_prey) + + digest_chance_owner_message = replacetext(digest_chance_owner_message, "%pred", owner) + digest_chance_owner_message = replacetext(digest_chance_owner_message, "%prey", R) + digest_chance_owner_message = replacetext(digest_chance_owner_message, "%belly", lowertext(name)) + digest_chance_owner_message = replacetext(digest_chance_owner_message, "%countprey", living_count) + digest_chance_owner_message = replacetext(digest_chance_owner_message, "%count", contents.len) + + digest_chance_prey_message = replacetext(digest_chance_prey_message, "%pred", owner) + digest_chance_prey_message = replacetext(digest_chance_prey_message, "%prey", R) + digest_chance_prey_message = replacetext(digest_chance_prey_message, "%belly", lowertext(name)) + digest_chance_prey_message = replacetext(digest_chance_prey_message, "%countprey", living_count) + digest_chance_prey_message = replacetext(digest_chance_prey_message, "%count", contents.len) + + digest_chance_owner_message = "[digest_chance_owner_message]" + digest_chance_prey_message = "[digest_chance_prey_message]" + + to_chat(R, digest_chance_prey_message) + to_chat(owner, digest_chance_owner_message) digest_mode = DM_DIGEST return else //Nothing interesting happened. to_chat(R, struggle_user_message) - to_chat(owner, "Your prey appears to be unable to make any progress in escaping your [lowertext(name)].") + to_chat(owner, "Your prey appears to be unable to make any progress in escaping your [lowertext(name)].") return to_chat(R, struggle_user_message) @@ -1136,8 +1501,8 @@ struggle_user_message = replacetext(struggle_user_message, "%belly", lowertext(name)) struggle_user_message = replacetext(struggle_user_message, "%countprey", absorbed_count) - struggle_outer_message = "[struggle_outer_message]" - struggle_user_message = "[struggle_user_message]" + struggle_outer_message = "[struggle_outer_message]" + struggle_user_message = "[struggle_user_message]" for(var/mob/M in hearers(4, owner)) M.show_message(struggle_outer_message, 2) // hearable @@ -1157,21 +1522,90 @@ //absorb resists if(escapable || owner.stat) //If the stomach has escapable enabled or the owner is dead/unconscious if(prob(escapechance) || owner.stat) //Let's have it check to see if the prey's escape attempt starts. - to_chat(R, "You try to force yourself out of \the [lowertext(name)].") - to_chat(owner, "Someone is attempting to free themselves from your [lowertext(name)]!") + + + var/living_count = 0 + for(var/mob/living/L in contents) + living_count++ + + var/escape_attempt_absorbed_owner_message = pick(escape_attempt_absorbed_messages_owner) + var/escape_attempt_absorbed_prey_message = pick(escape_attempt_absorbed_messages_prey) + + escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%pred", owner) + escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%prey", R) + escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%belly", lowertext(name)) + escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%countprey", living_count) + escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%count", contents.len) + + escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%pred", owner) + escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%prey", R) + escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%belly", lowertext(name)) + escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%countprey", living_count) + escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%count", contents.len) + + escape_attempt_absorbed_owner_message = "[escape_attempt_absorbed_owner_message]" + escape_attempt_absorbed_prey_message = "[escape_attempt_absorbed_prey_message]" + + to_chat(R, escape_attempt_absorbed_prey_message) + to_chat(owner, escape_attempt_absorbed_owner_message) if(do_after(R, escapetime)) if((escapable || owner.stat) && (R.loc == src) && prob(escapechance_absorbed)) //Does the escape attempt succeed? + var/escape_absorbed_owner_message = pick(escape_absorbed_messages_owner) + var/escape_absorbed_prey_message = pick(escape_absorbed_messages_prey) + var/escape_absorbed_outside_message = pick(escape_absorbed_messages_outside) + + escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%pred", owner) + escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%prey", R) + escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%belly", lowertext(name)) + escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%countprey", living_count) + escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%count", contents.len) + + escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%pred", owner) + escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%prey", R) + escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%belly", lowertext(name)) + escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%countprey", living_count) + escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%count", contents.len) + + escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%pred", owner) + escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%prey", R) + escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%belly", lowertext(name)) + escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%countprey", living_count) + escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%count", contents.len) + + escape_absorbed_owner_message = "[escape_absorbed_owner_message]" + escape_absorbed_prey_message = "[escape_absorbed_prey_message]" + escape_absorbed_outside_message = "[escape_absorbed_outside_message]" + release_specific_contents(R) - to_chat(R,"You manage to free yourself from \the [lowertext(name)].") - to_chat(owner,"[R] forces themselves free of your [lowertext(name)]!") + to_chat(R, escape_absorbed_prey_message) + to_chat(owner, escape_absorbed_owner_message) for(var/mob/M in hearers(4, owner)) - M.show_message("[R] climbs out of [owner]'s [lowertext(name)]!", 2) + M.show_message(escape_absorbed_outside_message, 2) return else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. return else //Belly became inescapable or you failed your roll. - to_chat(R,"Before you manage to reach freedom, you feel yourself getting dragged back into \the [lowertext(name)]!") - to_chat(owner,"The attempt to escape from your [lowertext(name)] has failed!") + + var/escape_fail_absorbed_owner_message = pick(escape_fail_absorbed_messages_owner) + var/escape_fail_absorbed_prey_message = pick(escape_fail_absorbed_messages_prey) + + escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%pred", owner) + escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%prey", R) + escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%belly", lowertext(name)) + escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%countprey", living_count) + escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%count", contents.len) + + escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%pred", owner) + escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%prey", R) + escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%belly", lowertext(name)) + escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%countprey", living_count) + escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%count", contents.len) + + escape_fail_absorbed_owner_message = "[escape_fail_absorbed_owner_message]" + escape_fail_absorbed_prey_message = "[escape_fail_absorbed_prey_message]" + + to_chat(R, escape_fail_absorbed_prey_message) + to_chat(owner, escape_fail_absorbed_owner_message) return to_chat(R, struggle_user_message) @@ -1255,6 +1689,7 @@ dupe.digestchance = digestchance dupe.absorbchance = absorbchance dupe.escapechance = escapechance + dupe.escapechance_absorbed = escapechance_absorbed dupe.transferchance = transferchance dupe.transferchance_secondary = transferchance_secondary dupe.transferlocation = transferlocation @@ -1308,6 +1743,131 @@ for(var/I in absorbed_struggle_messages_inside) dupe.absorbed_struggle_messages_inside += I + //escape_attempt_messages_owner - strings + dupe.escape_attempt_messages_owner.Cut() + for(var/I in escape_attempt_messages_owner) + dupe.escape_attempt_messages_owner += I + + //escape_attempt_messages_prey - strings + dupe.escape_attempt_messages_prey.Cut() + for(var/I in escape_attempt_messages_prey) + dupe.escape_attempt_messages_prey += I + + //escape_messages_owner - strings + dupe.escape_messages_owner.Cut() + for(var/I in escape_messages_owner) + dupe.escape_messages_owner += I + + //escape_messages_prey - strings + dupe.escape_messages_prey.Cut() + for(var/I in escape_messages_prey) + dupe.escape_messages_prey += I + + //escape_messages_outside - strings + dupe.escape_messages_outside.Cut() + for(var/I in escape_messages_outside) + dupe.escape_messages_outside += I + + //escape_item_messages_owner - strings + dupe.escape_item_messages_owner.Cut() + for(var/I in escape_item_messages_owner) + dupe.escape_item_messages_owner += I + + //escape_item_messages_prey - strings + dupe.escape_item_messages_prey.Cut() + for(var/I in escape_item_messages_prey) + dupe.escape_item_messages_prey += I + + //escape_item_messages_outside - strings + dupe.escape_item_messages_outside.Cut() + for(var/I in escape_item_messages_outside) + dupe.escape_item_messages_outside += I + + //escape_fail_messages_owner - strings + dupe.escape_fail_messages_owner.Cut() + for(var/I in escape_fail_messages_owner) + dupe.escape_fail_messages_owner += I + + //escape_fail_messages_prey - strings + dupe.escape_fail_messages_prey.Cut() + for(var/I in escape_fail_messages_prey) + dupe.escape_fail_messages_prey += I + + //escape_attempt_absorbed_messages_owner - strings + dupe.escape_attempt_absorbed_messages_owner.Cut() + for(var/I in escape_attempt_absorbed_messages_owner) + dupe.escape_attempt_absorbed_messages_owner += I + + //escape_attempt_absorbed_messages_prey - strings + dupe.escape_attempt_absorbed_messages_prey.Cut() + for(var/I in escape_attempt_absorbed_messages_prey) + dupe.escape_attempt_absorbed_messages_prey += I + + //escape_absorbed_messages_owner - strings + dupe.escape_absorbed_messages_owner.Cut() + for(var/I in escape_absorbed_messages_owner) + dupe.escape_absorbed_messages_owner += I + + //escape_absorbed_messages_prey - strings + dupe.escape_absorbed_messages_prey.Cut() + for(var/I in escape_absorbed_messages_prey) + dupe.escape_absorbed_messages_prey += I + + //escape_absorbed_messages_outside - strings + dupe.escape_absorbed_messages_outside.Cut() + for(var/I in escape_absorbed_messages_outside) + dupe.escape_absorbed_messages_outside += I + + //escape_fail_absorbed_messages_owner - strings + dupe.escape_fail_absorbed_messages_owner.Cut() + for(var/I in escape_fail_absorbed_messages_owner) + dupe.escape_fail_absorbed_messages_owner += I + + //escape_fail_absorbed_messages_prey - strings + dupe.escape_fail_absorbed_messages_prey.Cut() + for(var/I in escape_fail_absorbed_messages_prey) + dupe.escape_fail_absorbed_messages_prey += I + + //primary_transfer_messages_owner - strings + dupe.primary_transfer_messages_owner.Cut() + for(var/I in primary_transfer_messages_owner) + dupe.primary_transfer_messages_owner += I + + //primary_transfer_messages_prey - strings + dupe.primary_transfer_messages_prey.Cut() + for(var/I in primary_transfer_messages_prey) + dupe.primary_transfer_messages_prey += I + + //secondary_transfer_messages_owner - strings + dupe.secondary_transfer_messages_owner.Cut() + for(var/I in secondary_transfer_messages_owner) + dupe.secondary_transfer_messages_owner += I + + //secondary_transfer_messages_prey - strings + dupe.secondary_transfer_messages_prey.Cut() + for(var/I in secondary_transfer_messages_prey) + dupe.secondary_transfer_messages_prey += I + + //digest_chance_messages_owner - strings + dupe.digest_chance_messages_owner.Cut() + for(var/I in digest_chance_messages_owner) + dupe.digest_chance_messages_owner += I + + //digest_chance_messages_prey - strings + dupe.digest_chance_messages_prey.Cut() + for(var/I in digest_chance_messages_prey) + dupe.digest_chance_messages_prey += I + + //absorb_chance_messages_owner - strings + dupe.absorb_chance_messages_owner.Cut() + for(var/I in absorb_chance_messages_owner) + dupe.absorb_chance_messages_owner += I + + //absorb_chance_messages_prey - strings + dupe.absorb_chance_messages_prey.Cut() + for(var/I in absorb_chance_messages_prey) + dupe.absorb_chance_messages_prey += I + //digest_messages_owner - strings dupe.digest_messages_owner.Cut() for(var/I in digest_messages_owner) diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm index ca8921dd87..e7548f6b89 100644 --- a/code/modules/vore/eating/bellymodes_vr.dm +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -125,7 +125,7 @@ formatted_message = replacetext(formatted_message, "%prey", M) formatted_message = replacetext(formatted_message, "%countprey", absorbed_count) if(formatted_message) - to_chat(M, "[formatted_message]") + to_chat(M, "[formatted_message]") else if (digest_mode == DM_SELECT) var/datum/digest_mode/selective/DM_S = GLOB.digest_modes[DM_SELECT] @@ -141,7 +141,7 @@ formatted_message = replacetext(formatted_message, "%countprey", living_count) formatted_message = replacetext(formatted_message, "%count", contents.len) if(formatted_message) - to_chat(M, "[formatted_message]") + to_chat(M, "[formatted_message]") if(to_update) updateVRPanels() @@ -280,8 +280,8 @@ digest_alert_prey = replacetext(digest_alert_prey, "%count", contents.len) //Send messages - to_chat(owner, "[digest_alert_owner]") - to_chat(M, "[digest_alert_prey]") + to_chat(owner, "[digest_alert_owner]") + to_chat(M, "[digest_alert_prey]") if(M.ckey) GLOB.prey_digested_roundstat++ diff --git a/code/modules/vore/eating/exportpanel_vr.dm b/code/modules/vore/eating/exportpanel_vr.dm index 835fbcd03c..97aec1653c 100644 --- a/code/modules/vore/eating/exportpanel_vr.dm +++ b/code/modules/vore/eating/exportpanel_vr.dm @@ -69,6 +69,106 @@ for(var/msg in B.absorbed_struggle_messages_inside) belly_data["absorbed_struggle_messages_inside"] += msg + belly_data["escape_attempt_messages_owner"] = list() + for(var/msg in B.escape_attempt_messages_owner) + belly_data["escape_attempt_messages_owner"] += msg + + belly_data["escape_attempt_messages_prey"] = list() + for(var/msg in B.escape_attempt_messages_prey) + belly_data["escape_attempt_messages_prey"] += msg + + belly_data["escape_messages_owner"] = list() + for(var/msg in B.escape_messages_owner) + belly_data["escape_messages_owner"] += msg + + belly_data["escape_messages_prey"] = list() + for(var/msg in B.escape_messages_prey) + belly_data["escape_messages_prey"] += msg + + belly_data["escape_messages_outside"] = list() + for(var/msg in B.escape_messages_outside) + belly_data["escape_messages_outside"] += msg + + belly_data["escape_item_messages_owner"] = list() + for(var/msg in B.escape_item_messages_owner) + belly_data["escape_item_messages_owner"] += msg + + belly_data["escape_item_messages_prey"] = list() + for(var/msg in B.escape_item_messages_prey) + belly_data["escape_item_messages_prey"] += msg + + belly_data["escape_item_messages_outside"] = list() + for(var/msg in B.escape_item_messages_outside) + belly_data["escape_item_messages_outside"] += msg + + belly_data["escape_fail_messages_owner"] = list() + for(var/msg in B.escape_fail_messages_owner) + belly_data["escape_fail_messages_owner"] += msg + + belly_data["escape_fail_messages_prey"] = list() + for(var/msg in B.escape_fail_messages_prey) + belly_data["escape_fail_messages_prey"] += msg + + belly_data["escape_attempt_absorbed_messages_owner"] = list() + for(var/msg in B.escape_attempt_absorbed_messages_owner) + belly_data["escape_attempt_absorbed_messages_owner"] += msg + + belly_data["escape_attempt_absorbed_messages_prey"] = list() + for(var/msg in B.escape_attempt_absorbed_messages_prey) + belly_data["escape_attempt_absorbed_messages_prey"] += msg + + belly_data["escape_absorbed_messages_owner"] = list() + for(var/msg in B.escape_absorbed_messages_owner) + belly_data["escape_absorbed_messages_owner"] += msg + + belly_data["escape_absorbed_messages_prey"] = list() + for(var/msg in B.escape_absorbed_messages_prey) + belly_data["escape_absorbed_messages_prey"] += msg + + belly_data["escape_absorbed_messages_outside"] = list() + for(var/msg in B.escape_absorbed_messages_outside) + belly_data["escape_absorbed_messages_outside"] += msg + + belly_data["escape_fail_absorbed_messages_owner"] = list() + for(var/msg in B.escape_fail_absorbed_messages_owner) + belly_data["escape_fail_absorbed_messages_owner"] += msg + + belly_data["escape_fail_absorbed_messages_prey"] = list() + for(var/msg in B.escape_fail_absorbed_messages_prey) + belly_data["escape_fail_absorbed_messages_prey"] += msg + + belly_data["primary_transfer_messages_owner"] = list() + for(var/msg in B.primary_transfer_messages_owner) + belly_data["primary_transfer_messages_owner"] += msg + + belly_data["primary_transfer_messages_prey"] = list() + for(var/msg in B.primary_transfer_messages_prey) + belly_data["primary_transfer_messages_prey"] += msg + + belly_data["secondary_transfer_messages_owner"] = list() + for(var/msg in B.secondary_transfer_messages_owner) + belly_data["secondary_transfer_messages_owner"] += msg + + belly_data["secondary_transfer_messages_prey"] = list() + for(var/msg in B.secondary_transfer_messages_prey) + belly_data["secondary_transfer_messages_prey"] += msg + + belly_data["digest_chance_messages_owner"] = list() + for(var/msg in B.digest_chance_messages_owner) + belly_data["digest_chance_messages_owner"] += msg + + belly_data["digest_chance_messages_prey"] = list() + for(var/msg in B.digest_chance_messages_prey) + belly_data["digest_chance_messages_prey"] += msg + + belly_data["absorb_chance_messages_owner"] = list() + for(var/msg in B.absorb_chance_messages_owner) + belly_data["absorb_chance_messages_owner"] += msg + + belly_data["absorb_chance_messages_prey"] = list() + for(var/msg in B.absorb_chance_messages_prey) + belly_data["absorb_chance_messages_prey"] += msg + belly_data["digest_messages_owner"] = list() for(var/msg in B.digest_messages_owner) belly_data["digest_messages_owner"] += msg @@ -188,6 +288,7 @@ belly_data["escapable"] = B.escapable belly_data["escapechance"] = B.escapechance + belly_data["escapechance_absorbed"] = B.escapechance_absorbed belly_data["escapetime"] = B.escapetime belly_data["transferchance"] = B.transferchance diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 4914633fa1..36bb6be2f7 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -109,7 +109,7 @@ ///// If user clicked on their grabbed target else if((src == G.affecting) && (attacker.a_intent == I_GRAB) && (attacker.zone_sel.selecting == BP_TORSO) && (is_vore_predator(G.affecting))) if(!G.affecting.feeding) - to_chat(user, "[G.affecting] isn't willing to be fed.") + to_chat(user, "[G.affecting] isn't willing to be fed.") log_and_message_admins("[key_name_admin(src)] attempted to feed themselves to [key_name_admin(G.affecting)] against their prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])") return FALSE @@ -122,11 +122,11 @@ ///// If user clicked on anyone else but their grabbed target else if((src != G.affecting) && (src != G.assailant) && (is_vore_predator(src))) if(!feeding) - to_chat(user, "[src] isn't willing to be fed.") + to_chat(user, "[src] isn't willing to be fed.") log_and_message_admins("[key_name_admin(attacker)] attempted to feed [key_name_admin(G.affecting)] to [key_name_admin(src)] against predator's prefs ([src ? ADMIN_JMP(src) : "null"])") return FALSE if(!(G.affecting.devourable)) - to_chat(user, "[G.affecting] isn't able to be devoured.") + to_chat(user, "[G.affecting] isn't able to be devoured.") log_and_message_admins("[key_name_admin(attacker)] attempted to feed [key_name_admin(G.affecting)] to [key_name_admin(src)] against prey's prefs ([G.affecting ? ADMIN_JMP(G.affecting) : "null"])") return FALSE if(attacker.feed_grabbed_to_other(attacker, G.affecting, src)) @@ -364,7 +364,7 @@ setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - visible_message("[src] licks [tasted]!","You lick [tasted]. They taste rather like [tasted.get_taste_message()].","Slurp!") + visible_message("[src] licks [tasted]!","You lick [tasted]. They taste rather like [tasted.get_taste_message()].","Slurp!") /mob/living/proc/get_taste_message(allow_generic = 1) @@ -403,7 +403,7 @@ return setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - visible_message("[src] smells [smelled]!","You smell [smelled]. They smell like [smelled.get_smell_message()].","Sniff!") + visible_message("[src] smells [smelled]!","You smell [smelled]. They smell like [smelled.get_smell_message()].","Sniff!") /mob/living/proc/get_smell_message(allow_generic = 1) if(!vore_smell && !allow_generic) @@ -546,11 +546,11 @@ return FALSE if(!prey.devourable) - to_chat(user, "They aren't able to be devoured.") + to_chat(user, "They aren't able to be devoured.") log_and_message_admins("[key_name_admin(src)] attempted to devour [key_name_admin(prey)] against their prefs ([prey ? ADMIN_JMP(prey) : "null"])") return FALSE if(prey.absorbed || pred.absorbed) - to_chat(user, "They aren't aren't in a state to be devoured.") + to_chat(user, "They aren't aren't in a state to be devoured.") return FALSE //Determining vore attempt privacy @@ -568,17 +568,17 @@ // Slipnoms from chompstation downstream, credit to cadyn for the original PR. // Prepare messages if(prey.is_slipping) - attempt_msg = "It seems like [prey] is about to slide into [pred]'s [lowertext(belly.name)]!" - success_msg = "[prey] suddenly slides into [pred]'s [lowertext(belly.name)]!" + attempt_msg = "It seems like [prey] is about to slide into [pred]'s [lowertext(belly.name)]!" + success_msg = "[prey] suddenly slides into [pred]'s [lowertext(belly.name)]!" else if(pred.is_slipping) - attempt_msg = "It seems like [prey] is gonna end up inside [pred]'s [lowertext(belly.name)] as [pred] comes sliding over!" - success_msg = "[prey] suddenly slips inside of [pred]'s [lowertext(belly.name)] as [pred] slides into them!" + attempt_msg = "It seems like [prey] is gonna end up inside [pred]'s [lowertext(belly.name)] as [pred] comes sliding over!" + success_msg = "[prey] suddenly slips inside of [pred]'s [lowertext(belly.name)] as [pred] slides into them!" else if(user == pred) //Feeding someone to yourself - attempt_msg = "[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" - success_msg = "[pred] manages to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" + attempt_msg = "[pred] is attempting to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" + success_msg = "[pred] manages to [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" else //Feeding someone to another person - attempt_msg = "[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" - success_msg = "[user] manages to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" + attempt_msg = "[user] is attempting to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" + success_msg = "[user] manages to make [pred] [lowertext(belly.vore_verb)] [prey] into their [lowertext(belly.name)]!" // Announce that we start the attempt! @@ -1116,50 +1116,126 @@ for(var/belly in vore_organs) if(isbelly(belly)) var/obj/belly/B = belly - to_chat(src, "Belly name: [B.name]") - to_chat(src, "Belly desc: [B.desc]") - to_chat(src, "Belly absorbed desc: [B.absorbed_desc]") - to_chat(src, "Vore verb: [B.vore_verb]") - to_chat(src, "Struggle messages (outside):") + to_chat(src, "Belly name: [B.name]") + to_chat(src, "Belly desc: [B.desc]") + to_chat(src, "Belly absorbed desc: [B.absorbed_desc]") + to_chat(src, "Vore verb: [B.vore_verb]") + to_chat(src, "Struggle messages (outside):") for(var/msg in B.struggle_messages_outside) - to_chat(src, "[msg]") - to_chat(src, "Struggle messages (inside):") + to_chat(src, "[msg]") + to_chat(src, "Struggle messages (inside):") for(var/msg in B.struggle_messages_inside) - to_chat(src, "[msg]") - to_chat(src, "Absorbed struggle messages (outside):") + to_chat(src, "[msg]") + to_chat(src, "Absorbed struggle messages (outside):") for(var/msg in B.absorbed_struggle_messages_outside) - to_chat(src, "[msg]") - to_chat(src, "Absorbed struggle messages (inside):") + to_chat(src, "[msg]") + to_chat(src, "Absorbed struggle messages (inside):") for(var/msg in B.absorbed_struggle_messages_inside) - to_chat(src, "[msg]") - to_chat(src, "Digest messages (owner):") + to_chat(src, "[msg]") + to_chat(src, "Escape attempt messages (owner):") + for(var/msg in B.escape_attempt_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Escape attempt messages (prey):") + for(var/msg in B.escape_attempt_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Escape messages (owner):") + for(var/msg in B.escape_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Escape messages (prey):") + for(var/msg in B.escape_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Escape messages (outside):") + for(var/msg in B.escape_messages_outside) + to_chat(src, "[msg]") + to_chat(src, "Escape item messages (owner):") + for(var/msg in B.escape_item_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Escape item messages (prey):") + for(var/msg in B.escape_item_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Escape item messages (outside):") + for(var/msg in B.escape_item_messages_outside) + to_chat(src, "[msg]") + to_chat(src, "Escape fail messages (owner):") + for(var/msg in B.escape_fail_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Escape fail messages (prey):") + for(var/msg in B.escape_fail_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape attempt messages (owner):") + for(var/msg in B.escape_attempt_absorbed_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape attempt messages (prey):") + for(var/msg in B.escape_attempt_absorbed_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape messages (owner):") + for(var/msg in B.escape_absorbed_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape messages (prey):") + for(var/msg in B.escape_absorbed_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape messages (outside):") + for(var/msg in B.escape_absorbed_messages_outside) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape fail messages (owner):") + for(var/msg in B.escape_fail_absorbed_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Absorbed escape fail messages (prey):") + for(var/msg in B.escape_fail_absorbed_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Primary transfer messages (owner):") + for(var/msg in B.primary_transfer_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Primary transfer messages (prey):") + for(var/msg in B.primary_transfer_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Secondary transfer messages (owner):") + for(var/msg in B.secondary_transfer_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Secondary transfer messages (prey):") + for(var/msg in B.secondary_transfer_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Digest chance messages (owner):") + for(var/msg in B.digest_chance_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Digest chance messages (prey):") + for(var/msg in B.digest_chance_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Absorb chance messages (owner):") + for(var/msg in B.absorb_chance_messages_owner) + to_chat(src, "[msg]") + to_chat(src, "Absorb chance messages (prey):") + for(var/msg in B.absorb_chance_messages_prey) + to_chat(src, "[msg]") + to_chat(src, "Digest messages (owner):") for(var/msg in B.digest_messages_owner) - to_chat(src, "[msg]") - to_chat(src, "Digest messages (prey):") + to_chat(src, "[msg]") + to_chat(src, "Digest messages (prey):") for(var/msg in B.digest_messages_prey) - to_chat(src, "[msg]") - to_chat(src, "Absorb messages:") + to_chat(src, "[msg]") + to_chat(src, "Absorb messages (owner):") for(var/msg in B.absorb_messages_owner) - to_chat(src, "[msg]") - to_chat(src, "Absorb messages (prey):") + to_chat(src, "[msg]") + to_chat(src, "Absorb messages (prey):") for(var/msg in B.absorb_messages_prey) - to_chat(src, "[msg]") - to_chat(src, "Unabsorb messages:") + to_chat(src, "[msg]") + to_chat(src, "Unabsorb messages (owner):") for(var/msg in B.unabsorb_messages_owner) - to_chat(src, "[msg]") - to_chat(src, "Unabsorb messages (prey):") + to_chat(src, "[msg]") + to_chat(src, "Unabsorb messages (prey):") for(var/msg in B.unabsorb_messages_prey) - to_chat(src, "[msg]") - to_chat(src, "Examine messages:") + to_chat(src, "[msg]") + to_chat(src, "Examine messages (when full):") for(var/msg in B.examine_messages) - to_chat(src, "[msg]") + to_chat(src, "[msg]") + to_chat(src, "Examine messages (with absorbed victims):") for(var/msg in B.examine_messages_absorbed) - to_chat(src, "[msg]") - to_chat(src, "Emote lists:") + to_chat(src, "[msg]") + to_chat(src, "Emote lists:") for(var/EL in B.emote_lists) - to_chat(src, "[EL]:") + to_chat(src, "[EL]:") for(var/msg in B.emote_lists[EL]) - to_chat(src, "[msg]") + to_chat(src, "[msg]") /** * Small helper component to manage the vore panel HUD icon diff --git a/code/modules/vore/eating/silicon_vr.dm b/code/modules/vore/eating/silicon_vr.dm index 52a450a58c..e43b736f0e 100644 --- a/code/modules/vore/eating/silicon_vr.dm +++ b/code/modules/vore/eating/silicon_vr.dm @@ -25,7 +25,7 @@ bellied = prey prey.forceMove(src) visible_message("[src] entirely engulfs [prey] in hardlight holograms!") - to_chat(usr, "You completely engulf [prey] in hardlight holograms!") //Can't be part of the above, because the above is from the hologram. + to_chat(usr, "You completely engulf [prey] in hardlight holograms!") //Can't be part of the above, because the above is from the hologram. desc = "[initial(desc)] It seems to have hardlight mode enabled and someone inside." pass_flags = 0 @@ -52,7 +52,7 @@ // Wrong state if (!eyeobj || !holo) - to_chat(usr, "You can only use this when holo-projecting!") + to_chat(usr, "You can only use this when holo-projecting!") return //Holopads have this 'masters' list where the keys are AI names and the values are the hologram effects @@ -74,11 +74,11 @@ return //Probably cancelled if(!istype(prey)) - to_chat(usr, "Invalid mob choice!") + to_chat(usr, "Invalid mob choice!") return hologram.visible_message("[hologram] starts engulfing [prey] in hardlight holograms!") - to_chat(src, "You begin engulfing [prey] in hardlight holograms.") //Can't be part of the above, because the above is from the hologram. + to_chat(src, "You begin engulfing [prey] in hardlight holograms.") //Can't be part of the above, because the above is from the hologram. if(do_after(user=eyeobj,delay=50,target=prey,needhand=0) && holo && hologram && !hologram.bellied) //Didn't move and still projecting and effect exists and no other bellied people hologram.get_prey(prey) diff --git a/code/modules/vore/eating/stumblevore_vr.dm b/code/modules/vore/eating/stumblevore_vr.dm index cdaae1d5df..a979c210a8 100644 --- a/code/modules/vore/eating/stumblevore_vr.dm +++ b/code/modules/vore/eating/stumblevore_vr.dm @@ -32,13 +32,13 @@ M.Weaken(4) M.stop_flying() if(CanStumbleVore(M)) - visible_message("[M] flops carelessly into [src]!") + visible_message("[M] flops carelessly into [src]!") perform_the_nom(src,M,src,src.vore_selected,1) else if(M.CanStumbleVore(src)) - visible_message("[M] flops carelessly into [src]!") + visible_message("[M] flops carelessly into [src]!") perform_the_nom(M,src,M,M.vore_selected,1) else if(istype(S) && S.species.lightweight == 1) - visible_message("[M] carelessly bowls [src] over!") + visible_message("[M] carelessly bowls [src] over!") M.forceMove(get_turf(src)) M.apply_damage(0.5, BRUTE) Weaken(4) @@ -46,9 +46,9 @@ apply_damage(0.5, BRUTE) else if(round(weight) > 474) var/throwtarget = get_edge_target_turf(M, reverse_direction(M.dir)) - visible_message("[M] bounces backwards off of [src]'s plush body!") + visible_message("[M] bounces backwards off of [src]'s plush body!") M.throw_at(throwtarget, 2, 1) else - visible_message("[M] trips over [src]!") + visible_message("[M] trips over [src]!") M.forceMove(get_turf(src)) M.apply_damage(1, BRUTE) diff --git a/code/modules/vore/eating/transforming_vr.dm b/code/modules/vore/eating/transforming_vr.dm index e8de8d466b..638aa1d599 100644 --- a/code/modules/vore/eating/transforming_vr.dm +++ b/code/modules/vore/eating/transforming_vr.dm @@ -11,5 +11,5 @@ M.forceMove(egg) egg.name = egg_name if(message) - to_chat(M, "You lose sensation of your body, feeling only the warmth around you as you're encased in an egg.") - to_chat(O, "Your body shifts as you encase [M] in an egg.") + to_chat(M, "You lose sensation of your body, feeling only the warmth around you as you're encased in an egg.") + to_chat(O, "Your body shifts as you encase [M] in an egg.") diff --git a/code/modules/vore/eating/vertical_nom_vr.dm b/code/modules/vore/eating/vertical_nom_vr.dm index c9ff0a3096..658f6496cf 100644 --- a/code/modules/vore/eating/vertical_nom_vr.dm +++ b/code/modules/vore/eating/vertical_nom_vr.dm @@ -31,17 +31,17 @@ if(!target) return - to_chat(target, "You feel yourself being pulled up by something... Or someone?!") + to_chat(target, "You feel yourself being pulled up by something... Or someone?!") var/starting_loc = target.loc if(do_after(src, 50)) if(target.loc != starting_loc) - to_chat(target, "You have interrupted whatever that was...") - to_chat(src, "They got away.") + to_chat(target, "You have interrupted whatever that was...") + to_chat(src, "They got away.") return if(target.buckled) target.buckled.unbuckle_mob() - target.visible_message("\The [target] suddenly disappears somewhere above!",\ - "You are dragged above and feel yourself slipping directly into \the [src]'s [vore_selected]!") - to_chat(src, "You successfully snatch \the [target], slipping them into your [vore_selected].") - target.forceMove(src.vore_selected) \ No newline at end of file + target.visible_message("\The [target] suddenly disappears somewhere above!",\ + "You are dragged above and feel yourself slipping directly into \the [src]'s [vore_selected]!") + to_chat(src, "You successfully snatch \the [target], slipping them into your [vore_selected].") + target.forceMove(src.vore_selected) diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 4229a222d8..4142f81076 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -252,6 +252,7 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", selected_list["interacts"] = list() if(selected.escapable) selected_list["interacts"]["escapechance"] = selected.escapechance + selected_list["interacts"]["escapechance_absorbed"] = selected.escapechance_absorbed selected_list["interacts"]["escapetime"] = selected.escapetime selected_list["interacts"]["transferchance"] = selected.transferchance selected_list["interacts"]["transferlocation"] = selected.transferlocation @@ -1061,6 +1062,130 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", if(new_message) host.vore_selected.set_messages(new_message,"asmi") + if("escap") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they try to escape from within you. Write them in 2nd person ('you start to X')."+help,"Escape Attempt Message (to prey)",host.vore_selected.get_messages("escap"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escap") + + if("escao") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey tries to escape from within you. Write them in 2nd person ('X ... from your Y')."+help,"Escape Attempt Message (to you)",host.vore_selected.get_messages("escao"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escao") + + if("escp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they escape from within you. Write them in 2nd person ('you climb out of Y)."+help,"Escape Message (to prey)",host.vore_selected.get_messages("escp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escp") + + if("esco") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey escapes from within you. Write them in 2nd person ('X ... from your Y')."+help,"Escape Message (to you)",host.vore_selected.get_messages("esco"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"esco") + + if("escout") + var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when prey escapes from within you. Write them in 3rd person ('X climbs out of Z's Y')."+help,"Escape Message (outside)",host.vore_selected.get_messages("escout"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escout") + + if("escip") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they manage to eject an item from within you. Write them in 2nd person ('you manage to O'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (to prey)",host.vore_selected.get_messages("escip"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escip") + + if("escio") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey manages to eject an item from within you. Write them in 2nd person ('O slips from Y'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (to you)",host.vore_selected.get_messages("escio"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escio") + + if("esciout") + var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when prey manages to eject an item from within you. Write them in 3rd person ('O from Y'). Use %item to refer to the ejected item in this type."+help,"Escape Item Message (outside)",host.vore_selected.get_messages("esciout"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"esciout") + + if("escfp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they fail to escape from within you. Write them in 2nd person ('you failed to Y')."+help,"Escape Fail Message (to prey)",host.vore_selected.get_messages("escfp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escfp") + + if("escfo") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey fails to escape from within you. Write them in 2nd person ('X failed ... your Y')."+help,"Escape Fail Message (to you)",host.vore_selected.get_messages("escfo"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"escfo") + + if("aescap") + var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they try to escape from within you. Write them in 2nd person ('you start to X')."+help,"Absorbed Escape Attempt Message (to prey)",host.vore_selected.get_messages("aescap"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aescap") + + if("aescao") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey tries to escape from within you. Write them in 2nd person ('X ... from your Y')."+help,"Absorbed Escape Attempt Message (to you)",host.vore_selected.get_messages("aescao"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aescao") + + if("aescp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they escape from within you. Write them in 2nd person ('you escape from Y')."+help,"Absorbed Escape Message (to prey)",host.vore_selected.get_messages("aescp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aescp") + + if("aesco") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey escapes from within you. Write them in 2nd person ('X ... from your Y')."+help,"Absorbed Escape Message (to you)",host.vore_selected.get_messages("aesco"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aesco") + + if("aescout") + var/new_message = sanitize(tgui_input_text(user,"These are sent to those around you when absorbed prey escapes from within you. Write them in 3rd person ('X escapes from Z's Y')."+help,"Absorbed Escape Message (outside)",host.vore_selected.get_messages("aescout"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aescout") + + if("aescfp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to absorbed prey when they fail to escape from within you. Write them in 2nd person ('you failed to Y')."+help,"Absorbed Escape Fail Message (to prey)",host.vore_selected.get_messages("aescfp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aescfp") + + if("aescfo") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when absorbed prey fails to escape from within you. Write them in 2nd person ('X failed ... your Y')."+help,"Absorbed Escape Fail Message (to you)",host.vore_selected.get_messages("aescfo"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"aescfo") + + if("trnspp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they are automatically transferred into your primary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Primary Transfer Message (to prey)",host.vore_selected.get_messages("trnspp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"trnspp") + + if("trnspo") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey is automatically transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Primary Transfer Message (to you)",host.vore_selected.get_messages("trnspo"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"trnspo") + + if("trnssp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they are automatically transferred into your secondary destination. Write them in 2nd person ('you slide into Y'). Use %dest to refer to the target location in this type."+help,"Secondary Transfer Message (to prey)",host.vore_selected.get_messages("trnssp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"trnssp") + + if("trnsso") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey is automatically transferred into your primary destination. Write them in 2nd person ('X slid into your Y'). Use %dest to refer to the target location in this type."+help,"Secondary Transfer Message (to you)",host.vore_selected.get_messages("trnsso"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"trnsso") + + if("stmodp") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they trigger the interaction digest chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to prey)",host.vore_selected.get_messages("stmodp"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"stmodp") + + if("stmodo") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey triggers the interaction digest chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to you)",host.vore_selected.get_messages("stmodo"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"stmodo") + + if("stmoap") + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey when they trigger the interaction absorb chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to prey)",host.vore_selected.get_messages("stmoap"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"stmoap") + + if("stmoao") + var/new_message = sanitize(tgui_input_text(user,"These are sent to you when prey triggers the interaction absorb chance. Write them in 2nd person ('you feel X')."+help,"Stomach Mode Digest Message (to you)",host.vore_selected.get_messages("stmoao"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + if(new_message) + host.vore_selected.set_messages(new_message,"stmoao") if("em") var/new_message = sanitize(tgui_input_text(user,"These are sent to people who examine you when this belly has contents. Write them in 3rd person ('Their %belly is bulging')."+help,"Examine Message (when full)",host.vore_selected.get_messages("em"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) @@ -1165,6 +1290,31 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", host.vore_selected.struggle_messages_inside = initial(host.vore_selected.struggle_messages_inside) host.vore_selected.absorbed_struggle_messages_outside = initial(host.vore_selected.absorbed_struggle_messages_outside) host.vore_selected.absorbed_struggle_messages_inside = initial(host.vore_selected.absorbed_struggle_messages_inside) + host.vore_selected.escape_attempt_messages_owner = initial(host.vore_selected.escape_attempt_messages_owner) + host.vore_selected.escape_attempt_messages_prey = initial(host.vore_selected.escape_attempt_messages_prey) + host.vore_selected.escape_messages_owner = initial(host.vore_selected.escape_messages_owner) + host.vore_selected.escape_messages_prey = initial(host.vore_selected.escape_messages_prey) + host.vore_selected.escape_messages_outside = initial(host.vore_selected.escape_messages_outside) + host.vore_selected.escape_item_messages_owner = initial(host.vore_selected.escape_item_messages_owner) + host.vore_selected.escape_item_messages_prey = initial(host.vore_selected.escape_item_messages_prey) + host.vore_selected.escape_item_messages_outside = initial(host.vore_selected.escape_item_messages_outside) + host.vore_selected.escape_fail_messages_owner = initial(host.vore_selected.escape_fail_messages_owner) + host.vore_selected.escape_fail_messages_prey = initial(host.vore_selected.escape_fail_messages_prey) + host.vore_selected.escape_attempt_absorbed_messages_owner = initial(host.vore_selected.escape_attempt_absorbed_messages_owner) + host.vore_selected.escape_attempt_absorbed_messages_prey = initial(host.vore_selected.escape_attempt_absorbed_messages_prey) + host.vore_selected.escape_absorbed_messages_owner = initial(host.vore_selected.escape_absorbed_messages_owner) + host.vore_selected.escape_absorbed_messages_prey = initial(host.vore_selected.escape_absorbed_messages_prey) + host.vore_selected.escape_absorbed_messages_outside = initial(host.vore_selected.escape_absorbed_messages_outside) + host.vore_selected.escape_fail_absorbed_messages_owner = initial(host.vore_selected.escape_fail_absorbed_messages_owner) + host.vore_selected.escape_fail_absorbed_messages_prey = initial(host.vore_selected.escape_fail_absorbed_messages_prey) + host.vore_selected.primary_transfer_messages_owner = initial(host.vore_selected.primary_transfer_messages_owner) + host.vore_selected.primary_transfer_messages_prey = initial(host.vore_selected.primary_transfer_messages_prey) + host.vore_selected.secondary_transfer_messages_owner = initial(host.vore_selected.secondary_transfer_messages_owner) + host.vore_selected.secondary_transfer_messages_prey = initial(host.vore_selected.secondary_transfer_messages_prey) + host.vore_selected.digest_chance_messages_owner = initial(host.vore_selected.digest_chance_messages_owner) + host.vore_selected.digest_chance_messages_prey = initial(host.vore_selected.digest_chance_messages_prey) + host.vore_selected.absorb_chance_messages_owner = initial(host.vore_selected.absorb_chance_messages_owner) + host.vore_selected.absorb_chance_messages_prey = initial(host.vore_selected.absorb_chance_messages_prey) host.vore_selected.examine_messages = initial(host.vore_selected.examine_messages) host.vore_selected.examine_messages_absorbed = initial(host.vore_selected.examine_messages_absorbed) host.vore_selected.emote_lists = initial(host.vore_selected.emote_lists) @@ -1381,6 +1531,11 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", if(!isnull(escape_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options host.vore_selected.escapechance = sanitize_integer(escape_chance_input, 0, 100, initial(host.vore_selected.escapechance)) . = TRUE + if("b_escapechance_absorbed") + var/escape_absorbed_chance_input = tgui_input_number(user, "Set absorbed prey escape chance on resist (as %)", "Prey Absorbed Escape Chance", null, 100, 0) + if(!isnull(escape_absorbed_chance_input)) //These have to be 'null' because both cancel and 0 are valid, separate options + host.vore_selected.escapechance_absorbed = sanitize_integer(escape_absorbed_chance_input, 0, 100, initial(host.vore_selected.escapechance_absorbed)) + . = TRUE if("b_escapetime") var/escape_time_input = tgui_input_number(user, "Set number of seconds for prey to escape on resist (1-60)", "Prey Escape Time", null, 60, 1) if(!isnull(escape_time_input)) diff --git a/icons/inventory/accessory/item.dmi b/icons/inventory/accessory/item.dmi index e758fe7d4d..1c60ccfee6 100644 Binary files a/icons/inventory/accessory/item.dmi and b/icons/inventory/accessory/item.dmi differ diff --git a/icons/inventory/accessory/mob.dmi b/icons/inventory/accessory/mob.dmi index 298166f8bc..8fb324c931 100644 Binary files a/icons/inventory/accessory/mob.dmi and b/icons/inventory/accessory/mob.dmi differ diff --git a/icons/inventory/face/item.dmi b/icons/inventory/face/item.dmi index d1ea8a3fe9..618421ed5f 100644 Binary files a/icons/inventory/face/item.dmi and b/icons/inventory/face/item.dmi differ diff --git a/icons/inventory/face/item_vr.dmi b/icons/inventory/face/item_vr.dmi index cfa0381377..073f1df938 100644 Binary files a/icons/inventory/face/item_vr.dmi and b/icons/inventory/face/item_vr.dmi differ diff --git a/icons/inventory/face/mob.dmi b/icons/inventory/face/mob.dmi index 4459d4e85b..25b3466e07 100644 Binary files a/icons/inventory/face/mob.dmi and b/icons/inventory/face/mob.dmi differ diff --git a/icons/inventory/face/mob_vr.dmi b/icons/inventory/face/mob_vr.dmi index 6270461d76..6596062c57 100644 Binary files a/icons/inventory/face/mob_vr.dmi and b/icons/inventory/face/mob_vr.dmi differ diff --git a/icons/inventory/uniform/item.dmi b/icons/inventory/uniform/item.dmi index 8cf0bffad3..388f08c467 100644 Binary files a/icons/inventory/uniform/item.dmi and b/icons/inventory/uniform/item.dmi differ diff --git a/icons/inventory/uniform/mob.dmi b/icons/inventory/uniform/mob.dmi index 09e27fc452..dbf1d39f83 100644 Binary files a/icons/inventory/uniform/mob.dmi and b/icons/inventory/uniform/mob.dmi differ diff --git a/icons/mob/human.dmi b/icons/mob/human.dmi index 1c3ad0e96c..950bf15d4c 100644 Binary files a/icons/mob/human.dmi and b/icons/mob/human.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 8a7596f854..afbc6248ad 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/human_face_m.dmi b/icons/mob/human_face_m.dmi index 872cce2f3c..7986fb844f 100644 Binary files a/icons/mob/human_face_m.dmi and b/icons/mob/human_face_m.dmi differ diff --git a/icons/mob/vore/tails_vr.dmi b/icons/mob/vore/tails_vr.dmi index fafe63b1c6..a2b7e44ffe 100644 Binary files a/icons/mob/vore/tails_vr.dmi and b/icons/mob/vore/tails_vr.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index bdc777aad6..54fb7110bb 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1155,6 +1155,7 @@ window "mainwindow" saved-params = "pos;size;is-minimized;is-maximized" title = "VOREStation" is-maximized = true + statusbar = false icon = 'icons\\virgoicon.png' macro = "macro" menu = "menu" @@ -1168,7 +1169,7 @@ window "mainwindow" saved-params = "" elem "hotkey_toggle" type = BUTTON - pos = 560,420 + pos = 560,400 size = 80x20 anchor1 = 100,100 anchor2 = -1,-1 @@ -1179,7 +1180,7 @@ window "mainwindow" elem "mainvsplit" type = CHILD pos = 3,0 - size = 634x416 + size = 634x400 anchor1 = 0,0 anchor2 = 100,100 saved-params = "splitter" @@ -1187,7 +1188,7 @@ window "mainwindow" is-vert = true elem "input" type = INPUT - pos = 3,420 + pos = 3,400 size = 517x20 anchor1 = 0,100 anchor2 = 100,100 @@ -1195,9 +1196,19 @@ window "mainwindow" is-default = true border = sunken saved-params = "command" + elem "status_bar" + type = LABEL + pos = 3,420 + size = 517x16 + anchor1 = 0,100 + anchor2 = 100,100 + is-visible = true + text = "" + align = left + border = sunken elem "saybutton" type = BUTTON - pos = 520,420 + pos = 520,400 size = 40x20 anchor1 = 100,100 anchor2 = -1,-1 @@ -1222,12 +1233,8 @@ window "mapwindow" anchor1 = -1,-1 anchor2 = -1,-1 saved-params = "pos;size;is-minimized;is-maximized" - titlebar = false - statusbar = false - can-close = false - can-minimize = false - can-resize = false is-pane = true + on-status = ".winset \"status_bar.text=[[*]]\" " elem "map" type = MAP pos = 0,0 @@ -1250,46 +1257,28 @@ window "outputwindow" size = 640x480 anchor1 = -1,-1 anchor2 = -1,-1 + background-color = none saved-params = "pos;size;is-minimized;is-maximized" - titlebar = false - statusbar = false - can-close = false - can-minimize = false - can-resize = false is-pane = true - elem "chatloadlabel" - type = LABEL - pos = 0,0 - size = 640x480 - anchor1 = 0,0 - anchor2 = 100,100 - font-family = "sans-serif" - font-size = 24 - font-style = "bold" - text-color = #ffffff - background-color = #222222 - saved-params = "" - text = "Chat is loading.\nIf nothing happens after 20s,\nuse OOC > \"Reload VChat\"." - elem "htmloutput" + elem "browseroutput" type = BROWSER pos = 0,0 size = 640x480 anchor1 = 0,0 anchor2 = 100,100 is-visible = false + is-disabled = true saved-params = "" - elem "oldoutput" + elem "output" type = OUTPUT pos = 0,0 size = 640x480 anchor1 = 0,0 anchor2 = 100,100 - is-visible = false is-default = true saved-params = "" style = ".system {color:#FF0000;}" enable-http-images = true - max-lines = 0 window "prefs_markings_subwindow" elem "prefs_markings_subwindow" @@ -1429,6 +1418,19 @@ window "rpane" is-checked = true group = "rpanemode" button-type = pushbox + elem "infob" + type = BUTTON + pos = 60,0 + size = 60x16 + anchor1 = -1,-1 + anchor2 = -1,-1 + background-color = none + is-visible = false + saved-params = "is-checked" + text = "Info" + command = ".winset \"rpanewindow.left=infowindow\"" + group = "rpanemode" + button-type = pushbox elem "mediapanel" type = BROWSER pos = 392,25 diff --git a/code/stylesheet.dm b/interface/stylesheet.dm similarity index 89% rename from code/stylesheet.dm rename to interface/stylesheet.dm index 020cc9c6f8..646e7fd1da 100644 --- a/code/stylesheet.dm +++ b/interface/stylesheet.dm @@ -1,3 +1,11 @@ +/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +/// !!!!!!!!!!HEY LISTEN!!!!!!!!!!!!!!!!!!!!!!!! +/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +// If you modify this file you ALSO need to modify tgui/packages/tgui-panel/styles/tgchat/chat-light.scss and chat-dark.scss +// BUT you have to use PX font sizes with are on a x8 scale of these font sizes +// Sample font-size: DM: 8 CSS: 64px + /client/script = {"\n\n\n
\n'+c+"
\n\n\n"]),f=(new Date).toISOString().substring(0,19).replace(/[-:]/g,"").replace("T","-");window.navigator.msSaveBlob(l,"ss13-chatlog-"+f+".html")}},e}();window.__chatRenderer__||(window.__chatRenderer__=new w);var x=window.__chatRenderer__;t.chatRenderer=x},30116:function(e,t){"use strict";function n(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(n)return(n=n.call(e)).next.bind(n);if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0;return function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n9999)return{};o||(o=document.createDocumentFragment()),t||(t=[]);var h=u?u(r[0]):r[0],v=h.length,g=r.index+r[0].indexOf(h);d=t+a.CONNECTION_LOST_AFTER;!r.connectionLostAt&&u&&e.dispatch(c((0,o.connectionLost)())),r.connectionLostAt&&!u&&e.dispatch(c((0,o.connectionRestored)()))}}),1e3),function(e){return function(n){var i=n.type;return i===r.pingSuccess.type||i===r.pingSoft.type?(t=Date.now(),e(n)):i===o.roundRestarted.type?e(c(n)):e(n)}}}},13794:function(e,t,n){"use strict";t.__esModule=!0,t.gameReducer=void 0;var r=n(50879),o={roundId:null,roundTime:null,roundRestartedAt:null,connectionLostAt:null};t.gameReducer=function(e,t){void 0===e&&(e=o);var n=t.type,i=(t.payload,t.meta);return"roundrestart"===n?Object.assign({},e,{roundRestartedAt:i.now}):n===r.connectionLost.type?Object.assign({},e,{connectionLostAt:i.now}):n===r.connectionRestored.type?Object.assign({},e,{connectionLostAt:null}):e}},51389:function(e,t){"use strict";t.__esModule=!0,t.selectGame=void 0;t.selectGame=function(e){return e.game}},68042:function(e,t,n){"use strict";t.__esModule=!0,t.setupPanelFocusHacks=void 0;var r=n(69940),o=n(34443),i=n(19396),a=function(){return setImmediate((function(){return(0,i.focusMap)()}))};t.setupPanelFocusHacks=function(){var e=!1,t=null;window.addEventListener("focusin",(function(t){e=(0,o.canStealFocus)(t.target)})),window.addEventListener("mousedown",(function(e){t=[e.screenX,e.screenY]})),window.addEventListener("mouseup",(function(n){if(t){var o=[n.screenX,n.screenY];(0,r.vecLength)((0,r.vecSubtract)(o,t))>=10&&(e=!0)}e||a()})),o.globalEvents.on("keydown",(function(e){e.isModifierKey()||a()}))}},59789:function(e,t,n){"use strict";t.__esModule=!0,t.PingIndicator=void 0;var r=n(9333),o=n(1689),i=n(42991),a=n(78737),c=n(13435),u=n(66633);t.PingIndicator=function(e,t){var n=(0,a.useSelector)(t,u.selectPing),s=o.Color.lookup(n.networkQuality,[new o.Color(220,40,40),new o.Color(220,200,40),new o.Color(60,220,40)]),l=n.roundtrip?(0,i.toFixed)(n.roundtrip):"--";return(0,r.createVNode)(1,"div","Ping",[(0,r.createComponentVNode)(2,c.Box,{className:"Ping__indicator",backgroundColor:s}),l],0)}},48674:function(e,t,n){"use strict";t.__esModule=!0,t.pingSuccess=t.pingSoft=t.pingReply=t.pingFail=void 0;var r=n(78737),o=(0,r.createAction)("ping/reply");t.pingReply=o;var i=(0,r.createAction)("ping/soft");t.pingSoft=i;var a=(0,r.createAction)("ping/success",(function(e){return{payload:{lastId:e.id,roundtrip:.5*(Date.now()-e.sentAt)}}}));t.pingSuccess=a;var c=(0,r.createAction)("ping/fail");t.pingFail=c},79502:function(e,t){"use strict";t.__esModule=!0,t.PING_TIMEOUT=t.PING_ROUNDTRIP_WORST=t.PING_ROUNDTRIP_BEST=t.PING_QUEUE_SIZE=t.PING_MAX_FAILS=void 0;t.PING_TIMEOUT=2e3;t.PING_MAX_FAILS=3;t.PING_QUEUE_SIZE=8;t.PING_ROUNDTRIP_BEST=50;t.PING_ROUNDTRIP_WORST=200},97125:function(e,t,n){"use strict";t.__esModule=!0,t.pingReducer=t.pingMiddleware=t.PingIndicator=void 0;var r=n(38947);t.pingMiddleware=r.pingMiddleware;var o=n(59789);t.PingIndicator=o.PingIndicator;var i=n(86798);t.pingReducer=i.pingReducer},38947:function(e,t,n){"use strict";t.__esModule=!0,t.pingMiddleware=void 0;var r=n(48674),o=n(79502);t.pingMiddleware=function(e){var t=!1,n=0,i=[],a=function(){for(var t=0;to.PING_TIMEOUT&&(i[t]=null,e.dispatch((0,r.pingFail)()))}var c={index:n,sentAt:Date.now()};i[n]=c,Byond.sendMessage("ping",{index:n}),n=(n+1)%o.PING_QUEUE_SIZE};return function(e){return function(n){var o=n.type,c=n.payload;if(t||(t=!0,a()),o===r.pingSoft.type)return c.afk||a(),e(n);if(o===r.pingReply.type){var u=c.index,s=i[u];if(!s)return;return i[u]=null,e((0,r.pingSuccess)(s))}return e(n)}}}},86798:function(e,t,n){"use strict";t.__esModule=!0,t.pingReducer=void 0;var r=n(42991),o=n(48674),i=n(79502);t.pingReducer=function(e,t){void 0===e&&(e={});var n=t.type,a=t.payload;if(n===o.pingSuccess.type){var c=a.roundtrip,u=e.roundtripAvg||c,s=Math.round(.4*u+.6*c);return{roundtrip:c,roundtripAvg:s,failCount:0,networkQuality:1-(0,r.scale)(s,i.PING_ROUNDTRIP_BEST,i.PING_ROUNDTRIP_WORST)}}if(n===o.pingFail.type){var l=e.failCount,d=void 0===l?0:l,f=(0,r.clamp01)(e.networkQuality-d/i.PING_MAX_FAILS),p=Object.assign({},e,{failCount:d+1,networkQuality:f});return d>i.PING_MAX_FAILS&&(p.roundtrip=undefined,p.roundtripAvg=undefined),p}return e}},66633:function(e,t){"use strict";t.__esModule=!0,t.selectPing=void 0;t.selectPing=function(e){return e.ping}},2028:function(e,t,n){"use strict";t.__esModule=!0,t.ReconnectButton=void 0;var r=n(9333),o=n(13435),i=null;setInterval((function(){Byond.winget("","url").then((function(e){e&&!e.match(/:0$/)&&(i=e)}))}),5e3);t.ReconnectButton=function(){return i?(0,r.createFragment)([(0,r.createComponentVNode)(2,o.Button,{color:"white",onClick:function(){Byond.command(".reconnect")},children:"Reconnect"}),(0,r.createComponentVNode)(2,o.Button,{color:"white",onClick:function(){location.href="byond://"+i,Byond.command(".quit")},children:"Relaunch game"})],4):null}},36313:function(e,t,n){"use strict";t.__esModule=!0,t.SettingsPanel=t.SettingsGeneral=void 0;var r=n(9333),o=n(42991),i=n(57905),a=n(78737),c=n(13435),u=n(50351),s=n(74275),l=n(63671),d=n(99457),f=n(58685),p=n(31251),h=["id"];t.SettingsPanel=function(e,t){var n=(0,a.useSelector)(t,p.selectActiveTab),o=(0,a.useDispatch)(t);return(0,r.createComponentVNode)(2,c.Stack,{fill:!0,children:[(0,r.createComponentVNode)(2,c.Stack.Item,{children:(0,r.createComponentVNode)(2,c.Section,{fitted:!0,fill:!0,minHeight:"8em",children:(0,r.createComponentVNode)(2,c.Tabs,{vertical:!0,children:f.SETTINGS_TABS.map((function(e){return(0,r.createComponentVNode)(2,c.Tabs.Tab,{selected:e.id===n,onClick:function(){return o((0,d.changeSettingsTab)({tabId:e.id}))},children:e.name},e.id)}))})})}),(0,r.createComponentVNode)(2,c.Stack.Item,{grow:1,basis:0,children:["general"===n&&(0,r.createComponentVNode)(2,v),"chatPage"===n&&(0,r.createComponentVNode)(2,u.ChatPageSettings),"textHighlight"===n&&(0,r.createComponentVNode)(2,g)]})]})};var v=function(e,t){var n=(0,a.useSelector)(t,p.selectSettings),u=n.theme,h=n.fontFamily,v=n.fontSize,g=n.lineHeight,m=(0,a.useDispatch)(t),y=(0,i.useLocalState)(t,"freeFont",!1),b=y[0],_=y[1];return(0,r.createComponentVNode)(2,c.Section,{children:[(0,r.createComponentVNode)(2,c.LabeledList,{children:[(0,r.createComponentVNode)(2,c.LabeledList.Item,{label:"Theme",children:(0,r.createComponentVNode)(2,c.Dropdown,{selected:u,options:l.THEMES,onSelected:function(e){return m((0,d.updateSettings)({theme:e}))}})}),(0,r.createComponentVNode)(2,c.LabeledList.Item,{label:"Font style",children:(0,r.createComponentVNode)(2,c.Stack,{inline:!0,align:"baseline",children:[(0,r.createComponentVNode)(2,c.Stack.Item,{children:!b&&(0,r.createComponentVNode)(2,c.Dropdown,{selected:h,options:f.FONTS,onSelected:function(e){return m((0,d.updateSettings)({fontFamily:e}))}})||(0,r.createComponentVNode)(2,c.Input,{value:h,onChange:function(e,t){return m((0,d.updateSettings)({fontFamily:t}))}})}),(0,r.createComponentVNode)(2,c.Stack.Item,{children:(0,r.createComponentVNode)(2,c.Button,{content:"Custom font",icon:b?"lock-open":"lock",color:b?"good":"bad",ml:1,onClick:function(){_(!b)}})})]})}),(0,r.createComponentVNode)(2,c.LabeledList.Item,{label:"Font size",children:(0,r.createComponentVNode)(2,c.NumberInput,{width:"4em",step:1,stepPixelSize:10,minValue:8,maxValue:32,value:v,unit:"px",format:function(e){return(0,o.toFixed)(e)},onChange:function(e,t){return m((0,d.updateSettings)({fontSize:t}))}})}),(0,r.createComponentVNode)(2,c.LabeledList.Item,{label:"Line height",children:(0,r.createComponentVNode)(2,c.NumberInput,{width:"4em",step:.01,stepPixelSize:2,minValue:.8,maxValue:5,value:g,format:function(e){return(0,o.toFixed)(e,2)},onDrag:function(e,t){return m((0,d.updateSettings)({lineHeight:t}))}})})]}),(0,r.createComponentVNode)(2,c.Divider),(0,r.createComponentVNode)(2,c.Button,{icon:"save",onClick:function(){return m((0,s.saveChatToDisk)())},children:"Save chat log"})]})};t.SettingsGeneral=v;var g=function(e,t){var n=(0,a.useSelector)(t,p.selectHighlightSettings),o=(0,a.useDispatch)(t);return(0,r.createComponentVNode)(2,c.Section,{fill:!0,scrollable:!0,height:"200px",children:[(0,r.createComponentVNode)(2,c.Section,{p:0,children:(0,r.createComponentVNode)(2,c.Flex,{direction:"column",children:[n.map((function(e,t){return(0,r.createComponentVNode)(2,m,{id:e,mb:t+1===n.length?0:"10px"},t)})),n.length=0||(o[n]=e[n]);return o}(e,h),i=(0,a.useSelector)(t,p.selectHighlightSettingById),u=(0,a.useDispatch)(t),s=i[n],l=s.highlightColor,f=s.highlightText,v=s.highlightWholeMessage,g=s.matchWord,m=s.matchCase;return(0,r.normalizeProps)((0,r.createComponentVNode)(2,c.Flex.Item,Object.assign({},o,{children:[(0,r.createComponentVNode)(2,c.Flex,{mb:1,color:"label",align:"baseline",children:[(0,r.createComponentVNode)(2,c.Flex.Item,{grow:!0,children:(0,r.createComponentVNode)(2,c.Button,{content:"Delete",color:"transparent",icon:"times",onClick:function(){return u((0,d.removeHighlightSetting)({id:n}))}})}),(0,r.createComponentVNode)(2,c.Flex.Item,{children:(0,r.createComponentVNode)(2,c.Button.Checkbox,{checked:v,content:"Whole Message",tooltip:"If this option is selected, the entire message will be highlighted in yellow.",mr:"5px",onClick:function(){return u((0,d.updateHighlightSetting)({id:n,highlightWholeMessage:!v}))}})}),(0,r.createComponentVNode)(2,c.Flex.Item,{children:(0,r.createComponentVNode)(2,c.Button.Checkbox,{content:"Exact",checked:g,tooltipPosition:"bottom-start",tooltip:"If this option is selected, only exact matches (no extra letters before or after) will trigger. Not compatible with punctuation. Overriden if regex is used.",onClick:function(){return u((0,d.updateHighlightSetting)({id:n,matchWord:!g}))}})}),(0,r.createComponentVNode)(2,c.Flex.Item,{children:(0,r.createComponentVNode)(2,c.Button.Checkbox,{content:"Case",tooltip:"If this option is selected, the highlight will be case-sensitive.",checked:m,onClick:function(){return u((0,d.updateHighlightSetting)({id:n,matchCase:!m}))}})}),(0,r.createComponentVNode)(2,c.Flex.Item,{shrink:0,children:[(0,r.createComponentVNode)(2,c.ColorBox,{mr:1,color:l}),(0,r.createComponentVNode)(2,c.Input,{width:"5em",monospace:!0,placeholder:"#ffffff",value:l,onInput:function(e,t){return u((0,d.updateHighlightSetting)({id:n,highlightColor:t}))}})]})]}),(0,r.createComponentVNode)(2,c.TextArea,{height:"3em",value:f,placeholder:"Put words to highlight here. Separate terms with commas, i.e. (term1, term2, term3)",onChange:function(e,t){return u((0,d.updateHighlightSetting)({id:n,highlightText:t}))}})]})))}},99457:function(e,t,n){"use strict";t.__esModule=!0,t.updateSettings=t.updateHighlightSetting=t.toggleSettings=t.removeHighlightSetting=t.openChatSettings=t.loadSettings=t.changeSettingsTab=t.addHighlightSetting=void 0;var r=n(78737),o=n(40240),i=(0,r.createAction)("settings/update");t.updateSettings=i;var a=(0,r.createAction)("settings/load");t.loadSettings=a;var c=(0,r.createAction)("settings/changeTab");t.changeSettingsTab=c;var u=(0,r.createAction)("settings/toggle");t.toggleSettings=u;var s=(0,r.createAction)("settings/openChatTab");t.openChatSettings=s;var l=(0,r.createAction)("settings/addHighlightSetting",(function(){return{payload:(0,o.createHighlightSetting)()}}));t.addHighlightSetting=l;var d=(0,r.createAction)("settings/removeHighlightSetting");t.removeHighlightSetting=d;var f=(0,r.createAction)("settings/updateHighlightSetting");t.updateHighlightSetting=f},58685:function(e,t){"use strict";t.__esModule=!0,t.SETTINGS_TABS=t.MAX_HIGHLIGHT_SETTINGS=t.FONTS_DISABLED=t.FONTS=void 0;t.SETTINGS_TABS=[{id:"general",name:"General"},{id:"textHighlight",name:"Text Highlights"},{id:"chatPage",name:"Chat Tabs"}];var n="Default";t.FONTS_DISABLED=n;var r=[n,"Verdana","Arial","Arial Black","Comic Sans MS","Impact","Lucida Sans Unicode","Tahoma","Trebuchet MS","Courier New","Lucida Console"];t.FONTS=r;t.MAX_HIGHLIGHT_SETTINGS=10},65953:function(e,t,n){"use strict";t.__esModule=!0,t.useSettings=void 0;var r=n(78737),o=n(99457),i=n(31251);t.useSettings=function(e){var t=(0,r.useSelector)(e,i.selectSettings),n=(0,r.useDispatch)(e);return Object.assign({},t,{visible:t.view.visible,toggle:function(){return n((0,o.toggleSettings)())},update:function(e){return n((0,o.updateSettings)(e))}})}},39466:function(e,t,n){"use strict";t.__esModule=!0,t.useSettings=t.settingsReducer=t.settingsMiddleware=t.SettingsPanel=void 0;var r=n(65953);t.useSettings=r.useSettings;var o=n(7715);t.settingsMiddleware=o.settingsMiddleware;var i=n(85131);t.settingsReducer=i.settingsReducer;var a=n(36313);t.SettingsPanel=a.SettingsPanel},7715:function(e,t,n){"use strict";t.__esModule=!0,t.settingsMiddleware=void 0;var r=n(61010),o=n(63671),i=n(99457),a=n(31251),c=n(58685),u=null,s=null,l=null;t.settingsMiddleware=function(e){var t=!1;return function(n){return function(d){var f,p,h=d.type,v=d.payload;if(t||(t=!0,r.storage.get("panel-settings").then((function(t){e.dispatch((0,i.loadSettings)(t))}))),h===i.updateSettings.type||h===i.loadSettings.type||h===i.addHighlightSetting.type||h===i.removeHighlightSetting.type||h===i.updateHighlightSetting.type){var g=null==v?void 0:v.theme;g&&(0,o.setClientTheme)(g),n(d);var m=(0,a.selectSettings)(e.getState());return p=m.fontSize,l=p+"px",(f=m.fontFamily)===c.FONTS_DISABLED&&(f=null),s=f,function(){var e="";null!==s&&(e="font-family: "+s+" !important;");var t="body * :not(.Icon) {\n "+e+"\n }";null===u&&(u=document.createElement("style"),document.querySelector("head").append(u)),u.innerText=t,document.body.style.setProperty("font-size",l)}(),void r.storage.set("panel-settings",m)}return n(d)}}}},40240:function(e,t,n){"use strict";t.__esModule=!0,t.createHighlightSetting=t.createDefaultHighlightSetting=void 0;var r=n(23345),o=function(e){return Object.assign({id:(0,r.createUuid)(),highlightText:"",highlightColor:"#ffdd44",highlightWholeMessage:!0,matchWord:!1,matchCase:!1},e)};t.createHighlightSetting=o;t.createDefaultHighlightSetting=function(e){return o(Object.assign({id:"default"},e))}},85131:function(e,t,n){"use strict";t.__esModule=!0,t.settingsReducer=void 0;var r,o=n(99457),i=n(40240),a=n(58685),c=["id"];var u=(0,i.createDefaultHighlightSetting)(),s={version:1,fontSize:13,fontFamily:a.FONTS[0],lineHeight:1.2,theme:"light",adminMusicVolume:.5,highlightText:"",highlightColor:"#ffdd44",highlightSettings:[u.id],highlightSettingById:(r={},r[u.id]=u,r),view:{visible:!1,activeTab:a.SETTINGS_TABS[0].id}};t.settingsReducer=function(e,t){void 0===e&&(e=s);var n=t.type,r=t.payload;if(n===o.updateSettings.type)return Object.assign({},e,r);if(n===o.loadSettings.type){if(null==r||!r.version)return e;delete r.view;var i=Object.assign({},e,r);i.highlightSettings?i.highlightSettingById[u.id]||(i.highlightSettings=[u.id].concat(i.highlightSettings),i.highlightSettingById[u.id]=u):(i.highlightSettings=[u.id],i.highlightSettingById[u.id]=u);var l=i.highlightSettingById[u.id];return l.highlightColor=i.highlightColor,l.highlightText=i.highlightText,i}if(n===o.toggleSettings.type)return Object.assign({},e,{view:Object.assign({},e.view,{visible:!e.view.visible})});if(n===o.openChatSettings.type)return Object.assign({},e,{view:Object.assign({},e.view,{visible:!0,activeTab:"chatPage"})});if(n===o.changeSettingsTab.type){var d=r.tabId;return Object.assign({},e,{view:Object.assign({},e.view,{activeTab:d})})}if(n===o.addHighlightSetting.type){var f,p=r;return e.highlightSettings.length>=a.MAX_HIGHLIGHT_SETTINGS?e:Object.assign({},e,{highlightSettings:[].concat(e.highlightSettings,[p.id]),highlightSettingById:Object.assign({},e.highlightSettingById,(f={},f[p.id]=p,f))})}if(n===o.removeHighlightSetting.type){var h=r.id,v=Object.assign({},e,{highlightSettings:[].concat(e.highlightSettings),highlightSettingById:Object.assign({},e.highlightSettingById)});return h===u.id?v.highlightSettings[u.id]=u:(delete v.highlightSettingById[h],v.highlightSettings=v.highlightSettings.filter((function(e){return e!==h})),v.highlightSettings.length||(v.highlightSettings.push(u.id),v.highlightSettingById[u.id]=u)),v}if(n===o.updateHighlightSetting.type){var g=r.id,m=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(r,c),y=Object.assign({},e,{highlightSettings:[].concat(e.highlightSettings),highlightSettingById:Object.assign({},e.highlightSettingById)});return g===u.id&&(m.highlightText&&(y.highlightText=m.highlightText),m.highlightColor&&(y.highlightColor=m.highlightColor)),y.highlightSettingById[g]&&(y.highlightSettingById[g]=Object.assign({},y.highlightSettingById[g],m)),y}return e}},31251:function(e,t){"use strict";t.__esModule=!0,t.selectSettings=t.selectHighlightSettings=t.selectHighlightSettingById=t.selectActiveTab=void 0;t.selectSettings=function(e){return e.settings};t.selectActiveTab=function(e){return e.settings.view.activeTab};t.selectHighlightSettings=function(e){return e.settings.highlightSettings};t.selectHighlightSettingById=function(e){return e.settings.highlightSettingById}},14731:function(e,t,n){"use strict";t.__esModule=!0,t.telemetryMiddleware=void 0;var r=n(61010);function o(){o=function(){return e};var e={},t=Object.prototype,n=t.hasOwnProperty,r="function"==typeof Symbol?Symbol:{},i=r.iterator||"@@iterator",a=r.asyncIterator||"@@asyncIterator",c=r.toStringTag||"@@toStringTag";function u(e,t,n){return Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{u({},"")}catch(O){u=function(e,t,n){return e[t]=n}}function s(e,t,n,r){var o=t&&t.prototype instanceof f?t:f,i=Object.create(o.prototype),a=new C(r||[]);return i._invoke=function(e,t,n){var r="suspendedStart";return function(o,i){if("executing"===r)throw new Error("Generator is already running");if("completed"===r){if("throw"===o)throw i;return N()}for(n.method=o,n.arg=i;;){var a=n.delegate;if(a){var c=w(a,n);if(c){if(c===d)continue;return c}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if("suspendedStart"===r)throw r="completed",n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r="executing";var u=l(e,t,n);if("normal"===u.type){if(r=n.done?"completed":"suspendedYield",u.arg===d)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(r="completed",n.method="throw",n.arg=u.arg)}}}(e,n,a),i}function l(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(O){return{type:"throw",arg:O}}}e.wrap=s;var d={};function f(){}function p(){}function h(){}var v={};u(v,i,(function(){return this}));var g=Object.getPrototypeOf,m=g&&g(g(E([])));m&&m!==t&&n.call(m,i)&&(v=m);var y=h.prototype=f.prototype=Object.create(v);function b(e){["next","throw","return"].forEach((function(t){u(e,t,(function(e){return this._invoke(t,e)}))}))}function _(e,t){function r(o,i,a,c){var u=l(e[o],e,i);if("throw"!==u.type){var s=u.arg,d=s.value;return d&&"object"==typeof d&&n.call(d,"__await")?t.resolve(d.__await).then((function(e){r("next",e,a,c)}),(function(e){r("throw",e,a,c)})):t.resolve(d).then((function(e){s.value=e,a(s)}),(function(e){return r("throw",e,a,c)}))}c(u.arg)}var o;this._invoke=function(e,n){function i(){return new t((function(t,o){r(e,n,t,o)}))}return o=o?o.then(i,i):i()}}function w(e,t){var n=e.iterator[t.method];if(undefined===n){if(t.delegate=null,"throw"===t.method){if(e.iterator["return"]&&(t.method="return",t.arg=undefined,w(e,t),"throw"===t.method))return d;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return d}var r=l(n,e.iterator,t.arg);if("throw"===r.type)return t.method="throw",t.arg=r.arg,t.delegate=null,d;var o=r.arg;return o?o.done?(t[e.resultName]=o.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=undefined),t.delegate=null,d):o:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,d)}function x(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function S(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function C(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(x,this),this.reset(!0)}function E(e){if(e){var t=e[i];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,o=function t(){for(;++r=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),S(n),d}},"catch":function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;S(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:E(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=undefined),d}},e}function i(e,t,n,r,o,i,a){try{var c=e[i](a),u=c.value}catch(s){return void n(s)}c.done?t(u):Promise.resolve(u).then(r,o)}var a=(0,n(78196).createLogger)("telemetry");t.telemetryMiddleware=function(e){var t,n;return function(c){return function(u){var s,l=u.type,d=u.payload;if("telemetry/request"!==l)return"backend/update"===l?(c(u),void(s=o().mark((function h(){var i,c,u,s;return o().wrap((function(o){for(;;)switch(o.prev=o.next){case 0:if(c=null==d||null==(i=d.config)?void 0:i.client){o.next=4;break}return a.error("backend/update payload is missing client data!"),o.abrupt("return");case 4:if(t){o.next=13;break}return o.next=7,r.storage.get("telemetry");case 7:if(o.t0=o.sent,o.t0){o.next=10;break}o.t0={};case 10:(t=o.t0).connections||(t.connections=[]),a.debug("retrieved telemetry from storage",t);case 13:u=!1,t.connections.find((function(e){return n=c,(t=e).ckey===n.ckey&&t.address===n.address&&t.computer_id===n.computer_id;var t,n}))||(u=!0,t.connections.unshift(c),t.connections.length>10&&t.connections.pop()),u&&(a.debug("saving telemetry to storage",t),r.storage.set("telemetry",t)),n&&(s=n,n=null,e.dispatch({type:"telemetry/request",payload:s}));case 18:case"end":return o.stop()}}),h)})),function(){var e=this,t=arguments;return new Promise((function(n,r){var o=s.apply(e,t);function a(e){i(o,n,r,a,c,"next",e)}function c(e){i(o,n,r,a,c,"throw",e)}a(undefined)}))})()):c(u);if(!t)return a.debug("deferred"),void(n=d);a.debug("sending");var f=(null==d?void 0:d.limits)||{},p=t.connections.slice(0,f.connections);Byond.sendMessage("telemetry",{connections:p})}}}},63671:function(e,t){"use strict";t.__esModule=!0,t.setClientTheme=t.THEMES=void 0;t.THEMES=["light","dark"];var n="#202020",r="#171717",o="#a4bad6",i=null;t.setClientTheme=function(e){if(clearInterval(i),Byond.command(".output statbrowser:set_theme "+e),i=setTimeout((function(){Byond.command(".output statbrowser:set_theme "+e)}),1500),"light"===e)return Byond.winset({"infowindow.background-color":"none","infowindow.text-color":"#000000","info.background-color":"none","info.text-color":"#000000","browseroutput.background-color":"none","browseroutput.text-color":"#000000","outputwindow.background-color":"none","outputwindow.text-color":"#000000","mainwindow.background-color":"none","split.background-color":"none","changelog.background-color":"none","changelog.text-color":"#000000","rules.background-color":"none","rules.text-color":"#000000","wiki.background-color":"none","wiki.text-color":"#000000","forum.background-color":"none","forum.text-color":"#000000","github.background-color":"none","github.text-color":"#000000","report-issue.background-color":"none","report-issue.text-color":"#000000","output.background-color":"none","output.text-color":"#000000","statwindow.background-color":"none","statwindow.text-color":"#000000","stat.background-color":"#FFFFFF","stat.tab-background-color":"none","stat.text-color":"#000000","stat.tab-text-color":"#000000","stat.prefix-color":"#000000","stat.suffix-color":"#000000","saybutton.background-color":"none","saybutton.text-color":"#000000","oocbutton.background-color":"none","oocbutton.text-color":"#000000","mebutton.background-color":"none","mebutton.text-color":"#000000","asset_cache_browser.background-color":"none","asset_cache_browser.text-color":"#000000","tooltip.background-color":"none","tooltip.text-color":"#000000","input.background-color":"#FFFFFF","input.text-color":"#000000"});"dark"===e&&Byond.winset({"infowindow.background-color":n,"infowindow.text-color":o,"info.background-color":n,"info.text-color":o,"browseroutput.background-color":n,"browseroutput.text-color":o,"outputwindow.background-color":n,"outputwindow.text-color":o,"mainwindow.background-color":n,"split.background-color":n,"changelog.background-color":"#494949","changelog.text-color":o,"rules.background-color":"#494949","rules.text-color":o,"wiki.background-color":"#494949","wiki.text-color":o,"forum.background-color":"#494949","forum.text-color":o,"github.background-color":"#3a3a3a","github.text-color":o,"report-issue.background-color":"#492020","report-issue.text-color":o,"output.background-color":r,"output.text-color":o,"statwindow.background-color":r,"statwindow.text-color":o,"stat.background-color":r,"stat.tab-background-color":n,"stat.text-color":o,"stat.tab-text-color":o,"stat.prefix-color":o,"stat.suffix-color":o,"saybutton.background-color":n,"saybutton.text-color":o,"oocbutton.background-color":n,"oocbutton.text-color":o,"mebutton.background-color":n,"mebutton.text-color":o,"asset_cache_browser.background-color":n,"asset_cache_browser.text-color":o,"tooltip.background-color":n,"tooltip.text-color":o,"input.background-color":r,"input.text-color":o})}},48936:function(e,t){"use strict";t.__esModule=!0,t.resolveAsset=t.assetMiddleware=void 0;var n=[/v4shim/i],r={};t.resolveAsset=function(e){return r[e]||e};t.assetMiddleware=function(e){return function(e){return function(t){var o=t,i=o.type,a=o.payload;if("asset/stylesheet"!==i)if("asset/mappings"!==i)e(t);else for(var c=function(){var e=s[u];if(n.some((function(t){return t.test(e)})))return"continue";var t=a[e],o=e.split(".").pop();r[e]=t,"css"===o&&Byond.loadCss(t),"js"===o&&Byond.loadJs(t)},u=0,s=Object.keys(a);u=0||(o[n]=e[n]);return o}(e,a);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,i.Box,Object.assign({className:(0,o.classes)(["BlockQuote",t])},n)))}},89314:function(e,t,n){"use strict";t.__esModule=!0,t.unit=t.halfUnit=t.computeBoxProps=t.computeBoxClassName=t.Box=void 0;var r=n(54666),o=n(9333),i=n(95868),a=n(36711),c=["as","className","children"];var u=function(e){return"string"==typeof e?e.endsWith("px")&&!Byond.IS_LTE_IE8?parseFloat(e)/12+"rem":e:"number"==typeof e?Byond.IS_LTE_IE8?12*e+"px":e+"rem":void 0};t.unit=u;var s=function(e){return"string"==typeof e?u(e):"number"==typeof e?u(.5*e):void 0};t.halfUnit=s;var l=function(e){return"string"==typeof e&&a.CSS_COLORS.includes(e)},d=function(e){return function(t,n){"number"!=typeof n&&"string"!=typeof n||(t[e]=n)}},f=function(e,t){return function(n,r){"number"!=typeof r&&"string"!=typeof r||(n[e]=t(r))}},p=function(e,t){return function(n,r){r&&(n[e]=t)}},h=function(e,t,n){return function(r,o){if("number"==typeof o||"string"==typeof o)for(var i=0;i0&&(t.style=u),t};t.computeBoxProps=m;var y=function(e){var t=e.textColor||e.color,n=e.backgroundColor;return(0,r.classes)([l(t)&&"color-"+t,l(n)&&"color-bg-"+n])};t.computeBoxClassName=y;var b=function(e){var t=e.as,n=void 0===t?"div":t,r=e.className,a=e.children,u=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,c);if("function"==typeof a)return a(m(e));var s="string"==typeof r?r+" "+y(u):y(u),l=m(u);return(0,o.createVNode)(i.VNodeFlags.HtmlElement,n,s,a,i.ChildFlags.UnknownChildren,l,undefined)};t.Box=b,b.defaultHooks=r.pureComponentHooks},21782:function(e,t,n){"use strict";t.__esModule=!0,t.ButtonInput=t.ButtonFile=t.ButtonConfirm=t.ButtonCheckbox=t.Button=void 0;var r=n(9333),o=n(92547),i=n(54666),a=n(78196),c=n(89314),u=n(92854),s=n(4136),l=["className","fluid","icon","iconRotation","iconSpin","iconColor","iconPosition","iconSize","color","disabled","selected","tooltip","tooltipPosition","ellipsis","compact","circular","content","children","onclick","onClick","verticalAlignContent"],d=["checked"],f=["confirmContent","confirmColor","confirmIcon","icon","color","content","onClick"],p=["fluid","content","icon","iconRotation","iconSpin","tooltip","tooltipPosition","color","placeholder","maxLength"],h=["onSelectFiles","accept","multiple"];function v(){v=function(){return e};var e={},t=Object.prototype,n=t.hasOwnProperty,r="function"==typeof Symbol?Symbol:{},o=r.iterator||"@@iterator",i=r.asyncIterator||"@@asyncIterator",a=r.toStringTag||"@@toStringTag";function c(e,t,n){return Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{c({},"")}catch(O){c=function(e,t,n){return e[t]=n}}function u(e,t,n,r){var o=t&&t.prototype instanceof d?t:d,i=Object.create(o.prototype),a=new C(r||[]);return i._invoke=function(e,t,n){var r="suspendedStart";return function(o,i){if("executing"===r)throw new Error("Generator is already running");if("completed"===r){if("throw"===o)throw i;return N()}for(n.method=o,n.arg=i;;){var a=n.delegate;if(a){var c=w(a,n);if(c){if(c===l)continue;return c}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if("suspendedStart"===r)throw r="completed",n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r="executing";var u=s(e,t,n);if("normal"===u.type){if(r=n.done?"completed":"suspendedYield",u.arg===l)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(r="completed",n.method="throw",n.arg=u.arg)}}}(e,n,a),i}function s(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(O){return{type:"throw",arg:O}}}e.wrap=u;var l={};function d(){}function f(){}function p(){}var h={};c(h,o,(function(){return this}));var g=Object.getPrototypeOf,m=g&&g(g(E([])));m&&m!==t&&n.call(m,o)&&(h=m);var y=p.prototype=d.prototype=Object.create(h);function b(e){["next","throw","return"].forEach((function(t){c(e,t,(function(e){return this._invoke(t,e)}))}))}function _(e,t){function r(o,i,a,c){var u=s(e[o],e,i);if("throw"!==u.type){var l=u.arg,d=l.value;return d&&"object"==typeof d&&n.call(d,"__await")?t.resolve(d.__await).then((function(e){r("next",e,a,c)}),(function(e){r("throw",e,a,c)})):t.resolve(d).then((function(e){l.value=e,a(l)}),(function(e){return r("throw",e,a,c)}))}c(u.arg)}var o;this._invoke=function(e,n){function i(){return new t((function(t,o){r(e,n,t,o)}))}return o=o?o.then(i,i):i()}}function w(e,t){var n=e.iterator[t.method];if(undefined===n){if(t.delegate=null,"throw"===t.method){if(e.iterator["return"]&&(t.method="return",t.arg=undefined,w(e,t),"throw"===t.method))return l;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return l}var r=s(n,e.iterator,t.arg);if("throw"===r.type)return t.method="throw",t.arg=r.arg,t.delegate=null,l;var o=r.arg;return o?o.done?(t[e.resultName]=o.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=undefined),t.delegate=null,l):o:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,l)}function x(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function S(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function C(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(x,this),this.reset(!0)}function E(e){if(e){var t=e[o];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,i=function t(){for(;++r=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),S(n),l}},"catch":function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;S(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:E(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=undefined),l}},e}function g(e,t,n,r,o,i,a){try{var c=e[i](a),u=c.value}catch(s){return void n(s)}c.done?t(u):Promise.resolve(u).then(r,o)}function m(e){return function(){var t=this,n=arguments;return new Promise((function(r,o){var i=e.apply(t,n);function a(e){g(i,r,o,a,c,"next",e)}function c(e){g(i,r,o,a,c,"throw",e)}a(undefined)}))}}function y(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,b(e,t)}function b(e,t){return b=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},b(e,t)}function _(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var w=(0,a.createLogger)("Button"),x=function(e){var t=e.className,n=e.fluid,a=e.icon,d=e.iconRotation,f=e.iconSpin,p=e.iconColor,h=e.iconPosition,v=e.iconSize,g=e.color,m=e.disabled,y=e.selected,b=e.tooltip,x=e.tooltipPosition,S=e.ellipsis,C=e.compact,E=e.circular,N=e.content,O=e.children,M=e.onclick,k=e.onClick,T=e.verticalAlignContent,I=_(e,l),A=!(!N&&!O);M&&w.warn("Lowercase 'onclick' is not supported on Button and lowercase prop names are discouraged in general. Please use a camelCase'onClick' instead and read: https://infernojs.org/docs/guides/event-handling"),I.onClick=function(e){!m&&k&&k(e)},Byond.IS_LTE_IE8&&(I.unselectable=!0);var P=(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,i.classes)(["Button",n&&"Button--fluid",m&&"Button--disabled",y&&"Button--selected",A&&"Button--hasContent",S&&"Button--ellipsis",E&&"Button--circular",C&&"Button--compact",h&&"Button--iconPosition--"+h,T&&"Button--flex",T&&n&&"Button--flex--fluid",T&&"Button--verticalAlignContent--"+T,g&&"string"==typeof g?"Button--color--"+g:"Button--color--default",t,(0,c.computeBoxClassName)(I)]),(0,r.createVNode)(1,"div","Button__content",[a&&"right"!==h&&(0,r.createComponentVNode)(2,u.Icon,{name:a,color:p,rotation:d,spin:f}),N,O,a&&"right"===h&&(0,r.createComponentVNode)(2,u.Icon,{name:a,color:p,rotation:d,spin:f,fontSize:v})],0),2,Object.assign({tabIndex:!m&&"0",onKeyDown:function(t){if(!1!==e.captureKeys){var n=window.event?t.which:t.keyCode;if(n===o.KEY_SPACE||n===o.KEY_ENTER)return t.preventDefault(),void(!m&&k&&k(t));n!==o.KEY_ESCAPE||t.preventDefault()}}},(0,c.computeBoxProps)(I))));return b&&(P=(0,r.createComponentVNode)(2,s.Tooltip,{content:b,position:x,children:P})),P};t.Button=x,x.defaultHooks=i.pureComponentHooks;var S=function(e){var t=e.checked,n=_(e,d);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,x,Object.assign({color:"transparent",icon:t?"check-square-o":"square-o",selected:t},n)))};t.ButtonCheckbox=S,x.Checkbox=S;var C=function(e){function t(){var t;return(t=e.call(this)||this).state={clickedOnce:!1},t.handleClick=function(){t.state.clickedOnce&&t.setClickedOnce(!1)},t}y(t,e);var n=t.prototype;return n.setClickedOnce=function(e){var t=this;this.setState({clickedOnce:e}),e?setTimeout((function(){return window.addEventListener("click",t.handleClick)})):window.removeEventListener("click",this.handleClick)},n.render=function(){var e=this,t=this.props,n=t.confirmContent,o=void 0===n?"Confirm?":n,i=t.confirmColor,a=void 0===i?"bad":i,c=t.confirmIcon,u=t.icon,s=t.color,l=t.content,d=t.onClick,p=_(t,f);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,x,Object.assign({content:this.state.clickedOnce?o:l,icon:this.state.clickedOnce?c:u,color:this.state.clickedOnce?a:s,onClick:function(){return e.state.clickedOnce?d():e.setClickedOnce(!0)}},p)))},t}(r.Component);t.ButtonConfirm=C,x.Confirm=C;var E=function(e){function t(){var t;return(t=e.call(this)||this).inputRef=(0,r.createRef)(),t.state={inInput:!1},t}y(t,e);var n=t.prototype;return n.setInInput=function(e){if(this.setState({inInput:e}),this.inputRef){var t=this.inputRef.current;if(e){t.value=this.props.currentValue||"";try{t.focus(),t.select()}catch(n){}}}},n.commitResult=function(e){if(this.inputRef){var t=this.inputRef.current;if(""!==t.value)return void this.props.onCommit(e,t.value);if(!this.props.defaultValue)return;this.props.onCommit(e,this.props.defaultValue)}},n.render=function(){var e=this,t=this.props,n=t.fluid,a=t.content,l=t.icon,d=t.iconRotation,f=t.iconSpin,h=t.tooltip,v=t.tooltipPosition,g=t.color,m=void 0===g?"default":g,y=(t.placeholder,t.maxLength,_(t,p)),b=(0,r.normalizeProps)((0,r.createComponentVNode)(2,c.Box,Object.assign({className:(0,i.classes)(["Button",n&&"Button--fluid","Button--color--"+m])},y,{onClick:function(){return e.setInInput(!0)},children:[l&&(0,r.createComponentVNode)(2,u.Icon,{name:l,rotation:d,spin:f}),(0,r.createVNode)(1,"div",null,a,0),(0,r.createVNode)(64,"input","NumberInput__input",null,1,{style:{display:this.state.inInput?undefined:"none","text-align":"left"},onBlur:function(t){e.state.inInput&&(e.setInInput(!1),e.commitResult(t))},onKeyDown:function(t){if(t.keyCode===o.KEY_ENTER)return e.setInInput(!1),void e.commitResult(t);t.keyCode===o.KEY_ESCAPE&&e.setInInput(!1)}},null,this.inputRef)]})));return h&&(b=(0,r.createComponentVNode)(2,s.Tooltip,{content:h,position:v,children:b})),b},t}(r.Component);t.ButtonInput=E,x.Input=E;var N=function(e){function t(){var t;return(t=e.call(this)||this).inputRef=(0,r.createRef)(),t}y(t,e);var n=t.prototype;return n.read=function(){var e=m(v().mark((function t(e){var n;return v().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=Array.from(e).map((function(e){var t=new FileReader;return new Promise((function(n){t.onload=function(){return n(t.result)},t.readAsText(e)}))})),t.next=3,Promise.all(n);case 3:return t.abrupt("return",t.sent);case 4:case"end":return t.stop()}}),t)})));return function(t){return e.apply(this,arguments)}}(),n.render=function(){var e,t=this,n=this.props,o=n.onSelectFiles,i=n.accept,a=n.multiple,c=_(n,h),u=(0,r.createVNode)(64,"input",null,null,1,{hidden:!0,type:"file",accept:i,multiple:a,onChange:(e=m(v().mark((function s(){var e,n;return v().wrap((function(r){for(;;)switch(r.prev=r.next){case 0:if(!(e=t.inputRef.current.files).length){r.next=6;break}return r.next=4,t.read(e);case 4:n=r.sent,o(a?n:n[0]);case 6:case"end":return r.stop()}}),s)}))),function(){return e.apply(this,arguments)})},null,this.inputRef);return(0,r.createFragment)([(0,r.normalizeProps)((0,r.createComponentVNode)(2,x,Object.assign({},c,{onClick:function(){t.inputRef.current.click()}}))),u],0)},t}(r.Component);t.ButtonFile=N,x.File=N},93269:function(e,t,n){"use strict";t.__esModule=!0,t.ByondUi=void 0;var r=n(9333),o=n(54666),i=n(31376),a=n(78196),c=n(89314),u=["params"],s=["params"],l=["params"];function d(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function f(e,t){return f=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},f(e,t)}var p=(0,a.createLogger)("ByondUi"),h=[];window.addEventListener("beforeunload",(function(){for(var e=0;e=0||(o[n]=e[n]);return o}(t,c),m=this.state.viewBox,y=function(e,t,n,r){if(0===e.length)return[];var i=(0,o.zipWith)(Math.min).apply(void 0,e),a=(0,o.zipWith)(Math.max).apply(void 0,e);n!==undefined&&(i[0]=n[0],a[0]=n[1]),r!==undefined&&(i[1]=r[0],a[1]=r[1]);var c=(0,o.map)((function(e){return(0,o.zipWith)((function(e,t,n,r){return(e-t)/(n-t)*r}))(e,i,a,t)}))(e);return c}(i,m,u,s);if(y.length>0){var b=y[0],_=y[y.length-1];y.push([m[0]+v,_[1]]),y.push([m[0]+v,-v]),y.push([-v,-v]),y.push([-v,b[1]])}var w=function(e){for(var t="",n=0;n=0||(o[n]=e[n]);return o}(t,a);return(0,r.createComponentVNode)(2,o.Box,{mb:1,children:[(0,r.createVNode)(1,"div","Table",[(0,r.createVNode)(1,"div","Table__cell",(0,r.normalizeProps)((0,r.createComponentVNode)(2,i.Button,Object.assign({fluid:!0,color:s,icon:n?"chevron-down":"chevron-right",onClick:function(){return e.setState({open:!n})}},f,{children:l}))),2),d&&(0,r.createVNode)(1,"div","Table__cell Table__cell--collapsing",d,0)],0),n&&(0,r.createComponentVNode)(2,o.Box,{mt:1,children:c})]})},u}(r.Component);t.Collapsible=u},30821:function(e,t,n){"use strict";t.__esModule=!0,t.ColorBox=void 0;var r=n(9333),o=n(54666),i=n(89314),a=["content","children","className","color","backgroundColor"];var c=function(e){var t=e.content,n=(e.children,e.className),c=e.color,u=e.backgroundColor,s=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,a);return s.color=t?null:"transparent",s.backgroundColor=c||u,(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["ColorBox",n,(0,i.computeBoxClassName)(s)]),t||".",0,Object.assign({},(0,i.computeBoxProps)(s))))};t.ColorBox=c,c.defaultHooks=o.pureComponentHooks},65120:function(e,t,n){"use strict";t.__esModule=!0,t.UnsavedChangesDialog=t.Dialog=void 0;var r=n(9333),o=n(89314),i=n(21782),a=function(e){var t=e.title,n=e.onClose,a=e.children,c=e.width,u=e.height;return(0,r.createVNode)(1,"div","Dialog",(0,r.createComponentVNode)(2,o.Box,{className:"Dialog__content",width:c||"370px",height:u,children:[(0,r.createVNode)(1,"div","Dialog__header",[(0,r.createVNode)(1,"div","Dialog__title",t,0),(0,r.createComponentVNode)(2,o.Box,{mr:2,children:(0,r.createComponentVNode)(2,i.Button,{mr:"-3px",width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"window-close-o",tooltip:"Close",tooltipPosition:"bottom-start",onClick:n})})],4),a]}),2)};t.Dialog=a;var c=function(e){var t=e.onClick,n=e.children;return(0,r.createComponentVNode)(2,i.Button,{onClick:t,className:"Dialog__button",verticalAlignContent:"middle",children:n})};a.Button=c;t.UnsavedChangesDialog=function(e){var t=e.documentName,n=e.onSave,o=e.onDiscard,i=e.onClose;return(0,r.createComponentVNode)(2,a,{title:"Notepad",onClose:i,children:[(0,r.createVNode)(1,"div","Dialog__body",[(0,r.createTextVNode)("Do you want to save changes to "),t,(0,r.createTextVNode)("?")],0),(0,r.createVNode)(1,"div","Dialog__footer",[(0,r.createComponentVNode)(2,c,{onClick:n,children:"Save"}),(0,r.createComponentVNode)(2,c,{onClick:o,children:"Don't Save"}),(0,r.createComponentVNode)(2,c,{onClick:i,children:"Cancel"})],4)]})}},17597:function(e,t,n){"use strict";t.__esModule=!0,t.Dimmer=void 0;var r=n(9333),o=n(54666),i=n(89314),a=["className","children"];t.Dimmer=function(e){var t=e.className,n=e.children,c=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,a);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,i.Box,Object.assign({className:(0,o.classes)(["Dimmer"].concat(t))},c,{children:(0,r.createVNode)(1,"div","Dimmer__inner",n,0)})))}},54580:function(e,t,n){"use strict";t.__esModule=!0,t.Divider=void 0;var r=n(9333),o=n(54666);t.Divider=function(e){var t=e.vertical,n=e.hidden;return(0,r.createVNode)(1,"div",(0,o.classes)(["Divider",n&&"Divider--hidden",t?"Divider--vertical":"Divider--horizontal"]))}},58747:function(e,t,n){"use strict";t.__esModule=!0,t.DraggableControl=void 0;var r=n(9333),o=n(42991),i=n(54666),a=n(77988);function c(e,t){return c=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},c(e,t)}var u=function(e,t){return e.screenX*t[0]+e.screenY*t[1]},s=function(e){var t,n;function i(t){var n;return(n=e.call(this,t)||this).inputRef=(0,r.createRef)(),n.state={value:t.value,dragging:!1,editing:!1,internalValue:null,origin:null,suppressingFlicker:!1},n.flickerTimer=null,n.suppressFlicker=function(){var e=n.props.suppressFlicker;e>0&&(n.setState({suppressingFlicker:!0}),clearTimeout(n.flickerTimer),n.flickerTimer=setTimeout((function(){n.setState({suppressingFlicker:!1})}),e))},n.handleDragStart=function(e){var t=n.props,r=t.value,o=t.dragMatrix;n.state.editing||(document.body.style["pointer-events"]="none",n.ref=e.target,n.setState({dragging:!1,origin:u(e,o),value:r,internalValue:r}),n.timer=setTimeout((function(){n.setState({dragging:!0})}),250),n.dragInterval=setInterval((function(){var t=n.state,r=t.dragging,o=t.value,i=n.props.onDrag;r&&i&&i(e,o)}),n.props.updateRate||400),document.addEventListener("mousemove",n.handleDragMove),document.addEventListener("mouseup",n.handleDragEnd))},n.handleDragMove=function(e){var t=n.props,r=t.minValue,i=t.maxValue,a=t.step,c=t.stepPixelSize,s=t.dragMatrix;n.setState((function(t){var n=Object.assign({},t),l=u(e,s)-n.origin;if(t.dragging){var d=Number.isFinite(r)?r%a:0;n.internalValue=(0,o.clamp)(n.internalValue+l*a/c,r-a,i+a),n.value=(0,o.clamp)(n.internalValue-n.internalValue%a+d,r,i),n.origin=u(e,s)}else Math.abs(l)>4&&(n.dragging=!0);return n}))},n.handleDragEnd=function(e){var t=n.props,r=t.onChange,o=t.onDrag,i=n.state,a=i.dragging,c=i.value,u=i.internalValue;if(document.body.style["pointer-events"]="auto",clearTimeout(n.timer),clearInterval(n.dragInterval),n.setState({dragging:!1,editing:!a,origin:null}),document.removeEventListener("mousemove",n.handleDragMove),document.removeEventListener("mouseup",n.handleDragEnd),a)n.suppressFlicker(),r&&r(e,c),o&&o(e,c);else if(n.inputRef){var s=n.inputRef.current;s.value=u;try{s.focus(),s.select()}catch(l){}}},n}return n=e,(t=i).prototype=Object.create(n.prototype),t.prototype.constructor=t,c(t,n),i.prototype.render=function(){var e=this,t=this.state,n=t.dragging,i=t.editing,c=t.value,u=t.suppressingFlicker,s=this.props,l=s.animated,d=s.value,f=s.unit,p=s.minValue,h=s.maxValue,v=s.unclamped,g=s.format,m=s.onChange,y=s.onDrag,b=s.children,_=s.height,w=s.lineHeight,x=s.fontSize,S=d;(n||u)&&(S=c);var C=(0,r.createFragment)([!l||n||u?g?g(S):S:(0,r.createComponentVNode)(2,a.AnimatedNumber,{value:S,format:g}),f?" "+f:""],0),E=(0,r.createVNode)(64,"input","NumberInput__input",null,1,{style:{display:i?undefined:"none",height:_,"line-height":w,"font-size":x},onBlur:function(t){var n;i&&(n=v?parseFloat(t.target.value):(0,o.clamp)(parseFloat(t.target.value),p,h),Number.isNaN(n)?e.setState({editing:!1}):(e.setState({editing:!1,value:n}),e.suppressFlicker(),m&&m(t,n),y&&y(t,n)))},onKeyDown:function(t){var n;if(13===t.keyCode)return n=v?parseFloat(t.target.value):(0,o.clamp)(parseFloat(t.target.value),p,h),Number.isNaN(n)?void e.setState({editing:!1}):(e.setState({editing:!1,value:n}),e.suppressFlicker(),m&&m(t,n),void(y&&y(t,n)));27!==t.keyCode||e.setState({editing:!1})}},null,this.inputRef);return b({dragging:n,editing:i,value:d,displayValue:S,displayElement:C,inputElement:E,handleDragStart:this.handleDragStart})},i}(r.Component);t.DraggableControl=s,s.defaultHooks=i.pureComponentHooks,s.defaultProps={minValue:-Infinity,maxValue:+Infinity,step:1,stepPixelSize:1,suppressFlicker:50,dragMatrix:[1,0]}},46051:function(e,t,n){"use strict";t.__esModule=!0,t.Dropdown=void 0;var r=n(9333),o=n(37809),i=n(54666),a=n(89314),c=n(21782),u=n(92854),s=n(40254),l=["icon","iconRotation","iconSpin","clipSelectedText","color","dropdownStyle","over","nochevron","width","onClick","onSelected","selected","disabled","displayText","buttons"],d=["className"];function f(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function p(e,t){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},p(e,t)}var h={placement:"left-start",modifiers:[{name:"eventListeners",enabled:!1}]},v={width:0,height:0,top:0,right:0,bottom:0,left:0,x:0,y:0,toJSON:function(){return null}},g="Layout Dropdown__menu",m=function(e){var t,n;function v(){for(var t,n=arguments.length,r=new Array(n),o=0;o200?t.className="Layout Dropdown__menu-scroll":t.className=g;var n=this.props.options,a=(void 0===n?[]:n).map((function(t){var n,o;return"string"==typeof t?(o=t,n=t):null!==t&&(o=t.displayText,n=t.value),(0,r.createVNode)(1,"div",(0,i.classes)(["Dropdown__menuentry",e.state.selected===n&&"selected"]),o,0,{onClick:function(){e.setSelected(n)}},n)})),c=a.length?a:"No Options Found";(0,r.render)((0,r.createVNode)(1,"div",null,c,0),t,(function(){var e=v.singletonPopper;e===undefined?(e=(0,o.createPopper)(v.virtualElement,t,Object.assign({},h,{placement:"bottom-start"})),v.singletonPopper=e):(e.setOptions(Object.assign({},h,{placement:"bottom-start"})),e.update())}),this.context)}},m.setOpen=function(e){var t=this;this.setState((function(t){return Object.assign({},t,{open:e})})),e?setTimeout((function(){t.openMenu(),window.addEventListener("click",t.handleClick)})):(this.closeMenu(),window.removeEventListener("click",this.handleClick))},m.setSelected=function(e){this.setState((function(t){return Object.assign({},t,{selected:e})})),this.setOpen(!1),this.props.onSelected&&this.props.onSelected(e)},m.getOptionValue=function(e){return"string"==typeof e?e:e.value},m.getSelectedIndex=function(){var e=this,t=this.state.selected||this.props.selected,n=this.props.options;return(void 0===n?[]:n).findIndex((function(n){return e.getOptionValue(n)===t}))},m.toPrevious=function(){if(!(this.props.options.length<1)){var e=this.getSelectedIndex(),t=this.props.options.length-1;e>=0||(e=0);var n=0===e?t:e-1;this.setSelected(this.getOptionValue(this.props.options[n]))}},m.toNext=function(){if(!(this.props.options.length<1)){var e=this.getSelectedIndex(),t=this.props.options.length-1;e>=0||(e=t);var n=e===t?0:e+1;this.setSelected(this.getOptionValue(this.props.options[n]))}},m.render=function(){var e=this,t=this.props,n=t.icon,o=t.iconRotation,p=t.iconSpin,h=t.clipSelectedText,v=void 0===h||h,g=t.color,m=void 0===g?"default":g,y=(t.dropdownStyle,t.over),b=t.nochevron,_=t.width,w=t.onClick,x=(t.onSelected,t.selected,t.disabled),S=t.displayText,C=t.buttons,E=f(t,l),N=E.className,O=f(E,d),M=y?!this.state.open:this.state.open;return(0,r.createComponentVNode)(2,s.Stack,{fill:!0,children:[(0,r.createComponentVNode)(2,s.Stack.Item,{width:_,children:(0,r.normalizeProps)((0,r.createComponentVNode)(2,a.Box,Object.assign({width:"100%",className:(0,i.classes)(["Dropdown__control","Button","Button--color--"+m,x&&"Button--disabled",N]),onClick:function(t){x&&!e.state.open||(e.setOpen(!e.state.open),w&&w(t))}},O,{children:[n&&(0,r.createComponentVNode)(2,u.Icon,{name:n,rotation:o,spin:p,mr:1}),(0,r.createVNode)(1,"span","Dropdown__selected-text",S||this.state.selected,0,{style:{overflow:v?"hidden":"visible"}}),b||(0,r.createVNode)(1,"span","Dropdown__arrow-button",(0,r.createComponentVNode)(2,u.Icon,{name:M?"chevron-up":"chevron-down"}),2)]})))}),C&&(0,r.createFragment)([(0,r.createComponentVNode)(2,s.Stack.Item,{height:"100%",children:(0,r.createComponentVNode)(2,c.Button,{height:"100%",icon:"chevron-left",disabled:x,onClick:function(){x||e.toPrevious()}})}),(0,r.createComponentVNode)(2,s.Stack.Item,{height:"100%",children:(0,r.createComponentVNode)(2,c.Button,{height:"100%",icon:"chevron-right",disabled:x,onClick:function(){x||e.toNext()}})})],4)]})},v}(r.Component);t.Dropdown=m,m.renderedMenu=void 0,m.singletonPopper=void 0,m.currentOpenMenu=void 0,m.virtualElement={getBoundingClientRect:function(){var e,t;return null!=(e=null==(t=m.currentOpenMenu)?void 0:t.getBoundingClientRect())?e:v}}},4817:function(e,t,n){"use strict";t.__esModule=!0,t.FitText=void 0;var r=n(9333);function o(e,t){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},o(e,t)}var i=function(e){var t,n;function i(){var t;return(t=e.call(this)||this).ref=(0,r.createRef)(),t.state={fontSize:0},t.resize=t.resize.bind(function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(t)),window.addEventListener("resize",t.resize),t}n=e,(t=i).prototype=Object.create(n.prototype),t.prototype.constructor=t,o(t,n);var a=i.prototype;return a.componentDidUpdate=function(e){e.children!==this.props.children&&this.resize()},a.componentWillUnmount=function(){window.removeEventListener("resize",this.resize)},a.resize=function(){var e=this.ref.current;if(e){for(var t=this.props.maxWidth,n=0,r=this.props.maxFontSize,o=0;o<10;o++){var i,a=Math.round((n+r)/2);e.style.fontSize=a+"px";var c=e.offsetWidth-t;if(c>0)r=a;else{if(!(c<(null!=(i=this.props.acceptableDifference)?i:5)))break;n=a}}this.setState({fontSize:Math.round((n+r)/2)})}},a.componentDidMount=function(){this.resize()},a.render=function(){var e;return(0,r.createVNode)(1,"span",null,this.props.children,0,{style:Object.assign({"font-size":this.state.fontSize+"px"},"object"==typeof(null==(e=this.props.native)?void 0:e.style)&&this.props.native.style)},null,this.ref)},i}(r.Component);t.FitText=i},63152:function(e,t,n){"use strict";t.__esModule=!0,t.computeFlexProps=t.computeFlexItemProps=t.computeFlexItemClassName=t.computeFlexClassName=t.Flex=void 0;var r=n(9333),o=n(54666),i=n(89314),a=["className","direction","wrap","align","justify","inline"],c=["className"],u=["className","style","grow","order","shrink","basis","align"],s=["className"];function l(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var d=function(e){return(0,o.classes)(["Flex",e.inline&&"Flex--inline",Byond.IS_LTE_IE10&&"Flex--iefix",Byond.IS_LTE_IE10&&"column"===e.direction&&"Flex--iefix--column",(0,i.computeBoxClassName)(e)])};t.computeFlexClassName=d;var f=function(e){e.className;var t=e.direction,n=e.wrap,r=e.align,o=e.justify,c=(e.inline,l(e,a));return(0,i.computeBoxProps)(Object.assign({style:Object.assign({},c.style,{"flex-direction":t,"flex-wrap":!0===n?"wrap":n,"align-items":r,"justify-content":o})},c))};t.computeFlexProps=f;var p=function(e){var t=e.className,n=l(e,c);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)([t,d(n)]),null,1,Object.assign({},f(n))))};t.Flex=p,p.defaultHooks=o.pureComponentHooks;var h=function(e){return(0,o.classes)(["Flex__item",Byond.IS_LTE_IE10&&"Flex__item--iefix",(0,i.computeBoxClassName)(e)])};t.computeFlexItemClassName=h;var v=function(e){e.className;var t,n=e.style,r=e.grow,o=e.order,a=e.shrink,c=e.basis,s=e.align,d=l(e,u),f=null!=(t=null!=c?c:e.width)?t:r!==undefined?0:undefined;return(0,i.computeBoxProps)(Object.assign({style:Object.assign({},n,{"flex-grow":r!==undefined&&Number(r),"flex-shrink":a!==undefined&&Number(a),"flex-basis":(0,i.unit)(f),order:o,"align-self":s})},d))};t.computeFlexItemProps=v;var g=function(e){var t=e.className,n=l(e,s);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)([t,h(e)]),null,1,Object.assign({},v(n))))};g.defaultHooks=o.pureComponentHooks,p.Item=g},4177:function(e,t,n){"use strict";t.__esModule=!0,t.GridColumn=t.Grid=void 0;var r=n(9333),o=n(37470),i=n(54666),a=["children"],c=["size","style"];function u(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var s=function(e){var t=e.children,n=u(e,a);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,o.Table,Object.assign({},n,{children:(0,r.createComponentVNode)(2,o.Table.Row,{children:t})})))};t.Grid=s,s.defaultHooks=i.pureComponentHooks;var l=function(e){var t=e.size,n=void 0===t?1:t,i=e.style,a=u(e,c);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,o.Table.Cell,Object.assign({style:Object.assign({width:n+"%"},i)},a)))};t.GridColumn=l,s.defaultHooks=i.pureComponentHooks,s.Column=l},92854:function(e,t,n){"use strict";t.__esModule=!0,t.IconStack=t.Icon=void 0;var r=n(9333),o=n(54666),i=n(89314),a=["style"],c=["name","size","spin","className","rotation"],u=["className","children"];function s(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var l=/-o$/,d=function(e){var t=e.style,n=s(e,a),u=n.name,d=n.size,f=n.spin,p=n.className,h=n.rotation,v=s(n,c);d&&(t||(t={}),t["font-size"]=100*d+"%"),h&&(t||(t={}),t.transform="rotate("+h+"deg)"),v.style=t;var g=(0,i.computeBoxProps)(v),m="";if(u.startsWith("tg-"))m=u;else{var y=l.test(u),b=u.replace(l,"");m=y?"far ":"fas ",!b.startsWith("fa-")&&(m+="fa-"),m+=b,f&&(m+=" fa-spin")}return(0,r.normalizeProps)((0,r.createVNode)(1,"i",(0,o.classes)(["Icon",m,p,(0,i.computeBoxClassName)(v)]),null,1,Object.assign({},g)))};t.Icon=d,d.defaultHooks=o.pureComponentHooks;var f=function(e){var t=e.className,n=e.children,a=s(e,u);return(0,r.normalizeProps)((0,r.createVNode)(1,"span",(0,o.classes)(["IconStack",t,(0,i.computeBoxClassName)(a)]),n,0,Object.assign({},(0,i.computeBoxProps)(a))))};t.IconStack=f,d.Stack=f},21191:function(e,t,n){"use strict";t.__esModule=!0,t.InfinitePlane=void 0;var r=n(9333),o=n(89314),i=n(40254),a=n(41117),c=n(21782),u=["children","backgroundImage","imageWidth","initialLeft","initialTop"];function s(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function l(e,t){return l=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},l(e,t)}var d=function(e){var t,n;function d(){var t;return(t=e.call(this)||this).state={mouseDown:!1,left:0,top:0,lastLeft:0,lastTop:0,zoom:1},t.handleMouseDown=t.handleMouseDown.bind(s(t)),t.handleMouseMove=t.handleMouseMove.bind(s(t)),t.handleZoomIncrease=t.handleZoomIncrease.bind(s(t)),t.handleZoomDecrease=t.handleZoomDecrease.bind(s(t)),t.onMouseUp=t.onMouseUp.bind(s(t)),t.doOffsetMouse=t.doOffsetMouse.bind(s(t)),t}n=e,(t=d).prototype=Object.create(n.prototype),t.prototype.constructor=t,l(t,n);var f=d.prototype;return f.componentDidMount=function(){window.addEventListener("mouseup",this.onMouseUp),window.addEventListener("mousedown",this.doOffsetMouse),window.addEventListener("mousemove",this.doOffsetMouse),window.addEventListener("mouseup",this.doOffsetMouse)},f.componentWillUnmount=function(){window.removeEventListener("mouseup",this.onMouseUp),window.removeEventListener("mousedown",this.doOffsetMouse),window.removeEventListener("mousemove",this.doOffsetMouse),window.removeEventListener("mouseup",this.doOffsetMouse)},f.doOffsetMouse=function(e){var t=this.state.zoom;e.screenZoomX=e.screenX*Math.pow(t,-1),e.screenZoomY=e.screenY*Math.pow(t,-1)},f.handleMouseDown=function(e){this.setState((function(t){return{mouseDown:!0,lastLeft:e.clientX-t.left,lastTop:e.clientY-t.top}}))},f.onMouseUp=function(){this.setState({mouseDown:!1})},f.handleZoomIncrease=function(e){var t=this.props.onZoomChange,n=this.state.zoom,r=Math.min(n+.1,1.5);this.setState({zoom:r}),t&&t(r)},f.handleZoomDecrease=function(e){var t=this.props.onZoomChange,n=this.state.zoom,r=Math.max(n-.1,.5);this.setState({zoom:r}),t&&t(r)},f.handleMouseMove=function(e){var t,n,r=this.props,o=r.onBackgroundMoved,i=r.initialLeft,a=void 0===i?0:i,c=r.initialTop,u=void 0===c?0:c;this.state.mouseDown&&(this.setState((function(r){return t=e.clientX-r.lastLeft,n=e.clientY-r.lastTop,{left:t,top:n}})),o&&o(t+a,n+u))},f.render=function(){var e=this.props,t=e.children,n=e.backgroundImage,s=e.imageWidth,l=e.initialLeft,d=void 0===l?0:l,f=e.initialTop,p=void 0===f?0:f,h=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,u),v=this.state,g=v.left,m=v.top,y=v.zoom,b=d+g,_=p+m;return(0,r.normalizeProps)((0,r.createVNode)(1,"div",null,[(0,r.createVNode)(1,"div",null,null,1,{onMouseDown:this.handleMouseDown,onMouseMove:this.handleMouseMove,style:{position:"fixed",height:"100%",width:"100%","background-image":'url("'+n+'")',"background-position":b+"px "+_+"px","background-repeat":"repeat","background-size":y*s+"px"}}),(0,r.createVNode)(1,"div",null,t,0,{onMouseDown:this.handleMouseDown,onMouseMove:this.handleMouseMove,style:{position:"fixed",transform:"translate("+b+"px, "+_+"px) scale("+y+")","transform-origin":"top left",height:"100%",width:"100%"}}),(0,r.createComponentVNode)(2,i.Stack,{position:"absolute",width:"100%",children:[(0,r.createComponentVNode)(2,i.Stack.Item,{children:(0,r.createComponentVNode)(2,c.Button,{icon:"minus",onClick:this.handleZoomDecrease})}),(0,r.createComponentVNode)(2,i.Stack.Item,{grow:1,children:(0,r.createComponentVNode)(2,a.ProgressBar,{minValue:.5,value:y,maxValue:1.5,children:[y,"x"]})}),(0,r.createComponentVNode)(2,i.Stack.Item,{children:(0,r.createComponentVNode)(2,c.Button,{icon:"plus",onClick:this.handleZoomIncrease})})]})],4,Object.assign({},(0,o.computeBoxProps)(Object.assign({},h,{style:Object.assign({},h.style,{overflow:"hidden",position:"relative"})}))),null,this.ref))},d}(r.Component);t.InfinitePlane=d},53856:function(e,t,n){"use strict";t.__esModule=!0,t.toInputValue=t.Input=void 0;var r=n(9333),o=n(92547),i=n(54666),a=n(89314),c=["selfClear","onInput","onChange","onEnter","value","maxLength","placeholder"],u=["className","fluid","monospace"];function s(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function l(e,t){return l=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},l(e,t)}var d=function(e){return"number"!=typeof e&&"string"!=typeof e?"":String(e)};t.toInputValue=d;var f=function(e){var t,n;function f(){var t;return(t=e.call(this)||this).inputRef=(0,r.createRef)(),t.state={editing:!1},t.handleInput=function(e){var n=t.state.editing,r=t.props.onInput;n||t.setEditing(!0),r&&r(e,e.target.value)},t.handleFocus=function(e){t.state.editing||t.setEditing(!0)},t.handleBlur=function(e){var n=t.state.editing,r=t.props.onChange;n&&(t.setEditing(!1),r&&r(e,e.target.value))},t.handleKeyDown=function(e){var n=t.props,r=n.onInput,i=n.onChange,a=n.onEnter;return e.keyCode===o.KEY_ENTER?(t.setEditing(!1),i&&i(e,e.target.value),r&&r(e,e.target.value),a&&a(e,e.target.value),void(t.props.selfClear?e.target.value="":e.target.blur())):e.keyCode===o.KEY_ESCAPE?t.props.onEscape?void t.props.onEscape(e):(t.setEditing(!1),e.target.value=d(t.props.value),void e.target.blur()):void 0},t}n=e,(t=f).prototype=Object.create(n.prototype),t.prototype.constructor=t,l(t,n);var p=f.prototype;return p.componentDidMount=function(){var e=this,t=this.props.value,n=this.inputRef.current;n&&(n.value=d(t)),(this.props.autoFocus||this.props.autoSelect)&&setTimeout((function(){n.focus(),e.props.autoSelect&&n.select()}),1)},p.componentDidUpdate=function(e,t){var n=this.state.editing,r=e.value,o=this.props.value,i=this.inputRef.current;i&&!n&&r!==o&&(i.value=d(o))},p.setEditing=function(e){this.setState({editing:e})},p.render=function(){var e=this.props,t=(e.selfClear,e.onInput,e.onChange,e.onEnter,e.value,e.maxLength),n=e.placeholder,o=s(e,c),l=o.className,d=o.fluid,f=o.monospace,p=s(o,u);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,a.Box,Object.assign({className:(0,i.classes)(["Input",d&&"Input--fluid",f&&"Input--monospace",l])},p,{children:[(0,r.createVNode)(1,"div","Input__baseline",".",16),(0,r.createVNode)(64,"input","Input__input",null,1,{placeholder:n,onInput:this.handleInput,onFocus:this.handleFocus,onBlur:this.handleBlur,onKeyDown:this.handleKeyDown,maxLength:t},null,this.inputRef)]})))},f}(r.Component);t.Input=f},66581:function(e,t,n){"use strict";t.__esModule=!0,t.KeyListener=void 0;var r=n(9333),o=n(15268);function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}var a=function(e){var t,n;function r(){var t;return(t=e.call(this)||this).dispose=void 0,t.dispose=(0,o.listenForKeyEvents)((function(e){t.props.onKey&&t.props.onKey(e),e.isDown()&&t.props.onKeyDown&&t.props.onKeyDown(e),e.isUp()&&t.props.onKeyUp&&t.props.onKeyUp(e)})),t}n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,i(t,n);var a=r.prototype;return a.componentWillUnmount=function(){this.dispose()},a.render=function(){return null},r}(r.Component);t.KeyListener=a},9972:function(e,t,n){"use strict";t.__esModule=!0,t.Knob=void 0;var r=n(9333),o=n(42991),i=n(54666),a=n(89314),c=n(58747),u=n(97874),s=["animated","format","maxValue","minValue","unclamped","onChange","onDrag","step","stepPixelSize","suppressFlicker","unit","value","className","style","fillValue","color","ranges","size","bipolar","children"];t.Knob=function(e){if(Byond.IS_LTE_IE8)return(0,r.normalizeProps)((0,r.createComponentVNode)(2,u.NumberInput,Object.assign({},e)));var t=e.animated,n=e.format,l=e.maxValue,d=e.minValue,f=e.unclamped,p=e.onChange,h=e.onDrag,v=e.step,g=e.stepPixelSize,m=e.suppressFlicker,y=e.unit,b=e.value,_=e.className,w=e.style,x=e.fillValue,S=e.color,C=e.ranges,E=void 0===C?{}:C,N=e.size,O=void 0===N?1:N,M=e.bipolar,k=(e.children,function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,s));return(0,r.normalizeProps)((0,r.createComponentVNode)(2,c.DraggableControl,Object.assign({dragMatrix:[0,-1]},{animated:t,format:n,maxValue:l,minValue:d,unclamped:f,onChange:p,onDrag:h,step:v,stepPixelSize:g,suppressFlicker:m,unit:y,value:b},{children:function(e){var t=e.dragging,n=(e.editing,e.value),c=e.displayValue,u=e.displayElement,s=e.inputElement,f=e.handleDragStart,p=(0,o.scale)(null!=x?x:c,d,l),h=(0,o.scale)(c,d,l),v=S||(0,o.keyOfMatchingRange)(null!=x?x:n,E)||"default",g=Math.min(270*(h-.5),225);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,i.classes)(["Knob","Knob--color--"+v,M&&"Knob--bipolar",_,(0,a.computeBoxClassName)(k)]),[(0,r.createVNode)(1,"div","Knob__circle",(0,r.createVNode)(1,"div","Knob__cursorBox",(0,r.createVNode)(1,"div","Knob__cursor"),2,{style:{transform:"rotate("+g+"deg)"}}),2),t&&(0,r.createVNode)(1,"div","Knob__popupValue",u,0),(0,r.createVNode)(32,"svg","Knob__ring Knob__ringTrackPivot",(0,r.createVNode)(32,"circle","Knob__ringTrack",null,1,{cx:"50",cy:"50",r:"50"}),2,{viewBox:"0 0 100 100"}),(0,r.createVNode)(32,"svg","Knob__ring Knob__ringFillPivot",(0,r.createVNode)(32,"circle","Knob__ringFill",null,1,{style:{"stroke-dashoffset":Math.max(((M?2.75:2)-1.5*p)*Math.PI*50,0)},cx:"50",cy:"50",r:"50"}),2,{viewBox:"0 0 100 100"}),s],0,Object.assign({},(0,a.computeBoxProps)(Object.assign({style:Object.assign({"font-size":O+"em"},w)},k)),{onMouseDown:f})))}})))}},93341:function(e,t,n){"use strict";t.__esModule=!0,t.LabeledControls=void 0;var r=n(9333),o=n(63152),i=["children","wrap"],a=["label","children","mx"];function c(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var u=function(e){var t=e.children,n=e.wrap,a=c(e,i);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,o.Flex,Object.assign({mx:-.5,wrap:n,align:"stretch",justify:"space-between"},a,{children:t})))};t.LabeledControls=u;u.Item=function(e){var t=e.label,n=e.children,i=e.mx,u=void 0===i?1:i,s=c(e,a);return(0,r.createComponentVNode)(2,o.Flex.Item,{mx:u,children:(0,r.normalizeProps)((0,r.createComponentVNode)(2,o.Flex,Object.assign({height:"100%",direction:"column",align:"center",textAlign:"center",justify:"space-between"},s,{children:[(0,r.createComponentVNode)(2,o.Flex.Item),(0,r.createComponentVNode)(2,o.Flex.Item,{children:n}),(0,r.createComponentVNode)(2,o.Flex.Item,{color:"label",children:t})]})))})}},40514:function(e,t,n){"use strict";t.__esModule=!0,t.LabeledList=void 0;var r=n(9333),o=n(54666),i=n(89314),a=n(54580),c=function(e){var t=e.children;return(0,r.createVNode)(1,"table","LabeledList",t,0)};t.LabeledList=c,c.defaultHooks=o.pureComponentHooks;var u=function(e){var t=e.className,n=e.label,a=e.labelColor,c=void 0===a?"label":a,u=e.labelWrap,s=e.color,l=e.textAlign,d=e.buttons,f=e.content,p=e.children,h=e.verticalAlign,v=void 0===h?"baseline":h;return(0,r.createVNode)(1,"tr",(0,o.classes)(["LabeledList__row",t]),[(0,r.createComponentVNode)(2,i.Box,{as:"td",color:c,className:(0,o.classes)(["LabeledList__cell",!u&&"LabeledList__label--nowrap"]),verticalAlign:v,children:n?"string"==typeof n?n+":":n:null}),(0,r.createComponentVNode)(2,i.Box,{as:"td",color:s,textAlign:l,className:(0,o.classes)(["LabeledList__cell","LabeledList__content"]),colSpan:d?undefined:2,verticalAlign:v,children:[f,p]}),d&&(0,r.createVNode)(1,"td","LabeledList__cell LabeledList__buttons",d,0)],0)};u.defaultHooks=o.pureComponentHooks;var s=function(e){var t=e.size?(0,i.unit)(Math.max(0,e.size-1)):0;return(0,r.createVNode)(1,"tr","LabeledList__row",(0,r.createVNode)(1,"td",null,(0,r.createComponentVNode)(2,a.Divider),2,{colSpan:3,style:{"padding-top":t,"padding-bottom":t}}),2)};s.defaultHooks=o.pureComponentHooks,c.Item=u,c.Divider=s},38101:function(e,t,n){"use strict";t.__esModule=!0,t.MenuBar=t.Dropdown=void 0;var r=n(9333),o=n(54666),i=n(89314),a=n(78196),c=n(92854),u=["open","openWidth","children","disabled","display","onMouseOver","onClick","onOutsideClick"],s=["className"];function l(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function d(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,f(e,t)}function f(e,t){return f=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},f(e,t)}var p=function(e){function t(t){var n;return(n=e.call(this,t)||this).handleClick=void 0,n.handleClick=function(e){n.props.menuRef.current?n.props.menuRef.current.contains(e.target)?a.logger.log("Menu.handleClick(): Inside"):(a.logger.log("Menu.handleClick(): Outside"),n.props.onOutsideClick()):a.logger.log("Menu.handleClick(): No ref")},n}d(t,e);var n=t.prototype;return n.componentWillMount=function(){window.addEventListener("click",this.handleClick)},n.componentWillUnmount=function(){window.removeEventListener("click",this.handleClick)},n.render=function(){var e=this.props,t=e.width,n=e.children;return(0,r.createVNode)(1,"div","MenuBar__menu",n,0,{style:{width:t}})},t}(r.Component),h=function(e){function t(t){var n;return(n=e.call(this,t)||this).menuRef=void 0,n.menuRef=(0,r.createRef)(),n}return d(t,e),t.prototype.render=function(){var e=this.props,t=e.open,n=e.openWidth,a=e.children,c=e.disabled,d=e.display,f=e.onMouseOver,h=e.onClick,v=e.onOutsideClick,g=l(e,u),m=g.className,y=l(g,s);return(0,r.createVNode)(1,"div",null,[(0,r.normalizeProps)((0,r.createComponentVNode)(2,i.Box,Object.assign({className:(0,o.classes)(["MenuBar__MenuBarButton","MenuBar__font","MenuBar__hover",m])},y,{onClick:c?undefined:h,onmouseover:f,children:(0,r.createVNode)(1,"span","MenuBar__MenuBarButton-text",d,0)}))),t&&(0,r.createComponentVNode)(2,p,{width:n,menuRef:this.menuRef,onOutsideClick:v,children:a})],0,null,null,this.menuRef)},t}(r.Component),v=function(e){var t=e.entry,n=e.children,o=e.openWidth,i=e.display,a=e.setOpenMenuBar,c=e.openMenuBar,u=e.setOpenOnHover,s=e.openOnHover,l=e.disabled,d=e.className;return(0,r.createComponentVNode)(2,h,{openWidth:o,display:i,disabled:l,open:c===t,className:d,onClick:function(){a(c===t?null:t),u(!s)},onOutsideClick:function(){a(null),u(!1)},onMouseOver:function(){s&&a(t)},children:n})};t.Dropdown=v;v.MenuItemToggle=function(e){var t=e.value,n=e.displayText,a=e.onClick,u=e.checked;return(0,r.createComponentVNode)(2,i.Box,{className:(0,o.classes)(["MenuBar__font","MenuBar__MenuItem","MenuBar__MenuItemToggle","MenuBar__hover"]),onClick:function(){return a(t)},children:[(0,r.createVNode)(1,"div","MenuBar__MenuItemToggle__check",u&&(0,r.createComponentVNode)(2,c.Icon,{size:1.3,name:"check"}),0),n]})};v.MenuItem=function(e){var t=e.value,n=e.displayText,a=e.onClick;return(0,r.createComponentVNode)(2,i.Box,{className:(0,o.classes)(["MenuBar__font","MenuBar__MenuItem","MenuBar__hover"]),onClick:function(){return a(t)},children:n})};v.Separator=function(){return(0,r.createVNode)(1,"div","MenuBar__Separator")};var g=function(e){var t=e.children;return(0,r.createComponentVNode)(2,i.Box,{className:"MenuBar",children:t})};t.MenuBar=g,g.Dropdown=v},98005:function(e,t,n){"use strict";t.__esModule=!0,t.Modal=void 0;var r=n(9333),o=n(54666),i=n(89314),a=n(17597),c=["className","children","onEnter"];t.Modal=function(e){var t,n=e.className,u=e.children,s=e.onEnter,l=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,c);return s&&(t=function(e){13===(e.which||e.keyCode)&&s(e)}),(0,r.createComponentVNode)(2,a.Dimmer,{onKeyDown:t,children:(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Modal",n,(0,i.computeBoxClassName)(l)]),u,0,Object.assign({},(0,i.computeBoxProps)(l))))})}},25764:function(e,t,n){"use strict";t.__esModule=!0,t.NanoMap=void 0;var r=n(9333),o=n(13435),i=n(57905);function a(e,t){return a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},a(e,t)}var c=function(e){return e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault(),e.cancelBubble=!0,e.returnValue=!1,!1},u=function(e){var t,n;function u(t){var n;n=e.call(this,t)||this;var r=window.innerWidth/2-256,o=window.innerHeight/2-256;return n.state={offsetX:r,offsetY:o,transform:"none",dragging:!1,originX:null,originY:null,zoom:1},n.handleDragStart=function(e){n.ref=e.target,n.setState({dragging:!1,originX:e.screenX,originY:e.screenY}),document.addEventListener("mousemove",n.handleDragMove),document.addEventListener("mouseup",n.handleDragEnd),c(e)},n.handleDragMove=function(e){n.setState((function(t){var n=Object.assign({},t),r=e.screenX-n.originX,o=e.screenY-n.originY;return t.dragging?(n.offsetX+=r,n.offsetY+=o,n.originX=e.screenX,n.originY=e.screenY):n.dragging=!0,n})),c(e)},n.handleDragEnd=function(e){n.setState({dragging:!1,originX:null,originY:null}),document.removeEventListener("mousemove",n.handleDragMove),document.removeEventListener("mouseup",n.handleDragEnd),c(e)},n.handleOnClick=function(e){var t=e.offsetX/n.state.zoom/280,r=1-e.offsetY/n.state.zoom/280;e.byondX=t,e.byondY=r,"function"==typeof n.props.onClick&&n.props.onClick(e)},n.handleZoom=function(e,r){n.setState((function(e){var n=Math.min(Math.max(r,1),8),o=1.5*(n-e.zoom);e.zoom=n;var i=e.offsetX-262*o;i<-500&&(i=-500),i>500&&(i=500);var a=e.offsetY-256*o;return a<-200&&(a=-200),a>200&&(a=200),e.offsetX=i,e.offsetY=a,t.onZoom&&t.onZoom(e.zoom),e}))},n}return n=e,(t=u).prototype=Object.create(n.prototype),t.prototype.constructor=t,a(t,n),u.prototype.render=function(){var e=(0,i.useBackend)(this.context).config,t=this.state,n=t.dragging,a=t.offsetX,c=t.offsetY,u=t.zoom,l=void 0===u?1:u,d=this.props.children,f=280*l+"px",p={width:f,height:f,"margin-top":c+"px","margin-left":a+"px",overflow:"hidden",position:"relative","background-image":"url("+e.map+"_nanomap_z"+e.mapZLevel+".png)","background-size":"cover","background-repeat":"no-repeat","text-align":"center",cursor:n?"move":"auto"};return(0,r.createComponentVNode)(2,o.Box,{className:"NanoMap__container",children:[(0,r.createComponentVNode)(2,o.Box,{style:p,textAlign:"center",onMouseDown:this.handleDragStart,onClick:this.handleOnClick,children:(0,r.createComponentVNode)(2,o.Box,{children:d})}),(0,r.createComponentVNode)(2,s,{zoom:l,onZoom:this.handleZoom})]})},u}(r.Component);t.NanoMap=u;u.Marker=function(e,t){var n=e.x,i=e.y,a=e.zoom,u=void 0===a?1:a,s=e.icon,l=e.tooltip,d=e.color,f=e.onClick,p=2*n*u-u-3,h=2*i*u-u-3;return(0,r.createVNode)(1,"div",null,(0,r.createComponentVNode)(2,o.Box,{position:"absolute",className:"NanoMap__marker",lineHeight:"0",bottom:h+"px",left:p+"px",onMouseDown:function(e){c(e),f&&f(e)},children:[(0,r.createComponentVNode)(2,o.Icon,{name:s,color:d,fontSize:"6px"}),(0,r.createComponentVNode)(2,o.Tooltip,{content:l})]}),2)};var s=function(e,t){var n=(0,i.useBackend)(t),a=n.act,c=n.config,u=n.data;return(0,r.createComponentVNode)(2,o.Box,{className:"NanoMap__zoomer",children:(0,r.createComponentVNode)(2,o.LabeledList,{children:[(0,r.createComponentVNode)(2,o.LabeledList.Item,{label:"Zoom",children:(0,r.createComponentVNode)(2,o.Slider,{minValue:"1",maxValue:"8",stepPixelSize:"10",format:function(e){return e+"x"},value:e.zoom,onDrag:function(t,n){return e.onZoom(t,n)}})}),(0,r.createComponentVNode)(2,o.LabeledList.Item,{label:"Z-Level",children:u.map_levels.sort((function(e,t){return Number(e)-Number(t)})).map((function(e){return(0,r.createComponentVNode)(2,o.Button,{selected:~~e==~~c.mapZLevel,content:e,onClick:function(){a("setZLevel",{mapZLevel:e})}},e)}))})]})})};u.Zoomer=s},68210:function(e,t,n){"use strict";t.__esModule=!0,t.NoticeBox=void 0;var r=n(9333),o=n(54666),i=n(89314),a=["className","color","info","warning","success","danger"];var c=function(e){var t=e.className,n=e.color,c=e.info,u=(e.warning,e.success),s=e.danger,l=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,a);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,i.Box,Object.assign({className:(0,o.classes)(["NoticeBox",n&&"NoticeBox--color--"+n,c&&"NoticeBox--type--info",u&&"NoticeBox--type--success",s&&"NoticeBox--type--danger",t])},l)))};t.NoticeBox=c,c.defaultHooks=o.pureComponentHooks},97874:function(e,t,n){"use strict";t.__esModule=!0,t.NumberInput=void 0;var r=n(9333),o=n(42991),i=n(54666),a=n(77988),c=n(89314);function u(e,t){return u=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},u(e,t)}var s=function(e){var t,n;function s(t){var n;n=e.call(this,t)||this;var i=t.value;return n.inputRef=(0,r.createRef)(),n.state={value:i,dragging:!1,editing:!1,internalValue:null,origin:null,suppressingFlicker:!1},n.flickerTimer=null,n.suppressFlicker=function(){var e=n.props.suppressFlicker;e>0&&(n.setState({suppressingFlicker:!0}),clearTimeout(n.flickerTimer),n.flickerTimer=setTimeout((function(){return n.setState({suppressingFlicker:!1})}),e))},n.handleDragStart=function(e){var t=n.props.value;n.state.editing||(document.body.style["pointer-events"]="none",n.ref=e.target,n.setState({dragging:!1,origin:e.screenY,value:t,internalValue:t}),n.timer=setTimeout((function(){n.setState({dragging:!0})}),250),n.dragInterval=setInterval((function(){var t=n.state,r=t.dragging,o=t.value,i=n.props.onDrag;r&&i&&i(e,o)}),n.props.updateRate||400),document.addEventListener("mousemove",n.handleDragMove),document.addEventListener("mouseup",n.handleDragEnd))},n.handleDragMove=function(e){var t=n.props,r=t.minValue,i=t.maxValue,a=t.step,c=t.stepPixelSize;n.setState((function(t){var n=Object.assign({},t),u=n.origin-e.screenY;if(t.dragging){var s=Number.isFinite(r)?r%a:0;n.internalValue=(0,o.clamp)(n.internalValue+u*a/c,r-a,i+a),n.value=(0,o.clamp)(n.internalValue-n.internalValue%a+s,r,i),n.origin=e.screenY}else Math.abs(u)>4&&(n.dragging=!0);return n}))},n.handleDragEnd=function(e){var t=n.props,r=t.onChange,o=t.onDrag,i=n.state,a=i.dragging,c=i.value,u=i.internalValue;if(document.body.style["pointer-events"]="auto",clearTimeout(n.timer),clearInterval(n.dragInterval),n.setState({dragging:!1,editing:!a,origin:null}),document.removeEventListener("mousemove",n.handleDragMove),document.removeEventListener("mouseup",n.handleDragEnd),a)n.suppressFlicker(),r&&r(e,c),o&&o(e,c);else if(n.inputRef){var s=n.inputRef.current;s.value=u;try{s.focus(),s.select()}catch(l){}}},n}return n=e,(t=s).prototype=Object.create(n.prototype),t.prototype.constructor=t,u(t,n),s.prototype.render=function(){var e=this,t=this.state,n=t.dragging,u=t.editing,s=t.value,l=t.suppressingFlicker,d=this.props,f=d.className,p=d.fluid,h=d.animated,v=d.value,g=d.unit,m=d.minValue,y=d.maxValue,b=d.height,_=d.width,w=d.lineHeight,x=d.fontSize,S=d.format,C=d.onChange,E=d.onDrag,N=v;(n||l)&&(N=s);var O=(0,r.createVNode)(1,"div","NumberInput__content",[!h||n||l?S?S(N):N:(0,r.createComponentVNode)(2,a.AnimatedNumber,{value:N,format:S}),g?" "+g:""],0,{unselectable:Byond.IS_LTE_IE8});return(0,r.createComponentVNode)(2,c.Box,{className:(0,i.classes)(["NumberInput",p&&"NumberInput--fluid",f]),minWidth:_,minHeight:b,lineHeight:w,fontSize:x,onMouseDown:this.handleDragStart,children:[(0,r.createVNode)(1,"div","NumberInput__barContainer",(0,r.createVNode)(1,"div","NumberInput__bar",null,1,{style:{height:(0,o.clamp)((N-m)/(y-m)*100,0,100)+"%"}}),2),O,(0,r.createVNode)(64,"input","NumberInput__input",null,1,{style:{display:u?undefined:"none",height:b,"line-height":w,"font-size":x},onBlur:function(t){if(u){var n=(0,o.clamp)(parseFloat(t.target.value),m,y);Number.isNaN(n)?e.setState({editing:!1}):(e.setState({editing:!1,value:n}),e.suppressFlicker(),C&&C(t,n),E&&E(t,n))}},onKeyDown:function(t){if(13===t.keyCode){var n=(0,o.clamp)(parseFloat(t.target.value),m,y);return Number.isNaN(n)?void e.setState({editing:!1}):(e.setState({editing:!1,value:n}),e.suppressFlicker(),C&&C(t,n),void(E&&E(t,n)))}27!==t.keyCode||e.setState({editing:!1})}},null,this.inputRef)]})},s}(r.Component);t.NumberInput=s,s.defaultHooks=i.pureComponentHooks,s.defaultProps={minValue:-Infinity,maxValue:+Infinity,step:1,stepPixelSize:1,suppressFlicker:50}},91679:function(e,t,n){"use strict";t.__esModule=!0,t.Popper=void 0;var r=n(37809),o=n(9333);function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}var a=function(e){var t,n;function a(){var t;return(t=e.call(this)||this).renderedContent=void 0,t.popperInstance=void 0,a.id+=1,t}n=e,(t=a).prototype=Object.create(n.prototype),t.prototype.constructor=t,i(t,n);var c=a.prototype;return c.componentDidMount=function(){var e=this,t=this.props,n=t.additionalStyles,i=t.options;if(this.renderedContent=document.createElement("div"),n)for(var a=0,c=Object.entries(n);a=0||(o[n]=e[n]);return o}(e,u),y=(0,o.scale)(n,l,f),b=g!==undefined,_=p||(0,o.keyOfMatchingRange)(n,v)||"default",w=(0,a.computeBoxProps)(m),x=["ProgressBar",t,(0,a.computeBoxClassName)(m)],S={width:100*(0,o.clamp01)(y)+"%"};return c.CSS_COLORS.includes(_)||"default"===_?x.push("ProgressBar--color--"+_):(w.style=(w.style||"")+"border-color: "+_+";",S["background-color"]=_),(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,i.classes)(x),[(0,r.createVNode)(1,"div","ProgressBar__fill ProgressBar__fill--animated",null,1,{style:S}),(0,r.createVNode)(1,"div","ProgressBar__content",b?g:(0,o.toFixed)(100*y)+"%",0)],4,Object.assign({},w)))};t.ProgressBar=s,s.defaultHooks=i.pureComponentHooks},20159:function(e,t,n){"use strict";t.__esModule=!0,t.RestrictedInput=void 0;var r=n(9333),o=n(54666),i=n(42991),a=n(89314),c=n(92547),u=["onChange","onEnter","onInput","value"],s=["className","fluid","monospace"];function l(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function d(e,t){return d=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},d(e,t)}var f=function(e,t,n,r){var o=t||0,a=n||0===n?n:1e4;if(!e||!e.length)return String(o);var c=r?parseFloat(e.replace(/[^\-\d.]/g,"")):parseInt(e.replace(/[^\-\d]/g,""),10);return isNaN(c)?String(o):String((0,i.clamp)(c,o,a))},p=function(e){var t,n;function i(){var t;return(t=e.call(this)||this).inputRef=(0,r.createRef)(),t.state={editing:!1},t.handleBlur=function(e){t.state.editing&&t.setEditing(!1)},t.handleChange=function(e){var n=t.props,r=n.maxValue,o=n.minValue,i=n.onChange,a=n.allowFloats;e.target.value=f(e.target.value,o,r,a),i&&i(e,+e.target.value)},t.handleFocus=function(e){t.state.editing||t.setEditing(!0)},t.handleInput=function(e){var n=t.state.editing,r=t.props.onInput;n||t.setEditing(!0),r&&r(e,+e.target.value)},t.handleKeyDown=function(e){var n=t.props,r=n.maxValue,o=n.minValue,i=n.onChange,a=n.onEnter,u=n.allowFloats;if(e.keyCode===c.KEY_ENTER){var s=f(e.target.value,o,r,u);return t.setEditing(!1),i&&i(e,+s),a&&a(e,+s),void e.target.blur()}if(e.keyCode===c.KEY_ESCAPE)return t.props.onEscape?void t.props.onEscape(e):(t.setEditing(!1),e.target.value=t.props.value,void e.target.blur())},t}n=e,(t=i).prototype=Object.create(n.prototype),t.prototype.constructor=t,d(t,n);var p=i.prototype;return p.componentDidMount=function(){var e,t=this,n=this.props,r=n.maxValue,o=n.minValue,i=n.allowFloats,a=null==(e=this.props.value)?void 0:e.toString(),c=this.inputRef.current;c&&(c.value=f(a,o,r,i)),(this.props.autoFocus||this.props.autoSelect)&&setTimeout((function(){c.focus(),t.props.autoSelect&&c.select()}),1)},p.componentDidUpdate=function(e,t){var n,r,o=this.props,i=o.maxValue,a=o.minValue,c=o.allowFloats,u=this.state.editing,s=null==(n=e.value)?void 0:n.toString(),l=null==(r=this.props.value)?void 0:r.toString(),d=this.inputRef.current;d&&!u&&l!==s&&l!==d.value&&(d.value=f(l,a,i,c))},p.setEditing=function(e){this.setState({editing:e})},p.render=function(){var e=this.props,t=(e.onChange,e.onEnter,e.onInput,e.value,l(e,u)),n=t.className,i=t.fluid,c=t.monospace,d=l(t,s);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,a.Box,Object.assign({className:(0,o.classes)(["Input",i&&"Input--fluid",c&&"Input--monospace",n])},d,{children:[(0,r.createVNode)(1,"div","Input__baseline",".",16),(0,r.createVNode)(64,"input","Input__input",null,1,{onChange:this.handleChange,onInput:this.handleInput,onFocus:this.handleFocus,onBlur:this.handleBlur,onKeyDown:this.handleKeyDown,type:"number"},null,this.inputRef)]})))},i}(r.Component);t.RestrictedInput=p},58566:function(e,t,n){"use strict";t.__esModule=!0,t.RoundGauge=void 0;var r=n(9333),o=n(42991),i=n(54666),a=n(77988),c=n(89314),u=["value","minValue","maxValue","ranges","alertAfter","alertBefore","format","size","className","style"];t.RoundGauge=function(e){if(Byond.IS_LTE_IE8)return(0,r.normalizeProps)((0,r.createComponentVNode)(2,a.AnimatedNumber,Object.assign({},e)));var t=e.value,n=e.minValue,s=void 0===n?1:n,l=e.maxValue,d=void 0===l?1:l,f=e.ranges,p=e.alertAfter,h=e.alertBefore,v=e.format,g=e.size,m=void 0===g?1:g,y=e.className,b=e.style,_=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,u),w=(0,o.scale)(t,s,d),x=(0,o.clamp01)(w),S=f?{}:{primary:[0,1]};f&&Object.keys(f).forEach((function(e){var t=f[e];S[e]=[(0,o.scale)(t[0],s,d),(0,o.scale)(t[1],s,d)]}));var C=function(){if(p&&h&&pt)return!0}else if(pt)return!0;return!1}()&&(0,o.keyOfMatchingRange)(x,S);return(0,r.createComponentVNode)(2,c.Box,{inline:!0,children:[(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,i.classes)(["RoundGauge",y,(0,c.computeBoxClassName)(_)]),(0,r.createVNode)(32,"svg",null,[(p||h)&&(0,r.createVNode)(32,"g",(0,i.classes)(["RoundGauge__alert",C?"active RoundGauge__alert--"+C:""]),(0,r.createVNode)(32,"path",null,null,1,{d:"M48.211,14.578C48.55,13.9 49.242,13.472 50,13.472C50.758,13.472 51.45,13.9 51.789,14.578C54.793,20.587 60.795,32.589 63.553,38.106C63.863,38.726 63.83,39.462 63.465,40.051C63.101,40.641 62.457,41 61.764,41C55.996,41 44.004,41 38.236,41C37.543,41 36.899,40.641 36.535,40.051C36.17,39.462 36.137,38.726 36.447,38.106C39.205,32.589 45.207,20.587 48.211,14.578ZM50,34.417C51.426,34.417 52.583,35.574 52.583,37C52.583,38.426 51.426,39.583 50,39.583C48.574,39.583 47.417,38.426 47.417,37C47.417,35.574 48.574,34.417 50,34.417ZM50,32.75C50,32.75 53,31.805 53,22.25C53,20.594 51.656,19.25 50,19.25C48.344,19.25 47,20.594 47,22.25C47,31.805 50,32.75 50,32.75Z"}),2),(0,r.createVNode)(32,"g",null,(0,r.createVNode)(32,"circle","RoundGauge__ringTrack",null,1,{cx:"50",cy:"50",r:"45"}),2),(0,r.createVNode)(32,"g",null,Object.keys(S).map((function(e,t){var n=S[e];return(0,r.createVNode)(32,"circle","RoundGauge__ringFill RoundGauge--color--"+e,null,1,{style:{"stroke-dashoffset":Math.max((2-(n[1]-n[0]))*Math.PI*50,0)},transform:"rotate("+(180+180*n[0])+" 50 50)",cx:"50",cy:"50",r:"45"},t)})),0),(0,r.createVNode)(32,"g","RoundGauge__needle",[(0,r.createVNode)(32,"polygon","RoundGauge__needleLine",null,1,{points:"46,50 50,0 54,50"}),(0,r.createVNode)(32,"circle","RoundGauge__needleMiddle",null,1,{cx:"50",cy:"50",r:"8"})],4,{transform:"rotate("+(180*x-90)+" 50 50)"})],0,{viewBox:"0 0 100 50"}),2,Object.assign({},(0,c.computeBoxProps)(Object.assign({style:Object.assign({"font-size":m+"em"},b)},_))))),(0,r.createComponentVNode)(2,a.AnimatedNumber,{value:t,format:v,size:m})]})}},17008:function(e,t,n){"use strict";t.__esModule=!0,t.Section=void 0;var r=n(9333),o=n(54666),i=n(34443),a=n(89314),c=["className","title","buttons","fill","fitted","scrollable","scrollableHorizontal","flexGrow","noTopPadding","stretchContents","children","onScroll"];function u(e,t){return u=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},u(e,t)}var s=function(e){var t,n;function s(t){var n;return(n=e.call(this,t)||this).scrollableRef=void 0,n.scrollable=void 0,n.onScroll=void 0,n.scrollableHorizontal=void 0,n.scrollableRef=t.scrollableRef||(0,r.createRef)(),n.scrollable=t.scrollable,n.onScroll=t.onScroll,n.scrollableHorizontal=t.scrollableHorizontal,n}n=e,(t=s).prototype=Object.create(n.prototype),t.prototype.constructor=t,u(t,n);var l=s.prototype;return l.componentDidMount=function(){(this.scrollable||this.scrollableHorizontal)&&((0,i.addScrollableNode)(this.scrollableRef.current),this.onScroll&&this.scrollableRef.current&&(this.scrollableRef.current.onscroll=this.onScroll))},l.componentWillUnmount=function(){(this.scrollable||this.scrollableHorizontal)&&(0,i.removeScrollableNode)(this.scrollableRef.current)},l.render=function(){var e=this.props,t=e.className,n=e.title,i=e.buttons,u=e.fill,s=e.fitted,l=e.scrollable,d=e.scrollableHorizontal,f=e.flexGrow,p=e.noTopPadding,h=e.stretchContents,v=e.children,g=e.onScroll,m=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,c),y=(0,o.canRender)(n)||(0,o.canRender)(i);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Section",Byond.IS_LTE_IE8&&"Section--iefix",u&&"Section--fill",s&&"Section--fitted",l&&"Section--scrollable",d&&"Section--scrollableHorizontal",f&&"Section--flex",t,(0,a.computeBoxClassName)(m)]),[y&&(0,r.createVNode)(1,"div","Section__title",[(0,r.createVNode)(1,"span","Section__titleText",n,0),(0,r.createVNode)(1,"div","Section__buttons",i,0)],4),(0,r.createVNode)(1,"div","Section__rest",(0,r.createVNode)(1,"div",(0,o.classes)(["Section__content",!!h&&"Section__content--stretchContents",!!p&&"Section__content--noTopPadding"]),v,0,{onScroll:g},null,this.scrollableRef),0)],0,Object.assign({},(0,a.computeBoxProps)(m))))},s}(r.Component);t.Section=s},92354:function(e,t,n){"use strict";t.__esModule=!0,t.Slider=void 0;var r=n(9333),o=n(42991),i=n(54666),a=n(89314),c=n(58747),u=n(97874),s=["animated","format","maxValue","minValue","onChange","onDrag","step","stepPixelSize","suppressFlicker","unit","value","className","fillValue","color","ranges","children"];t.Slider=function(e){if(Byond.IS_LTE_IE8)return(0,r.normalizeProps)((0,r.createComponentVNode)(2,u.NumberInput,Object.assign({},e)));var t=e.animated,n=e.format,l=e.maxValue,d=e.minValue,f=e.onChange,p=e.onDrag,h=e.step,v=e.stepPixelSize,g=e.suppressFlicker,m=e.unit,y=e.value,b=e.className,_=e.fillValue,w=e.color,x=e.ranges,S=void 0===x?{}:x,C=e.children,E=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,s),N=C!==undefined;return(0,r.normalizeProps)((0,r.createComponentVNode)(2,c.DraggableControl,Object.assign({dragMatrix:[1,0]},{animated:t,format:n,maxValue:l,minValue:d,onChange:f,onDrag:p,step:h,stepPixelSize:v,suppressFlicker:g,unit:m,value:y},{children:function(e){var t=e.dragging,n=(e.editing,e.value),c=e.displayValue,u=e.displayElement,s=e.inputElement,f=e.handleDragStart,p=_!==undefined&&null!==_,h=((0,o.scale)(n,d,l),(0,o.scale)(null!=_?_:c,d,l)),v=(0,o.scale)(c,d,l),g=w||(0,o.keyOfMatchingRange)(null!=_?_:n,S)||"default";return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,i.classes)(["Slider","ProgressBar","ProgressBar--color--"+g,b,(0,a.computeBoxClassName)(E)]),[(0,r.createVNode)(1,"div",(0,i.classes)(["ProgressBar__fill",p&&"ProgressBar__fill--animated"]),null,1,{style:{width:100*(0,o.clamp01)(h)+"%",opacity:.4}}),(0,r.createVNode)(1,"div","ProgressBar__fill",null,1,{style:{width:100*(0,o.clamp01)(Math.min(h,v))+"%"}}),(0,r.createVNode)(1,"div","Slider__cursorOffset",[(0,r.createVNode)(1,"div","Slider__cursor"),(0,r.createVNode)(1,"div","Slider__pointer"),t&&(0,r.createVNode)(1,"div","Slider__popupValue",u,0)],0,{style:{width:100*(0,o.clamp01)(v)+"%"}}),(0,r.createVNode)(1,"div","ProgressBar__content",N?C:u,0),s],0,Object.assign({},(0,a.computeBoxProps)(E),{onMouseDown:f})))}})))}},40254:function(e,t,n){"use strict";t.__esModule=!0,t.Stack=void 0;var r=n(9333),o=n(54666),i=n(63152),a=["className","vertical","fill"],c=["className","innerRef"],u=["className","hidden"];function s(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var l=function(e){var t=e.className,n=e.vertical,c=e.fill,u=s(e,a);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Stack",c&&"Stack--fill",n?"Stack--vertical":"Stack--horizontal",t,(0,i.computeFlexClassName)(e)]),null,1,Object.assign({},(0,i.computeFlexProps)(Object.assign({direction:n?"column":"row"},u)))))};t.Stack=l;l.Item=function(e){var t=e.className,n=e.innerRef,a=s(e,c);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Stack__item",t,(0,i.computeFlexItemClassName)(a)]),null,1,Object.assign({},(0,i.computeFlexItemProps)(a)),null,n))};l.Divider=function(e){var t=e.className,n=e.hidden,a=s(e,u);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Stack__item","Stack__divider",n&&"Stack__divider--hidden",t,(0,i.computeFlexItemClassName)(a)]),null,1,Object.assign({},(0,i.computeFlexItemProps)(a))))}},38391:function(e,t,n){"use strict";t.__esModule=!0,t.StyleableSection=void 0;var r=n(9333),o=n(89314);t.StyleableSection=function(e){return(0,r.createComponentVNode)(2,o.Box,{style:e.style,children:[(0,r.createComponentVNode)(2,o.Box,{"class":"Section__title",style:e.titleStyle,children:[(0,r.createComponentVNode)(2,o.Box,{"class":"Section__titleText",style:e.textStyle,children:e.title}),(0,r.createVNode)(1,"div","Section__buttons",e.titleSubtext,0)]}),(0,r.createComponentVNode)(2,o.Box,{"class":"Section__rest",children:(0,r.createComponentVNode)(2,o.Box,{"class":"Section__content",children:e.children})})]})}},37470:function(e,t,n){"use strict";t.__esModule=!0,t.TableRow=t.TableCell=t.Table=void 0;var r=n(9333),o=n(54666),i=n(89314),a=["className","collapsing","children"],c=["className","header"],u=["className","collapsing","header"];function s(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var l=function(e){var t=e.className,n=e.collapsing,c=e.children,u=s(e,a);return(0,r.normalizeProps)((0,r.createVNode)(1,"table",(0,o.classes)(["Table",n&&"Table--collapsing",t,(0,i.computeBoxClassName)(u)]),(0,r.createVNode)(1,"tbody",null,c,0),2,Object.assign({},(0,i.computeBoxProps)(u))))};t.Table=l,l.defaultHooks=o.pureComponentHooks;var d=function(e){var t=e.className,n=e.header,a=s(e,c);return(0,r.normalizeProps)((0,r.createVNode)(1,"tr",(0,o.classes)(["Table__row",n&&"Table__row--header",t,(0,i.computeBoxClassName)(e)]),null,1,Object.assign({},(0,i.computeBoxProps)(a))))};t.TableRow=d,d.defaultHooks=o.pureComponentHooks;var f=function(e){var t=e.className,n=e.collapsing,a=e.header,c=s(e,u);return(0,r.normalizeProps)((0,r.createVNode)(1,"td",(0,o.classes)(["Table__cell",n&&"Table__cell--collapsing",a&&"Table__cell--header",t,(0,i.computeBoxClassName)(e)]),null,1,Object.assign({},(0,i.computeBoxProps)(c))))};t.TableCell=f,f.defaultHooks=o.pureComponentHooks,l.Row=d,l.Cell=f},76279:function(e,t,n){"use strict";t.__esModule=!0,t.Tabs=void 0;var r=n(9333),o=n(54666),i=n(89314),a=n(92854),c=["className","vertical","fill","fluid","children"],u=["className","selected","color","icon","leftSlot","rightSlot","children"];function s(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var l=function(e){var t=e.className,n=e.vertical,a=e.fill,u=e.fluid,l=e.children,d=s(e,c);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Tabs",n?"Tabs--vertical":"Tabs--horizontal",a&&"Tabs--fill",u&&"Tabs--fluid",t,(0,i.computeBoxClassName)(d)]),l,0,Object.assign({},(0,i.computeBoxProps)(d))))};t.Tabs=l;l.Tab=function(e){var t=e.className,n=e.selected,c=e.color,l=e.icon,d=e.leftSlot,f=e.rightSlot,p=e.children,h=s(e,u);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Tab","Tabs__Tab","Tab--color--"+c,n&&"Tab--selected",t].concat((0,i.computeBoxClassName)(h))),[(0,o.canRender)(d)&&(0,r.createVNode)(1,"div","Tab__left",d,0)||!!l&&(0,r.createVNode)(1,"div","Tab__left",(0,r.createComponentVNode)(2,a.Icon,{name:l}),2),(0,r.createVNode)(1,"div","Tab__text",p,0),(0,o.canRender)(f)&&(0,r.createVNode)(1,"div","Tab__right",f,0)],0,Object.assign({},(0,i.computeBoxProps)(h))))}},2231:function(e,t,n){"use strict";t.__esModule=!0,t.TextArea=void 0;var r=n(9333),o=n(54666),i=n(89314),a=n(53856),c=n(92547),u=["onChange","onKeyDown","onKeyPress","onInput","onFocus","onBlur","onEnter","value","maxLength","placeholder","scrollbar","noborder","displayedValue"],s=["className","fluid","nowrap"];function l(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function d(e,t){return d=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},d(e,t)}var f=function(e){var t,n;function f(t,n){var o;(o=e.call(this,t,n)||this).textareaRef=t.innerRef||(0,r.createRef)(),o.state={editing:!1,scrolledAmount:0};var i=t.dontUseTabForIndent,u=void 0!==i&&i;return o.handleOnInput=function(e){var t=o.state.editing,n=o.props.onInput;t||o.setEditing(!0),n&&n(e,e.target.value)},o.handleOnChange=function(e){var t=o.state.editing,n=o.props.onChange;t&&o.setEditing(!1),n&&n(e,e.target.value)},o.handleKeyPress=function(e){var t=o.state.editing,n=o.props.onKeyPress;t||o.setEditing(!0),n&&n(e,e.target.value)},o.handleKeyDown=function(e){var t=o.state.editing,n=o.props,r=n.onChange,i=n.onInput,s=n.onEnter,l=n.onKey;if(e.keyCode===c.KEY_ENTER)return o.setEditing(!1),r&&r(e,e.target.value),i&&i(e,e.target.value),s&&s(e,e.target.value),void(o.props.selfClear&&(e.target.value="",e.target.blur()));if(e.keyCode===c.KEY_ESCAPE)return o.props.onEscape&&o.props.onEscape(e),o.setEditing(!1),void(o.props.selfClear?e.target.value="":(e.target.value=(0,a.toInputValue)(o.props.value),e.target.blur()));if((t||o.setEditing(!0),l&&l(e,e.target.value),!u)&&(e.keyCode||e.which)===c.KEY_TAB){e.preventDefault();var d=e.target,f=d.value,p=d.selectionStart,h=d.selectionEnd;e.target.value=f.substring(0,p)+"\t"+f.substring(h),e.target.selectionEnd=p+1,i&&i(e,e.target.value)}},o.handleFocus=function(e){o.state.editing||o.setEditing(!0)},o.handleBlur=function(e){var t=o.state.editing,n=o.props.onChange;t&&(o.setEditing(!1),n&&n(e,e.target.value))},o.handleScroll=function(e){var t=o.props.displayedValue,n=o.textareaRef.current;t&&n&&o.setState({scrolledAmount:n.scrollTop})},o}n=e,(t=f).prototype=Object.create(n.prototype),t.prototype.constructor=t,d(t,n);var p=f.prototype;return p.componentDidMount=function(){var e=this,t=this.props.value,n=this.textareaRef.current;n&&(n.value=(0,a.toInputValue)(t)),(this.props.autoFocus||this.props.autoSelect)&&setTimeout((function(){n.focus(),e.props.autoSelect&&n.select()}),1)},p.componentDidUpdate=function(e,t){var n=e.value,r=this.props.value,o=this.textareaRef.current;o&&"string"==typeof r&&n!==r&&(o.value=(0,a.toInputValue)(r))},p.setEditing=function(e){this.setState({editing:e})},p.getValue=function(){return this.textareaRef.current&&this.textareaRef.current.value},p.render=function(){var e=this.props,t=(e.onChange,e.onKeyDown,e.onKeyPress,e.onInput,e.onFocus,e.onBlur,e.onEnter,e.value,e.maxLength),n=e.placeholder,a=e.scrollbar,c=e.noborder,d=e.displayedValue,f=l(e,u),p=f.className,h=f.fluid,v=f.nowrap,g=l(f,s),m=this.state.scrolledAmount;return(0,r.normalizeProps)((0,r.createComponentVNode)(2,i.Box,Object.assign({className:(0,o.classes)(["TextArea",h&&"TextArea--fluid",c&&"TextArea--noborder",p])},g,{children:[!!d&&(0,r.createComponentVNode)(2,i.Box,{position:"absolute",width:"100%",height:"100%",overflow:"hidden",children:(0,r.createVNode)(1,"div",(0,o.classes)(["TextArea__textarea","TextArea__textarea_custom"]),d,0,{style:{transform:"translateY(-"+m+"px)"}})}),(0,r.createVNode)(128,"textarea",(0,o.classes)(["TextArea__textarea",a&&"TextArea__textarea--scrollable",v&&"TextArea__nowrap"]),null,1,{placeholder:n,onChange:this.handleOnChange,onKeyDown:this.handleKeyDown,onKeyPress:this.handleKeyPress,onInput:this.handleOnInput,onFocus:this.handleFocus,onBlur:this.handleBlur,onScroll:this.handleScroll,maxLength:t,style:{color:d?"rgba(0, 0, 0, 0)":"inherit"}},null,this.textareaRef)]})))},f}(r.Component);t.TextArea=f},27996:function(e,t,n){"use strict";t.__esModule=!0,t.TimeDisplay=void 0;var r=n(77742),o=n(9333);function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}var a=function(e){return"number"==typeof e&&Number.isFinite(e)&&!Number.isNaN(e)},c=function(e){var t,n;function o(t){var n;return(n=e.call(this,t)||this).timer=null,n.last_seen_value=undefined,n.state={value:0},a(t.value)&&(n.state.value=Number(t.value),n.last_seen_value=Number(t.value)),n}n=e,(t=o).prototype=Object.create(n.prototype),t.prototype.constructor=t,i(t,n);var c=o.prototype;return c.componentDidUpdate=function(){var e=this;this.props.auto!==undefined&&(clearInterval(this.timer),this.timer=setInterval((function(){return e.tick()}),1e3))},c.tick=function(){var e=Number(this.state.value);this.props.value!==this.last_seen_value&&(this.last_seen_value=this.props.value,e=this.props.value);var t="up"===this.props.auto?10:-10,n=Math.max(0,e+t);this.setState({value:n})},c.componentDidMount=function(){var e=this;this.props.auto!==undefined&&(this.timer=setInterval((function(){return e.tick()}),1e3))},c.componentWillUnmount=function(){clearInterval(this.timer)},c.render=function(){var e=this.state.value;return a(e)?(0,r.formatTime)(e):this.state.value||null},o}(o.Component);t.TimeDisplay=c},4136:function(e,t,n){"use strict";t.__esModule=!0,t.Tooltip=void 0;var r=n(9333),o=n(37809);function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}var a={modifiers:[{name:"eventListeners",enabled:!1}]},c={width:0,height:0,top:0,right:0,bottom:0,left:0,x:0,y:0,toJSON:function(){return null}},u=function(e){var t,n;function c(){return e.apply(this,arguments)||this}n=e,(t=c).prototype=Object.create(n.prototype),t.prototype.constructor=t,i(t,n);var u=c.prototype;return u.getDOMNode=function(){return(0,r.findDOMfromVNode)(this.$LI,!0)},u.componentDidMount=function(){var e=this,t=this.getDOMNode();t&&(t.addEventListener("mouseenter",(function(){var n=c.renderedTooltip;n===undefined&&((n=document.createElement("div")).className="Tooltip",document.body.appendChild(n),c.renderedTooltip=n),c.currentHoveredElement=t,n.style.opacity="1",e.renderPopperContent()})),t.addEventListener("mouseleave",(function(){e.fadeOut()})))},u.fadeOut=function(){c.currentHoveredElement===this.getDOMNode()&&(c.currentHoveredElement=undefined,c.renderedTooltip.style.opacity="0")},u.renderPopperContent=function(){var e=this,t=c.renderedTooltip;t&&(0,r.render)((0,r.createVNode)(1,"span",null,this.props.content,0),t,(function(){var n=c.singletonPopper;n===undefined?(n=(0,o.createPopper)(c.virtualElement,t,Object.assign({},a,{placement:e.props.position||"auto"})),c.singletonPopper=n):(n.setOptions(Object.assign({},a,{placement:e.props.position||"auto"})),n.update())}),this.context)},u.componentDidUpdate=function(){c.currentHoveredElement===this.getDOMNode()&&this.renderPopperContent()},u.componentWillUnmount=function(){this.fadeOut()},u.render=function(){return this.props.children},c}(r.Component);t.Tooltip=u,u.renderedTooltip=void 0,u.singletonPopper=void 0,u.currentHoveredElement=void 0,u.virtualElement={getBoundingClientRect:function(){var e,t;return null!=(e=null==(t=u.currentHoveredElement)?void 0:t.getBoundingClientRect())?e:c}}},60924:function(e,t,n){"use strict";t.__esModule=!0,t.TrackOutsideClicks=void 0;var r=n(9333);function o(e,t){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},o(e,t)}var i=function(e){var t,n;function i(){var t;return(t=e.call(this)||this).ref=(0,r.createRef)(),t.handleOutsideClick=t.handleOutsideClick.bind(function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(t)),document.addEventListener("click",t.handleOutsideClick),t}n=e,(t=i).prototype=Object.create(n.prototype),t.prototype.constructor=t,o(t,n);var a=i.prototype;return a.componentWillUnmount=function(){document.removeEventListener("click",this.handleOutsideClick)},a.handleOutsideClick=function(e){e.target instanceof Node&&this.ref.current&&!this.ref.current.contains(e.target)&&this.props.onOutsideClick()},a.render=function(){return(0,r.createVNode)(1,"div",null,this.props.children,0,null,null,this.ref)},i}(r.Component);t.TrackOutsideClicks=i},13435:function(e,t,n){"use strict";t.__esModule=!0,t.TrackOutsideClicks=t.Tooltip=t.TimeDisplay=t.TextArea=t.Tabs=t.Table=t.StyleableSection=t.Stack=t.Slider=t.Section=t.RoundGauge=t.RestrictedInput=t.ProgressBar=t.Popper=t.NumberInput=t.NoticeBox=t.NanoMap=t.Modal=t.MenuBar=t.LabeledList=t.LabeledControls=t.Knob=t.KeyListener=t.Input=t.InfinitePlane=t.Icon=t.Grid=t.Flex=t.FitText=t.Dropdown=t.DraggableControl=t.Divider=t.Dimmer=t.Dialog=t.ColorBox=t.Collapsible=t.Chart=t.ByondUi=t.Button=t.Box=t.BlockQuote=t.Blink=t.Autofocus=t.AnimatedNumber=void 0;var r=n(77988);t.AnimatedNumber=r.AnimatedNumber;var o=n(36787);t.Autofocus=o.Autofocus;var i=n(57971);t.Blink=i.Blink;var a=n(36154);t.BlockQuote=a.BlockQuote;var c=n(89314);t.Box=c.Box;var u=n(21782);t.Button=u.Button;var s=n(93269);t.ByondUi=s.ByondUi;var l=n(46625);t.Chart=l.Chart;var d=n(8877);t.Collapsible=d.Collapsible;var f=n(30821);t.ColorBox=f.ColorBox;var p=n(17597);t.Dimmer=p.Dimmer;var h=n(54580);t.Divider=h.Divider;var v=n(58747);t.DraggableControl=v.DraggableControl;var g=n(46051);t.Dropdown=g.Dropdown;var m=n(63152);t.Flex=m.Flex;var y=n(4817);t.FitText=y.FitText;var b=n(4177);t.Grid=b.Grid;var _=n(92854);t.Icon=_.Icon;var w=n(21191);t.InfinitePlane=w.InfinitePlane;var x=n(53856);t.Input=x.Input;var S=n(66581);t.KeyListener=S.KeyListener;var C=n(9972);t.Knob=C.Knob;var E=n(93341);t.LabeledControls=E.LabeledControls;var N=n(40514);t.LabeledList=N.LabeledList;var O=n(38101);t.MenuBar=O.MenuBar;var M=n(98005);t.Modal=M.Modal;var k=n(25764);t.NanoMap=k.NanoMap;var T=n(68210);t.NoticeBox=T.NoticeBox;var I=n(97874);t.NumberInput=I.NumberInput;var A=n(41117);t.ProgressBar=A.ProgressBar;var P=n(91679);t.Popper=P.Popper;var L=n(20159);t.RestrictedInput=L.RestrictedInput;var V=n(58566);t.RoundGauge=V.RoundGauge;var B=n(17008);t.Section=B.Section;var j=n(92354);t.Slider=j.Slider;var R=n(38391);t.StyleableSection=R.StyleableSection;var D=n(40254);t.Stack=D.Stack;var F=n(37470);t.Table=F.Table;var Y=n(76279);t.Tabs=Y.Tabs;var K=n(2231);t.TextArea=K.TextArea;var U=n(27996);t.TimeDisplay=U.TimeDisplay;var z=n(60924);t.TrackOutsideClicks=z.TrackOutsideClicks;var H=n(4136);t.Tooltip=H.Tooltip;var G=n(65120);t.Dialog=G.Dialog},36711:function(e,t){"use strict";t.__esModule=!0,t.getGasLabel=t.getGasFromId=t.getGasColor=t.UI_UPDATE=t.UI_INTERACTIVE=t.UI_DISABLED=t.UI_CLOSE=t.T0C=t.RADIO_CHANNELS=t.CSS_COLORS=t.COLORS=void 0;t.T0C=273.15;t.UI_INTERACTIVE=2;t.UI_UPDATE=1;t.UI_DISABLED=0;t.UI_CLOSE=-1;t.COLORS={department:{captain:"#c06616",security:"#e74c3c",medbay:"#3498db",science:"#9b59b6",engineering:"#f1c40f",cargo:"#f39c12",centcom:"#00c100",other:"#c38312"},manifest:{command:"#3333FF",security:"#8e0000",medical:"#006600",engineering:"#b27300",science:"#a65ba6",cargo:"#bb9040",planetside:"#555555",civilian:"#a32800",miscellaneous:"#666666",silicon:"#222222"},damageType:{oxy:"#3498db",toxin:"#2ecc71",burn:"#e67e22",brute:"#e74c3c"},reagent:{acidicbuffer:"#fbc314",basicbuffer:"#3853a4"}};t.CSS_COLORS=["black","white","red","orange","yellow","olive","green","teal","blue","violet","purple","pink","brown","grey","good","average","bad","label"];t.RADIO_CHANNELS=[{name:"Mercenary",freq:1213,color:"#6D3F40"},{name:"Raider",freq:1277,color:"#6D3F40"},{name:"Special Ops",freq:1341,color:"#5C5C8A"},{name:"AI Private",freq:1343,color:"#FF00FF"},{name:"Response Team",freq:1345,color:"#5C5C8A"},{name:"Supply",freq:1347,color:"#5F4519"},{name:"Service",freq:1349,color:"#6eaa2c"},{name:"Science",freq:1351,color:"#993399"},{name:"Command",freq:1353,color:"#193A7A"},{name:"Medical",freq:1355,color:"#008160"},{name:"Engineering",freq:1357,color:"#A66300"},{name:"Security",freq:1359,color:"#A30000"},{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"}];var n=[{id:"oxygen",name:"Oxygen",label:"O\u2082",color:"blue"},{id:"nitrogen",name:"Nitrogen",label:"N\u2082",color:"green"},{id:"carbon_dioxide",name:"Carbon Dioxide",label:"CO\u2082",color:"grey"},{id:"phoron",name:"Phoron",label:"Phoron",color:"pink"},{id:"volatile_fuel",name:"Volatile Fuel",label:"EXP",color:"teal"},{id:"nitrous_oxide",name:"Nitrous Oxide",label:"N\u2082O",color:"red"},{id:"other",name:"Other",label:"Other",color:"white"},{id:"pressure",name:"Pressure",label:"Pressure",color:"average"},{id:"temperature",name:"Temperature",label:"Temperature",color:"yellow"}];t.getGasLabel=function(e,t){if(!e)return t||"None";for(var r=e.toLowerCase(),o=e.replace(/(^\w{1})|(\s+\w{1})/g,(function(e){return e.toUpperCase()})),i=0;i=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),S(n),d}},"catch":function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;S(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:E(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=undefined),d}},e}function u(e,t,n,r,o,i,a){try{var c=e[i](a),u=c.value}catch(s){return void n(s)}c.done?t(u):Promise.resolve(u).then(r,o)}function s(e){return function(){var t=this,n=arguments;return new Promise((function(r,o){var i=e.apply(t,n);function a(e){u(i,r,o,a,c,"next",e)}function c(e){u(i,r,o,a,c,"throw",e)}a(undefined)}))}}var l,d,f,p,h,v=(0,i.createLogger)("drag"),g=null!=(r=window.devicePixelRatio)?r:1,m=Byond.windowId,y=!1,b=!1,_=[0,0];t.setWindowKey=function(e){m=e};var w=function(){return[window.screenLeft*g,window.screenTop*g]};t.getWindowPosition=w;var x=function(){return[window.innerWidth*g,window.innerHeight*g]};t.getWindowSize=x;var S=function(e){var t=(0,o.vecAdd)(e,_);return Byond.winset(Byond.windowId,{pos:t[0]+","+t[1]})},C=function(e){return Byond.winset(Byond.windowId,{size:e[0]+"x"+e[1]})},E=function(){return[window.screen.availWidth*g,window.screen.availHeight*g]},N=function(e,t,n){void 0===n&&(n=50);for(var r,o=[t],i=0;iu&&(o[a]=u-t[a],i=!0)}return[i,o]};t.dragStartHandler=function(e){var t;v.log("drag start"),y=!0,d=(0,o.vecSubtract)([e.screenX,e.screenY],w()),null==(t=e.target)||t.focus(),document.addEventListener("mousemove",A),document.addEventListener("mouseup",I),A(e)};var I=function V(e){v.log("drag end"),A(e),document.removeEventListener("mousemove",A),document.removeEventListener("mouseup",V),y=!1,O()},A=function(e){y&&(e.preventDefault(),S((0,o.vecSubtract)([e.screenX,e.screenY],d)))};t.resizeStartHandler=function(e,t){return function(n){var r;f=[e,t],v.log("resize start",f),b=!0,d=(0,o.vecSubtract)([n.screenX,n.screenY],w()),p=x(),null==(r=n.target)||r.focus(),document.addEventListener("mousemove",L),document.addEventListener("mouseup",P),L(n)}};var P=function B(e){v.log("resize end",h),L(e),document.removeEventListener("mousemove",L),document.removeEventListener("mouseup",B),b=!1,O()},L=function(e){if(b){e.preventDefault();var t=(0,o.vecSubtract)([e.screenX,e.screenY],w()),n=(0,o.vecSubtract)(t,d);(h=(0,o.vecAdd)(p,(0,o.vecMultiply)(f,n),[1,1]))[0]=Math.max(h[0],150*g),h[1]=Math.max(h[1],50*g),C(h)}}},34443:function(e,t,n){"use strict";t.__esModule=!0,t.setupGlobalEvents=t.removeScrollableNode=t.globalEvents=t.canStealFocus=t.addScrollableNode=t.KeyEvent=void 0;var r=n(92547),o=new(n(70088).EventEmitter);t.globalEvents=o;var i,a=!1;t.setupGlobalEvents=function(e){void 0===e&&(e={}),a=!!e.ignoreWindowFocus};var c=!0,u=function m(e,t){a?c=!0:(i&&(clearTimeout(i),i=null),t?i=setTimeout((function(){return m(e)})):c!==e&&(c=e,o.emit(e?"window-focus":"window-blur"),o.emit("window-focus-change",e)))},s=null,l=function(e){var t=String(e.tagName).toLowerCase();return"input"===t||"textarea"===t};t.canStealFocus=l;var d=function y(){s&&(s.removeEventListener("blur",y),s=null)},f=null,p=null,h=[];t.addScrollableNode=function(e){h.push(e)};t.removeScrollableNode=function(e){var t=h.indexOf(e);t>=0&&h.splice(t,1)};window.addEventListener("mousemove",(function(e){var t=e.target;t!==p&&(p=t,function(e){if(!s&&c)for(var t=document.body;e&&e!==t;){if(h.includes(e)){if(e.contains(f))return;return f=e,void e.focus()}e=e.parentElement}}(t))})),window.addEventListener("focusin",(function(e){if(p=null,f=e.target,u(!0),l(e.target))return t=e.target,d(),void(s=t).addEventListener("blur",d);var t})),window.addEventListener("focusout",(function(e){p=null,u(!1,!0)})),window.addEventListener("blur",(function(e){p=null,u(!1,!0)})),window.addEventListener("beforeunload",(function(e){u(!1)}));var v={},g=function(){function e(e,t,n){this.event=void 0,this.type=void 0,this.code=void 0,this.ctrl=void 0,this.shift=void 0,this.alt=void 0,this.repeat=void 0,this._str=void 0,this.event=e,this.type=t,this.code=e.keyCode,this.ctrl=e.ctrlKey,this.shift=e.shiftKey,this.alt=e.altKey,this.repeat=!!n}var t=e.prototype;return t.hasModifierKeys=function(){return this.ctrl||this.alt||this.shift},t.isModifierKey=function(){return this.code===r.KEY_CTRL||this.code===r.KEY_SHIFT||this.code===r.KEY_ALT},t.isDown=function(){return"keydown"===this.type},t.isUp=function(){return"keyup"===this.type},t.toString=function(){return this._str||(this._str="",this.ctrl&&(this._str+="Ctrl+"),this.alt&&(this._str+="Alt+"),this.shift&&(this._str+="Shift+"),this.code>=48&&this.code<=90?this._str+=String.fromCharCode(this.code):this.code>=r.KEY_F1&&this.code<=r.KEY_F12?this._str+="F"+(this.code-111):this._str+="["+this.code+"]"),this._str},e}();t.KeyEvent=g,document.addEventListener("keydown",(function(e){if(!l(e.target)){var t=e.keyCode,n=new g(e,"keydown",v[t]);o.emit("keydown",n),o.emit("key",n),v[t]=!0}})),document.addEventListener("keyup",(function(e){if(!l(e.target)){var t=e.keyCode,n=new g(e,"keyup");o.emit("keyup",n),o.emit("key",n),v[t]=!1}}))},19396:function(e,t){"use strict";t.__esModule=!0,t.focusWindow=t.focusMap=void 0;t.focusMap=function(){Byond.winset("mapwindow.map",{focus:!0})};t.focusWindow=function(){Byond.winset(Byond.windowId,{focus:!0})}},77742:function(e,t){"use strict";t.__esModule=!0,t.formatTime=t.formatSiUnit=t.formatSiBaseTenUnit=t.formatPower=t.formatMoney=t.formatDb=t.formatCommaNumber=void 0;var n=["f","p","n","\u03bc","m"," ","k","M","G","T","P","E","Z","Y","R","Q","F","N","H"],r=n.indexOf(" "),o=function(e,t,o){if(void 0===t&&(t=-r),void 0===o&&(o=""),!isFinite(e))return e.toString();var i=Math.floor(Math.log10(Math.abs(e))),a=Math.max(3*t,i),c=Math.floor(a/3),u=n[Math.min(c+r,n.length-1)],s=(e/Math.pow(1e3,c)).toFixed(2);return s.endsWith(".00")?s=s.slice(0,-3):s.endsWith(".0")&&(s=s.slice(0,-2)),(s+" "+u.trim()+o).trim()};t.formatSiUnit=o;t.formatPower=function(e,t){return void 0===t&&(t=0),o(e,t,"W")};t.formatMoney=function(e,t){if(void 0===t&&(t=0),!Number.isFinite(e))return String(e);var n=Number(e.toFixed(t)),r=n<0,o=Math.abs(n).toString().split(".");o[0]=o[0].replace(/\B(?=(\d{3})+(?!\d))/g,"\u2009");var i=o.join(".");return r?"-"+i:i};t.formatDb=function(e){var t=20*Math.log10(e),n=t>=0?"+":"-",r=Math.abs(t);return""+n+(r=r===Infinity?"Inf":r.toFixed(2))+" dB"};var i=["","\xb7 10\xb3","\xb7 10\u2076","\xb7 10\u2079","\xb7 10\xb9\xb2","\xb7 10\xb9\u2075","\xb7 10\xb9\u2078","\xb7 10\xb2\xb9","\xb7 10\xb2\u2074","\xb7 10\xb2\u2077","\xb7 10\xb3\u2070","\xb7 10\xb3\xb3","\xb7 10\xb3\u2076","\xb7 10\xb3\u2079"];t.formatSiBaseTenUnit=function(e,t,n){if(void 0===t&&(t=0),void 0===n&&(n=""),!isFinite(e))return"NaN";var r=Math.floor(Math.log10(e)),o=Math.max(3*t,r),a=Math.floor(o/3),c=i[a],u=e/Math.pow(1e3,a),s=Math.max(0,2-o%3);return(u.toFixed(s)+" "+c+" "+n).trim()};t.formatTime=function(e,t){void 0===t&&(t="default");var n=Math.floor(e/10),r=Math.floor(n/3600),o=Math.floor(n%3600/60),i=n%60;return"short"===t?""+(r>0?r+"h":"")+(o>0?o+"m":"")+(i>0?i+"s":""):String(r).padStart(2,"0")+":"+String(o).padStart(2,"0")+":"+String(i).padStart(2,"0")};t.formatCommaNumber=function(e){if(!Number.isFinite(e))return e;var t=e.toString().split(".");return t[0]=t[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),t.join(".")}},15268:function(e,t,n){"use strict";t.__esModule=!0,t.setupHotKeys=t.releaseHotKey=t.releaseHeldKeys=t.listenForKeyEvents=t.acquireHotKey=void 0;var r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{"default":e};var n=i(t);if(n&&n.has(e))return n.get(e);var r={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var c=o?Object.getOwnPropertyDescriptor(e,a):null;c&&(c.get||c.set)?Object.defineProperty(r,a,c):r[a]=e[a]}r["default"]=e,n&&n.set(e,r);return r}(n(92547)),o=n(34443);function i(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(i=function(e){return e?n:t})(e)}var a=(0,n(78196).createLogger)("hotkeys"),c={},u=[r.KEY_ESCAPE,r.KEY_ENTER,r.KEY_SPACE,r.KEY_TAB,r.KEY_CTRL,r.KEY_SHIFT,r.KEY_UP,r.KEY_DOWN,r.KEY_LEFT,r.KEY_RIGHT,r.KEY_F5],s={},l=[],d=function(e){var t=String(e);if("Ctrl+F5"!==t&&"Ctrl+R"!==t){if("Ctrl+F"!==t&&!(e.event.defaultPrevented||e.isModifierKey()||u.includes(e.code))){var n,r=16===(n=e.code)?"Shift":17===n?"Ctrl":18===n?"Alt":33===n?"Northeast":34===n?"Southeast":35===n?"Southwest":36===n?"Northwest":37===n?"West":38===n?"North":39===n?"East":40===n?"South":45===n?"Insert":46===n?"Delete":n>=48&&n<=57||n>=65&&n<=90?String.fromCharCode(n):n>=96&&n<=105?"Numpad"+(n-96):n>=112&&n<=123?"F"+(n-111):188===n?",":189===n?"-":190===n?".":void 0;if(r){var o=c[r];if(o)return a.debug("macro",o),Byond.command(o);if(e.isDown()&&!s[r]){s[r]=!0;var i='TguiKeyDown "'+r+'"';return a.debug(i),Byond.command(i)}if(e.isUp()&&s[r]){s[r]=!1;var l='TguiKeyUp "'+r+'"';return a.debug(l),Byond.command(l)}}}}else location.reload()};t.acquireHotKey=function(e){u.push(e)};t.releaseHotKey=function(e){var t=u.indexOf(e);t>=0&&u.splice(t,1)};var f=function(){for(var e=0,t=Object.keys(s);e=0||(o[n]=e[n]);return o}var l=function(e){var t=e.className,n=e.theme,a=void 0===n?"nanotrasen":n,u=e.children,l=s(e,c);return(0,r.createVNode)(1,"div","theme-"+a,(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Layout",t,(0,i.computeBoxClassName)(l)]),u,0,Object.assign({},(0,i.computeBoxProps)(l)))),2)};t.Layout=l;var d=function(e){var t=e.className,n=e.scrollable,a=e.children,c=s(e,u);return(0,r.normalizeProps)((0,r.createVNode)(1,"div",(0,o.classes)(["Layout__content",n&&"Layout__content--scrollable",t,(0,i.computeBoxClassName)(c)]),a,0,Object.assign({},(0,i.computeBoxProps)(c))))};d.defaultHooks={onComponentDidMount:function(e){return(0,a.addScrollableNode)(e)},onComponentWillUnmount:function(e){return(0,a.removeScrollableNode)(e)}},l.Content=d},53062:function(e,t,n){"use strict";t.__esModule=!0,t.NtosWindow=void 0;var r=n(9333),o=n(48936),i=n(57905),a=n(13435),c=n(26318),u=function(e,t){var n=e.title,u=e.width,s=void 0===u?575:u,l=e.height,d=void 0===l?700:l,f=e.children,p=(0,i.useBackend)(t),h=p.act,v=p.data,g=v.PC_device_theme,m=v.PC_batteryicon,y=v.PC_showbatteryicon,b=v.PC_batterypercent,_=v.PC_ntneticon,w=v.PC_stationdate,x=v.PC_stationtime,S=v.PC_programheaders,C=void 0===S?[]:S,E=v.PC_showexitprogram;return(0,r.createComponentVNode)(2,c.Window,{title:n,width:s,height:d,theme:g,children:(0,r.createVNode)(1,"div","NtosWindow",[(0,r.createVNode)(1,"div","NtosWindow__header NtosHeader",[(0,r.createVNode)(1,"div","NtosHeader__left",[(0,r.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,mr:2,children:[(0,r.createComponentVNode)(2,a.Button,{width:"26px",lineHeight:"22px",textAlign:"left",tooltip:w,color:"transparent",icon:"calendar",tooltipPosition:"bottom"}),x]}),(0,r.createComponentVNode)(2,a.Box,{inline:!0,italic:!0,mr:2,opacity:.33,children:"syndicate"===g?"Syndix":"NtOS"})],4),(0,r.createVNode)(1,"div","NtosHeader__right",[C.map((function(e){return(0,r.createComponentVNode)(2,a.Box,{inline:!0,mr:1,children:(0,r.createVNode)(1,"img","NtosHeader__icon",null,1,{src:(0,o.resolveAsset)(e.icon)})},e.icon)})),(0,r.createComponentVNode)(2,a.Box,{inline:!0,children:_&&(0,r.createVNode)(1,"img","NtosHeader__icon",null,1,{src:(0,o.resolveAsset)(_)})}),!(!y||!m)&&(0,r.createComponentVNode)(2,a.Box,{inline:!0,mr:1,children:[(0,r.createVNode)(1,"img","NtosHeader__icon",null,1,{src:(0,o.resolveAsset)(m)}),b&&b]}),!!E&&(0,r.createComponentVNode)(2,a.Button,{width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"window-minimize-o",tooltip:"Minimize",tooltipPosition:"bottom",onClick:function(){return h("PC_minimize")}}),!!E&&(0,r.createComponentVNode)(2,a.Button,{mr:"-3px",width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"window-close-o",tooltip:"Close",tooltipPosition:"bottom-start",onClick:function(){return h("PC_exit")}}),!E&&(0,r.createComponentVNode)(2,a.Button,{mr:"-3px",width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"power-off",tooltip:"Power off",tooltipPosition:"bottom-start",onClick:function(){return h("PC_shutdown")}})],0)],4),f],0)})};t.NtosWindow=u;u.Content=function(e){return(0,r.createVNode)(1,"div","NtosWindow__content",(0,r.normalizeProps)((0,r.createComponentVNode)(2,c.Window.Content,Object.assign({},e))),2)}},16432:function(e,t,n){"use strict";t.__esModule=!0,t.Pane=void 0;var r=n(9333),o=n(54666),i=n(57905),a=n(13435),c=n(53201),u=n(3851),s=["theme","children","className"],l=["className","fitted","children"];function d(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}var f=function(e,t){var n=e.theme,l=e.children,f=e.className,p=d(e,s),h=(0,i.useBackend)(t).suspended,v=(0,c.useDebug)(t).debugLayout;return(0,r.normalizeProps)((0,r.createComponentVNode)(2,u.Layout,Object.assign({className:(0,o.classes)(["Window",f]),theme:n},p,{children:(0,r.createComponentVNode)(2,a.Box,{fillPositionedParent:!0,className:v&&"debug-layout",children:!h&&l})})))};t.Pane=f;f.Content=function(e){var t=e.className,n=e.fitted,i=e.children,a=d(e,l);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,u.Layout.Content,Object.assign({className:(0,o.classes)(["Window__content",t])},a,{children:n&&i||(0,r.createVNode)(1,"div","Window__contentPadding",i,0)})))}},26318:function(e,t,n){"use strict";t.__esModule=!0,t.Window=void 0;var r=n(9333),o=n(54666),i=n(78737),a=n(96940),c=n(57905),u=n(13435),s=n(36711),l=n(53201),d=(n(70755),n(41655)),f=n(78196),p=n(3851),h=["className","fitted","children"];function v(e,t){return v=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},v(e,t)}var g=(0,f.createLogger)("Window"),m=[400,600],y=function(e){var t,n;function u(){return e.apply(this,arguments)||this}n=e,(t=u).prototype=Object.create(n.prototype),t.prototype.constructor=t,v(t,n);var f=u.prototype;return f.componentDidMount=function(){var e=(0,c.useBackend)(this.context).suspended,t=this.props.canClose,n=void 0===t||t;e||(Byond.winset(Byond.windowId,{"can-close":Boolean(n)}),g.log("mounting"),this.updateGeometry())},f.componentDidUpdate=function(e){(this.props.width!==e.width||this.props.height!==e.height)&&this.updateGeometry()},f.updateGeometry=function(){var e,t=(0,c.useBackend)(this.context).config,n=Object.assign({size:m},t.window);this.props.width&&this.props.height&&(n.size=[this.props.width,this.props.height]),null!=(e=t.window)&&e.key&&(0,d.setWindowKey)(t.window.key),(0,d.recallWindowGeometry)(n)},f.render=function(){var e,t=this.props,n=t.canClose,u=void 0===n||n,f=t.theme,h=t.title,v=t.children,m=t.buttons,y=(0,c.useBackend)(this.context),b=y.config,w=y.suspended,x=(0,l.useDebug)(this.context).debugLayout,S=(0,i.useDispatch)(this.context),C=null==(e=b.window)?void 0:e.fancy,E=b.user&&(b.user.observer?b.status=0||(o[n]=e[n]);return o}(e,h);return(0,r.normalizeProps)((0,r.createComponentVNode)(2,p.Layout.Content,Object.assign({className:(0,o.classes)(["Window__content",t])},a,{children:n&&i||(0,r.createVNode)(1,"div","Window__contentPadding",i,0)})))};var b=function(e){switch(e){case s.UI_INTERACTIVE:return"good";case s.UI_UPDATE:return"average";case s.UI_DISABLED:default:return"bad"}},_=function(e,t){var n=e.className,c=e.title,s=e.status,l=e.canClose,d=e.fancy,f=e.onDragStart,p=e.onClose,h=e.children,v=((0,i.useDispatch)(t),"string"==typeof c&&c===c.toLowerCase()&&(0,a.toTitleCase)(c)||c);return(0,r.createVNode)(1,"div",(0,o.classes)(["TitleBar",n]),[s===undefined&&(0,r.createComponentVNode)(2,u.Icon,{className:"TitleBar__statusIcon",name:"tools",opacity:.5})||(0,r.createComponentVNode)(2,u.Icon,{className:"TitleBar__statusIcon",color:b(s),name:"eye"}),(0,r.createVNode)(1,"div","TitleBar__dragZone",null,1,{onMousedown:function(e){return d&&f(e)}}),(0,r.createVNode)(1,"div","TitleBar__title",[v,!!h&&(0,r.createVNode)(1,"div","TitleBar__buttons",h,0)],0),!1,Boolean(d&&l)&&(0,r.createVNode)(1,"div","TitleBar__close TitleBar__clickable",Byond.IS_LTE_IE8?"x":"\xd7",0,{onclick:p})],0)}},59979:function(e,t,n){"use strict";t.__esModule=!0,t.Window=t.Pane=t.NtosWindow=t.Layout=void 0;var r=n(3851);t.Layout=r.Layout;var o=n(53062);t.NtosWindow=o.NtosWindow;var i=n(16432);t.Pane=i.Pane;var a=n(26318);t.Window=a.Window},87731:function(e,t){"use strict";t.__esModule=!0,t.captureExternalLinks=void 0;t.captureExternalLinks=function(){document.addEventListener("click",(function(e){for(var t=e.target;;){if(!t||t===document.body)return;if("a"===String(t.tagName).toLowerCase())break;t=t.parentElement}var n=t.getAttribute("href")||"";if(!("?"===n.charAt(0)||n.startsWith("byond://"))){e.preventDefault();var r=n;r.toLowerCase().startsWith("www")&&(r="https://"+r),Byond.sendMessage({type:"openLink",url:r})}}))}},78196:function(e,t,n){"use strict";t.__esModule=!0,t.logger=t.createLogger=void 0;n(17651);var r=0,o=1,i=2,a=3,c=4,u=function(e,t){void 0===t&&(t="Generic");for(var n=arguments.length,r=new Array(n>2?n-2:0),o=2;o=i){var a=[t].concat(r).map((function(e){return"string"==typeof e?e:e instanceof Error?e.stack||String(e):JSON.stringify(e)})).filter((function(e){return e})).join(" ")+"\nUser Agent: "+navigator.userAgent;Byond.sendMessage({type:"log",ns:t,message:a})}},s=function(e){return{debug:function(){for(var t=arguments.length,n=new Array(t),o=0;o0&&(0,o.round)(c.width)/e.offsetWidth||1,s=e.offsetHeight>0&&(0,o.round)(c.height)/e.offsetHeight||1);var l=((0,r.isElement)(e)?(0,i["default"])(e):window).visualViewport,f=!(0,a["default"])()&&n,d=(c.left+(f&&l?l.offsetLeft:0))/u,p=(c.top+(f&&l?l.offsetTop:0))/s,h=c.width/u,g=c.height/s;return{width:h,height:g,top:p,right:d+h,bottom:p+g,left:d,x:d,y:p}};var r=n(75011),o=n(14194),i=c(n(1866)),a=c(n(45407));function c(e){return e&&e.__esModule?e:{"default":e}}},35823:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t,n,r){var o="clippingParents"===t?function(e){var t=(0,a["default"])((0,d["default"])(e)),n=["absolute","fixed"].indexOf((0,s["default"])(e).position)>=0,r=n&&(0,l.isHTMLElement)(e)?(0,c["default"])(e):e;if(!(0,l.isElement)(r))return[];return t.filter((function(e){return(0,l.isElement)(e)&&(0,p["default"])(e,r)&&"body"!==(0,h["default"])(e)}))}(e):[].concat(t),i=[].concat(o,[n]),u=i[0],f=i.reduce((function(t,n){var o=y(e,n,r);return t.top=(0,v.max)(o.top,t.top),t.right=(0,v.min)(o.right,t.right),t.bottom=(0,v.min)(o.bottom,t.bottom),t.left=(0,v.max)(o.left,t.left),t}),y(e,u,r));return f.width=f.right-f.left,f.height=f.bottom-f.top,f.x=f.left,f.y=f.top,f};var r=n(83996),o=m(n(75047)),i=m(n(37407)),a=m(n(97262)),c=m(n(66689)),u=m(n(36748)),s=m(n(77060)),l=n(75011),f=m(n(97617)),d=m(n(84330)),p=m(n(89691)),h=m(n(72793)),g=m(n(14834)),v=n(14194);function m(e){return e&&e.__esModule?e:{"default":e}}function y(e,t,n){return t===r.viewport?(0,g["default"])((0,o["default"])(e,n)):(0,l.isElement)(t)?function(e,t){var n=(0,f["default"])(e,!1,"fixed"===t);return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}(t,n):(0,g["default"])((0,i["default"])((0,u["default"])(e)))}},4254:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t,n){void 0===n&&(n=!1);var f=(0,a.isHTMLElement)(t),d=(0,a.isHTMLElement)(t)&&function(e){var t=e.getBoundingClientRect(),n=(0,l.round)(t.width)/e.offsetWidth||1,r=(0,l.round)(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(t),p=(0,u["default"])(t),h=(0,r["default"])(e,d,n),g={scrollLeft:0,scrollTop:0},v={x:0,y:0};(f||!f&&!n)&&(("body"!==(0,i["default"])(t)||(0,s["default"])(p))&&(g=(0,o["default"])(t)),(0,a.isHTMLElement)(t)?((v=(0,r["default"])(t,!0)).x+=t.clientLeft,v.y+=t.clientTop):p&&(v.x=(0,c["default"])(p)));return{x:h.left+g.scrollLeft-v.x,y:h.top+g.scrollTop-v.y,width:h.width,height:h.height}};var r=f(n(97617)),o=f(n(86394)),i=f(n(72793)),a=n(75011),c=f(n(44653)),u=f(n(36748)),s=f(n(9135)),l=n(14194);function f(e){return e&&e.__esModule?e:{"default":e}}},77060:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return(0,o["default"])(e).getComputedStyle(e)};var r,o=(r=n(1866))&&r.__esModule?r:{"default":r}},36748:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return(((0,r.isElement)(e)?e.ownerDocument:e.document)||window.document).documentElement};var r=n(75011)},37407:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t,n=(0,r["default"])(e),u=(0,a["default"])(e),s=null==(t=e.ownerDocument)?void 0:t.body,l=(0,c.max)(n.scrollWidth,n.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),f=(0,c.max)(n.scrollHeight,n.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),d=-u.scrollLeft+(0,i["default"])(e),p=-u.scrollTop;"rtl"===(0,o["default"])(s||n).direction&&(d+=(0,c.max)(n.clientWidth,s?s.clientWidth:0)-l);return{width:l,height:f,x:d,y:p}};var r=u(n(36748)),o=u(n(77060)),i=u(n(44653)),a=u(n(10416)),c=n(14194);function u(e){return e&&e.__esModule?e:{"default":e}}},89821:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}}},92957:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,o["default"])(e),n=e.offsetWidth,r=e.offsetHeight;Math.abs(t.width-n)<=1&&(n=t.width);Math.abs(t.height-r)<=1&&(r=t.height);return{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}};var r,o=(r=n(97617))&&r.__esModule?r:{"default":r}},72793:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e?(e.nodeName||"").toLowerCase():null}},86394:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return e!==(0,o["default"])(e)&&(0,i.isHTMLElement)(e)?(0,a["default"])(e):(0,r["default"])(e)};var r=c(n(10416)),o=c(n(1866)),i=n(75011),a=c(n(89821));function c(e){return e&&e.__esModule?e:{"default":e}}},66689:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,r["default"])(e),n=f(e);for(;n&&(0,c["default"])(n)&&"static"===(0,i["default"])(n).position;)n=f(n);if(n&&("html"===(0,o["default"])(n)||"body"===(0,o["default"])(n)&&"static"===(0,i["default"])(n).position))return t;return n||function(e){var t=/firefox/i.test((0,s["default"])());if(/Trident/i.test((0,s["default"])())&&(0,a.isHTMLElement)(e)){if("fixed"===(0,i["default"])(e).position)return null}var n=(0,u["default"])(e);(0,a.isShadowRoot)(n)&&(n=n.host);for(;(0,a.isHTMLElement)(n)&&["html","body"].indexOf((0,o["default"])(n))<0;){var r=(0,i["default"])(n);if("none"!==r.transform||"none"!==r.perspective||"paint"===r.contain||-1!==["transform","perspective"].indexOf(r.willChange)||t&&"filter"===r.willChange||t&&r.filter&&"none"!==r.filter)return n;n=n.parentNode}return null}(e)||t};var r=l(n(1866)),o=l(n(72793)),i=l(n(77060)),a=n(75011),c=l(n(46795)),u=l(n(84330)),s=l(n(36110));function l(e){return e&&e.__esModule?e:{"default":e}}function f(e){return(0,a.isHTMLElement)(e)&&"fixed"!==(0,i["default"])(e).position?e.offsetParent:null}},84330:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){if("html"===(0,r["default"])(e))return e;return e.assignedSlot||e.parentNode||((0,i.isShadowRoot)(e)?e.host:null)||(0,o["default"])(e)};var r=a(n(72793)),o=a(n(36748)),i=n(75011);function a(e){return e&&e.__esModule?e:{"default":e}}},89523:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function u(e){if(["html","body","#document"].indexOf((0,i["default"])(e))>=0)return e.ownerDocument.body;if((0,a.isHTMLElement)(e)&&(0,o["default"])(e))return e;return u((0,r["default"])(e))};var r=c(n(84330)),o=c(n(9135)),i=c(n(72793)),a=n(75011);function c(e){return e&&e.__esModule?e:{"default":e}}},75047:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t){var n=(0,r["default"])(e),c=(0,o["default"])(e),u=n.visualViewport,s=c.clientWidth,l=c.clientHeight,f=0,d=0;if(u){s=u.width,l=u.height;var p=(0,a["default"])();(p||!p&&"fixed"===t)&&(f=u.offsetLeft,d=u.offsetTop)}return{width:s,height:l,x:f+(0,i["default"])(e),y:d}};var r=c(n(1866)),o=c(n(36748)),i=c(n(44653)),a=c(n(45407));function c(e){return e&&e.__esModule?e:{"default":e}}},1866:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}},10416:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,o["default"])(e),n=t.pageXOffset,r=t.pageYOffset;return{scrollLeft:n,scrollTop:r}};var r,o=(r=n(1866))&&r.__esModule?r:{"default":r}},44653:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return(0,r["default"])((0,o["default"])(e)).left+(0,i["default"])(e).scrollLeft};var r=a(n(97617)),o=a(n(36748)),i=a(n(10416));function a(e){return e&&e.__esModule?e:{"default":e}}},75011:function(e,t,n){"use strict";t.__esModule=!0,t.isElement=function(e){var t=(0,o["default"])(e).Element;return e instanceof t||e instanceof Element},t.isHTMLElement=function(e){var t=(0,o["default"])(e).HTMLElement;return e instanceof t||e instanceof HTMLElement},t.isShadowRoot=function(e){if("undefined"==typeof ShadowRoot)return!1;var t=(0,o["default"])(e).ShadowRoot;return e instanceof t||e instanceof ShadowRoot};var r,o=(r=n(1866))&&r.__esModule?r:{"default":r}},45407:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(){return!/^((?!chrome|android).)*safari/i.test((0,o["default"])())};var r,o=(r=n(36110))&&r.__esModule?r:{"default":r}},9135:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,o["default"])(e),n=t.overflow,r=t.overflowX,i=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+i+r)};var r,o=(r=n(77060))&&r.__esModule?r:{"default":r}},46795:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return["table","td","th"].indexOf((0,o["default"])(e))>=0};var r,o=(r=n(72793))&&r.__esModule?r:{"default":r}},97262:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function u(e,t){var n;void 0===t&&(t=[]);var c=(0,r["default"])(e),s=c===(null==(n=e.ownerDocument)?void 0:n.body),l=(0,i["default"])(c),f=s?[l].concat(l.visualViewport||[],(0,a["default"])(c)?c:[]):c,d=t.concat(f);return s?d:d.concat(u((0,o["default"])(f)))};var r=c(n(89523)),o=c(n(84330)),i=c(n(1866)),a=c(n(9135));function c(e){return e&&e.__esModule?e:{"default":e}}},83996:function(e,t){"use strict";t.__esModule=!0,t.write=t.viewport=t.variationPlacements=t.top=t.start=t.right=t.reference=t.read=t.popper=t.placements=t.modifierPhases=t.main=t.left=t.end=t.clippingParents=t.bottom=t.beforeWrite=t.beforeRead=t.beforeMain=t.basePlacements=t.auto=t.afterWrite=t.afterRead=t.afterMain=void 0;var n=t.top="top",r=t.bottom="bottom",o=t.right="right",i=t.left="left",a=t.auto="auto",c=t.basePlacements=[n,r,o,i],u=t.start="start",s=t.end="end",l=(t.clippingParents="clippingParents",t.viewport="viewport",t.popper="popper",t.reference="reference",t.variationPlacements=c.reduce((function(e,t){return e.concat([t+"-"+u,t+"-"+s])}),[]),t.placements=[].concat(c,[a]).reduce((function(e,t){return e.concat([t,t+"-"+u,t+"-"+s])}),[]),t.beforeRead="beforeRead"),f=t.read="read",d=t.afterRead="afterRead",p=t.beforeMain="beforeMain",h=t.main="main",g=t.afterMain="afterMain",v=t.beforeWrite="beforeWrite",m=t.write="write",y=t.afterWrite="afterWrite";t.modifierPhases=[l,f,d,p,h,g,v,m,y]},92935:function(e,t,n){"use strict";t.__esModule=!0;var r={popperGenerator:!0,detectOverflow:!0,createPopperBase:!0,createPopper:!0,createPopperLite:!0};t.popperGenerator=t.detectOverflow=t.createPopperLite=t.createPopperBase=t.createPopper=void 0;var o=n(83996);Object.keys(o).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(r,e)||e in t&&t[e]===o[e]||(t[e]=o[e]))}));var i=n(97934);Object.keys(i).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(r,e)||e in t&&t[e]===i[e]||(t[e]=i[e]))}));var a=n(50252);t.popperGenerator=a.popperGenerator,t.detectOverflow=a.detectOverflow,t.createPopperBase=a.createPopper;var c=n(1728);t.createPopper=c.createPopper;var u=n(88037);t.createPopperLite=u.createPopper},38621:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r,o=(r=n(72793))&&r.__esModule?r:{"default":r},i=n(75011);t["default"]={name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var n=t.styles[e]||{},r=t.attributes[e]||{},a=t.elements[e];(0,i.isHTMLElement)(a)&&(0,o["default"])(a)&&(Object.assign(a.style,n),Object.keys(r).forEach((function(e){var t=r[e];!1===t?a.removeAttribute(e):a.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach((function(e){var r=t.elements[e],a=t.attributes[e]||{},c=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:n[e]).reduce((function(e,t){return e[t]="",e}),{});(0,i.isHTMLElement)(r)&&(0,o["default"])(r)&&(Object.assign(r.style,c),Object.keys(a).forEach((function(e){r.removeAttribute(e)})))}))}},requires:["computeStyles"]}},90860:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r=d(n(85312)),o=d(n(92957)),i=d(n(89691)),a=d(n(66689)),c=d(n(86274)),u=n(52855),s=d(n(10632)),l=d(n(59597)),f=n(83996);function d(e){return e&&e.__esModule?e:{"default":e}}var p=function(e,t){return e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e,(0,s["default"])("number"!=typeof e?e:(0,l["default"])(e,f.basePlacements))};t["default"]={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,i=e.name,s=e.options,l=n.elements.arrow,d=n.modifiersData.popperOffsets,h=(0,r["default"])(n.placement),g=(0,c["default"])(h),v=[f.left,f.right].indexOf(h)>=0?"height":"width";if(l&&d){var m=p(s.padding,n),y=(0,o["default"])(l),b="y"===g?f.top:f.left,_="y"===g?f.bottom:f.right,w=n.rects.reference[v]+n.rects.reference[g]-d[g]-n.rects.popper[v],x=d[g]-n.rects.reference[g],S=(0,a["default"])(l),C=S?"y"===g?S.clientHeight||0:S.clientWidth||0:0,E=w/2-x/2,N=m[b],O=C-y[v]-m[_],M=C/2-y[v]/2+E,k=(0,u.within)(N,M,O),T=g;n.modifiersData[i]=((t={})[T]=k,t.centerOffset=k-M,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&(0,i["default"])(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]}},15224:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0,t.mapToStyles=p;var r=n(83996),o=f(n(66689)),i=f(n(1866)),a=f(n(36748)),c=f(n(77060)),u=f(n(85312)),s=f(n(48218)),l=n(14194);function f(e){return e&&e.__esModule?e:{"default":e}}var d={top:"auto",right:"auto",bottom:"auto",left:"auto"};function p(e){var t,n=e.popper,u=e.popperRect,s=e.placement,f=e.variation,p=e.offsets,h=e.position,g=e.gpuAcceleration,v=e.adaptive,m=e.roundOffsets,y=e.isFixed,b=p.x,_=void 0===b?0:b,w=p.y,x=void 0===w?0:w,S="function"==typeof m?m({x:_,y:x}):{x:_,y:x};_=S.x,x=S.y;var C=p.hasOwnProperty("x"),E=p.hasOwnProperty("y"),N=r.left,O=r.top,M=window;if(v){var k=(0,o["default"])(n),T="clientHeight",I="clientWidth";if(k===(0,i["default"])(n)&&(k=(0,a["default"])(n),"static"!==(0,c["default"])(k).position&&"absolute"===h&&(T="scrollHeight",I="scrollWidth")),s===r.top||(s===r.left||s===r.right)&&f===r.end)O=r.bottom,x-=(y&&k===M&&M.visualViewport?M.visualViewport.height:k[T])-u.height,x*=g?1:-1;if(s===r.left||(s===r.top||s===r.bottom)&&f===r.end)N=r.right,_-=(y&&k===M&&M.visualViewport?M.visualViewport.width:k[I])-u.width,_*=g?1:-1}var A,P=Object.assign({position:h},v&&d),L=!0===m?function(e,t){var n=e.x,r=e.y,o=t.devicePixelRatio||1;return{x:(0,l.round)(n*o)/o||0,y:(0,l.round)(r*o)/o||0}}({x:_,y:x},(0,i["default"])(n)):{x:_,y:x};return _=L.x,x=L.y,g?Object.assign({},P,((A={})[O]=E?"0":"",A[N]=C?"0":"",A.transform=(M.devicePixelRatio||1)<=1?"translate("+_+"px, "+x+"px)":"translate3d("+_+"px, "+x+"px, 0)",A)):Object.assign({},P,((t={})[O]=E?x+"px":"",t[N]=C?_+"px":"",t.transform="",t))}t["default"]={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,n=e.options,r=n.gpuAcceleration,o=void 0===r||r,i=n.adaptive,a=void 0===i||i,c=n.roundOffsets,l=void 0===c||c,f={placement:(0,u["default"])(t.placement),variation:(0,s["default"])(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:o,isFixed:"fixed"===t.options.strategy};null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,p(Object.assign({},f,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:a,roundOffsets:l})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,p(Object.assign({},f,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}}},59953:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r,o=(r=n(1866))&&r.__esModule?r:{"default":r};var i={passive:!0};t["default"]={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var t=e.state,n=e.instance,r=e.options,a=r.scroll,c=void 0===a||a,u=r.resize,s=void 0===u||u,l=(0,o["default"])(t.elements.popper),f=[].concat(t.scrollParents.reference,t.scrollParents.popper);return c&&f.forEach((function(e){e.addEventListener("scroll",n.update,i)})),s&&l.addEventListener("resize",n.update,i),function(){c&&f.forEach((function(e){e.removeEventListener("scroll",n.update,i)})),s&&l.removeEventListener("resize",n.update,i)}},data:{}}},21128:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r=l(n(72310)),o=l(n(85312)),i=l(n(53379)),a=l(n(49883)),c=l(n(67450)),u=n(83996),s=l(n(48218));function l(e){return e&&e.__esModule?e:{"default":e}}t["default"]={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,l=e.name;if(!t.modifiersData[l]._skip){for(var f=n.mainAxis,d=void 0===f||f,p=n.altAxis,h=void 0===p||p,g=n.fallbackPlacements,v=n.padding,m=n.boundary,y=n.rootBoundary,b=n.altBoundary,_=n.flipVariations,w=void 0===_||_,x=n.allowedAutoPlacements,S=t.options.placement,C=(0,o["default"])(S),E=g||(C===S||!w?[(0,r["default"])(S)]:function(e){if((0,o["default"])(e)===u.auto)return[];var t=(0,r["default"])(e);return[(0,i["default"])(e),t,(0,i["default"])(t)]}(S)),N=[S].concat(E).reduce((function(e,n){return e.concat((0,o["default"])(n)===u.auto?(0,c["default"])(t,{placement:n,boundary:m,rootBoundary:y,padding:v,flipVariations:w,allowedAutoPlacements:x}):n)}),[]),O=t.rects.reference,M=t.rects.popper,k=new Map,T=!0,I=N[0],A=0;A=0,j=B?"width":"height",R=(0,a["default"])(t,{placement:P,boundary:m,rootBoundary:y,altBoundary:b,padding:v}),D=B?V?u.right:u.left:V?u.bottom:u.top;O[j]>M[j]&&(D=(0,r["default"])(D));var F=(0,r["default"])(D),Y=[];if(d&&Y.push(R[L]<=0),h&&Y.push(R[D]<=0,R[F]<=0),Y.every((function(e){return e}))){I=P,T=!1;break}k.set(P,Y)}if(T)for(var K=function(e){var t=N.find((function(t){var n=k.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return I=t,"break"},U=w?3:1;U>0;U--){if("break"===K(U))break}t.placement!==I&&(t.modifiersData[l]._skip=!0,t.placement=I,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}}},17945:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r,o=n(83996),i=(r=n(49883))&&r.__esModule?r:{"default":r};function a(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function c(e){return[o.top,o.right,o.bottom,o.left].some((function(t){return e[t]>=0}))}t["default"]={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,u=t.modifiersData.preventOverflow,s=(0,i["default"])(t,{elementContext:"reference"}),l=(0,i["default"])(t,{altBoundary:!0}),f=a(s,r),d=a(l,o,u),p=c(f),h=c(d);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:d,isReferenceHidden:p,hasPopperEscaped:h},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":h})}}},97934:function(e,t,n){"use strict";t.__esModule=!0,t.preventOverflow=t.popperOffsets=t.offset=t.hide=t.flip=t.eventListeners=t.computeStyles=t.arrow=t.applyStyles=void 0;var r=d(n(38621));t.applyStyles=r["default"];var o=d(n(90860));t.arrow=o["default"];var i=d(n(15224));t.computeStyles=i["default"];var a=d(n(59953));t.eventListeners=a["default"];var c=d(n(21128));t.flip=c["default"];var u=d(n(17945));t.hide=u["default"];var s=d(n(90642));t.offset=s["default"];var l=d(n(23786));t.popperOffsets=l["default"];var f=d(n(78230));function d(e){return e&&e.__esModule?e:{"default":e}}t.preventOverflow=f["default"]},90642:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0,t.distanceAndSkiddingToXY=a;var r,o=(r=n(85312))&&r.__esModule?r:{"default":r},i=n(83996);function a(e,t,n){var r=(0,o["default"])(e),a=[i.left,i.top].indexOf(r)>=0?-1:1,c="function"==typeof n?n(Object.assign({},t,{placement:e})):n,u=c[0],s=c[1];return u=u||0,s=(s||0)*a,[i.left,i.right].indexOf(r)>=0?{x:s,y:u}:{x:u,y:s}}t["default"]={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.offset,c=void 0===o?[0,0]:o,u=i.placements.reduce((function(e,n){return e[n]=a(n,t.rects,c),e}),{}),s=u[t.placement],l=s.x,f=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=l,t.modifiersData.popperOffsets.y+=f),t.modifiersData[r]=u}}},23786:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r,o=(r=n(85694))&&r.__esModule?r:{"default":r};t["default"]={name:"popperOffsets",enabled:!0,phase:"read",fn:function(e){var t=e.state,n=e.name;t.modifiersData[n]=(0,o["default"])({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})},data:{}}},78230:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var r=n(83996),o=h(n(85312)),i=h(n(86274)),a=h(n(4320)),c=n(52855),u=h(n(92957)),s=h(n(66689)),l=h(n(49883)),f=h(n(48218)),d=h(n(23941)),p=n(14194);function h(e){return e&&e.__esModule?e:{"default":e}}t["default"]={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,h=e.name,g=n.mainAxis,v=void 0===g||g,m=n.altAxis,y=void 0!==m&&m,b=n.boundary,_=n.rootBoundary,w=n.altBoundary,x=n.padding,S=n.tether,C=void 0===S||S,E=n.tetherOffset,N=void 0===E?0:E,O=(0,l["default"])(t,{boundary:b,rootBoundary:_,padding:x,altBoundary:w}),M=(0,o["default"])(t.placement),k=(0,f["default"])(t.placement),T=!k,I=(0,i["default"])(M),A=(0,a["default"])(I),P=t.modifiersData.popperOffsets,L=t.rects.reference,V=t.rects.popper,B="function"==typeof N?N(Object.assign({},t.rects,{placement:t.placement})):N,j="number"==typeof B?{mainAxis:B,altAxis:B}:Object.assign({mainAxis:0,altAxis:0},B),R=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,D={x:0,y:0};if(P){if(v){var F,Y="y"===I?r.top:r.left,K="y"===I?r.bottom:r.right,U="y"===I?"height":"width",z=P[I],H=z+O[Y],G=z-O[K],W=C?-V[U]/2:0,$=k===r.start?L[U]:V[U],q=k===r.start?-V[U]:-L[U],X=t.elements.arrow,Z=C&&X?(0,u["default"])(X):{width:0,height:0},Q=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:(0,d["default"])(),J=Q[Y],ee=Q[K],te=(0,c.within)(0,L[U],Z[U]),ne=T?L[U]/2-W-te-J-j.mainAxis:$-te-J-j.mainAxis,re=T?-L[U]/2+W+te+ee+j.mainAxis:q+te+ee+j.mainAxis,oe=t.elements.arrow&&(0,s["default"])(t.elements.arrow),ie=oe?"y"===I?oe.clientTop||0:oe.clientLeft||0:0,ae=null!=(F=null==R?void 0:R[I])?F:0,ce=z+ne-ae-ie,ue=z+re-ae,se=(0,c.within)(C?(0,p.min)(H,ce):H,z,C?(0,p.max)(G,ue):G);P[I]=se,D[I]=se-z}if(y){var le,fe="x"===I?r.top:r.left,de="x"===I?r.bottom:r.right,pe=P[A],he="y"===A?"height":"width",ge=pe+O[fe],ve=pe-O[de],me=-1!==[r.top,r.left].indexOf(M),ye=null!=(le=null==R?void 0:R[A])?le:0,be=me?ge:pe-L[he]-V[he]-ye+j.altAxis,_e=me?pe+L[he]+V[he]-ye-j.altAxis:ve,we=C&&me?(0,c.withinMaxClamp)(be,pe,_e):(0,c.within)(C?be:ge,pe,C?_e:ve);P[A]=we,D[A]=we-pe}t.modifiersData[h]=D}},requiresIfExists:["offset"]}},88037:function(e,t,n){"use strict";t.__esModule=!0,t.defaultModifiers=t.createPopper=void 0;var r=n(50252);t.popperGenerator=r.popperGenerator,t.detectOverflow=r.detectOverflow;var o=u(n(59953)),i=u(n(23786)),a=u(n(15224)),c=u(n(38621));function u(e){return e&&e.__esModule?e:{"default":e}}var s=t.defaultModifiers=[o["default"],i["default"],a["default"],c["default"]];t.createPopper=(0,r.popperGenerator)({defaultModifiers:s})},1728:function(e,t,n){"use strict";t.__esModule=!0;var r={createPopper:!0,createPopperLite:!0,defaultModifiers:!0,popperGenerator:!0,detectOverflow:!0};t.defaultModifiers=t.createPopperLite=t.createPopper=void 0;var o=n(50252);t.popperGenerator=o.popperGenerator,t.detectOverflow=o.detectOverflow;var i=v(n(59953)),a=v(n(23786)),c=v(n(15224)),u=v(n(38621)),s=v(n(90642)),l=v(n(21128)),f=v(n(78230)),d=v(n(90860)),p=v(n(17945)),h=n(88037);t.createPopperLite=h.createPopper;var g=n(97934);function v(e){return e&&e.__esModule?e:{"default":e}}Object.keys(g).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(r,e)||e in t&&t[e]===g[e]||(t[e]=g[e]))}));var m=t.defaultModifiers=[i["default"],a["default"],c["default"],u["default"],s["default"],l["default"],f["default"],d["default"],p["default"]];t.createPopperLite=t.createPopper=(0,o.popperGenerator)({defaultModifiers:m})},67450:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t){void 0===t&&(t={});var n=t,c=n.placement,u=n.boundary,s=n.rootBoundary,l=n.padding,f=n.flipVariations,d=n.allowedAutoPlacements,p=void 0===d?o.placements:d,h=(0,r["default"])(c),g=h?f?o.variationPlacements:o.variationPlacements.filter((function(e){return(0,r["default"])(e)===h})):o.basePlacements,v=g.filter((function(e){return p.indexOf(e)>=0}));0===v.length&&(v=g);var m=v.reduce((function(t,n){return t[n]=(0,i["default"])(e,{placement:n,boundary:u,rootBoundary:s,padding:l})[(0,a["default"])(n)],t}),{});return Object.keys(m).sort((function(e,t){return m[e]-m[t]}))};var r=c(n(48218)),o=n(83996),i=c(n(49883)),a=c(n(85312));function c(e){return e&&e.__esModule?e:{"default":e}}},85694:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t,n=e.reference,c=e.element,u=e.placement,s=u?(0,r["default"])(u):null,l=u?(0,o["default"])(u):null,f=n.x+n.width/2-c.width/2,d=n.y+n.height/2-c.height/2;switch(s){case a.top:t={x:f,y:n.y-c.height};break;case a.bottom:t={x:f,y:n.y+n.height};break;case a.right:t={x:n.x+n.width,y:d};break;case a.left:t={x:n.x-c.width,y:d};break;default:t={x:n.x,y:n.y}}var p=s?(0,i["default"])(s):null;if(null!=p){var h="y"===p?"height":"width";switch(l){case a.start:t[p]=t[p]-(n[h]/2-c[h]/2);break;case a.end:t[p]=t[p]+(n[h]/2-c[h]/2)}}return t};var r=c(n(85312)),o=c(n(48218)),i=c(n(86274)),a=n(83996);function c(e){return e&&e.__esModule?e:{"default":e}}},63889:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){var t;return function(){return t||(t=new Promise((function(n){Promise.resolve().then((function(){t=undefined,n(e())}))}))),t}}},49883:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t){void 0===t&&(t={});var n=t,d=n.placement,p=void 0===d?e.placement:d,h=n.strategy,g=void 0===h?e.strategy:h,v=n.boundary,m=void 0===v?u.clippingParents:v,y=n.rootBoundary,b=void 0===y?u.viewport:y,_=n.elementContext,w=void 0===_?u.popper:_,x=n.altBoundary,S=void 0!==x&&x,C=n.padding,E=void 0===C?0:C,N=(0,l["default"])("number"!=typeof E?E:(0,f["default"])(E,u.basePlacements)),O=w===u.popper?u.reference:u.popper,M=e.rects.popper,k=e.elements[S?O:w],T=(0,r["default"])((0,s.isElement)(k)?k:k.contextElement||(0,o["default"])(e.elements.popper),m,b,g),I=(0,i["default"])(e.elements.reference),A=(0,a["default"])({reference:I,element:M,strategy:"absolute",placement:p}),P=(0,c["default"])(Object.assign({},M,A)),L=w===u.popper?P:I,V={top:T.top-L.top+N.top,bottom:L.bottom-T.bottom+N.bottom,left:T.left-L.left+N.left,right:L.right-T.right+N.right},B=e.modifiersData.offset;if(w===u.popper&&B){var j=B[p];Object.keys(V).forEach((function(e){var t=[u.right,u.bottom].indexOf(e)>=0?1:-1,n=[u.top,u.bottom].indexOf(e)>=0?"y":"x";V[e]+=j[n]*t}))}return V};var r=d(n(35823)),o=d(n(36748)),i=d(n(97617)),a=d(n(85694)),c=d(n(14834)),u=n(83996),s=n(75011),l=d(n(10632)),f=d(n(59597));function d(e){return e&&e.__esModule?e:{"default":e}}},59597:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}},4320:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return"x"===e?"y":"x"}},85312:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return e.split("-")[0]};n(83996)},23941:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(){return{top:0,right:0,bottom:0,left:0}}},86274:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}},72310:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e.replace(/left|right|bottom|top/g,(function(e){return n[e]}))};var n={left:"right",right:"left",bottom:"top",top:"bottom"}},53379:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e.replace(/start|end/g,(function(e){return n[e]}))};var n={start:"end",end:"start"}},48218:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e.split("-")[1]}},14194:function(e,t){"use strict";t.__esModule=!0,t.round=t.min=t.max=void 0;t.max=Math.max,t.min=Math.min,t.round=Math.round},27343:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){var t=e.reduce((function(e,t){var n=e[t.name];return e[t.name]=n?Object.assign({},n,t,{options:Object.assign({},n.options,t.options),data:Object.assign({},n.data,t.data)}):t,e}),{});return Object.keys(t).map((function(e){return t[e]}))}},10632:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return Object.assign({},(0,o["default"])(),e)};var r,o=(r=n(23941))&&r.__esModule?r:{"default":r}},47307:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=function(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}(e);return r.modifierPhases.reduce((function(e,n){return e.concat(t.filter((function(e){return e.phase===n})))}),[])};var r=n(83996)},14834:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}},36110:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(){var e=navigator.userAgentData;if(null!=e&&e.brands&&Array.isArray(e.brands))return e.brands.map((function(e){return e.brand+"/"+e.version})).join(" ");return navigator.userAgent}},52855:function(e,t,n){"use strict";t.__esModule=!0,t.within=o,t.withinMaxClamp=function(e,t,n){var r=o(e,t,n);return r>n?n:r};var r=n(14194);function o(e,t,n){return(0,r.max)(e,(0,r.min)(t,n))}},85964:function(e){"use strict";e.exports=function(){function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,n){return t=Object.setPrototypeOf||function(){function e(e,t){return e.__proto__=t,e}return e}(),t(e,n)}function n(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function r(e,o,i){return r=n()?Reflect.construct:function(){function e(e,n,r){var o=[null];o.push.apply(o,n);var i=new(Function.bind.apply(e,o));return r&&t(i,r.prototype),i}return e}(),r.apply(null,arguments)}function o(e){return i(e)||a(e)||c(e)||s()}function i(e){if(Array.isArray(e))return u(e)}function a(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function c(e,t){if(e){if("string"==typeof e)return u(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(e,t):void 0}}function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1?n-1:0),o=1;o/gm),X=v(/\${[\w\W]*}/gm),Z=v(/^data-[\-\w.\u00B7-\uFFFF]/),Q=v(/^aria-[\-\w]+$/),J=v(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),ee=v(/^(?:\w+script|data):/i),te=v(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),ne=v(/^html$/i),re=function(){function e(){return"undefined"==typeof window?null:window}return e}(),oe=function(){function t(t,n){if("object"!==e(t)||"function"!=typeof t.createPolicy)return null;var r=null,o="data-tt-policy-suffix";n.currentScript&&n.currentScript.hasAttribute(o)&&(r=n.currentScript.getAttribute(o));var i="dompurify"+(r?"#"+r:"");try{return t.createPolicy(i,{createHTML:function(){function e(e){return e}return e}(),createScriptURL:function(){function e(e){return e}return e}()})}catch(a){return null}}return t}();function ie(){var t=arguments.length>0&&arguments[0]!==undefined?arguments[0]:re(),n=function(){function e(e){return ie(e)}return e}();if(n.version="2.4.7",n.removed=[],!t||!t.document||9!==t.document.nodeType)return n.isSupported=!1,n;var r=t.document,i=t.document,a=t.DocumentFragment,c=t.HTMLTemplateElement,u=t.Node,s=t.Element,l=t.NodeFilter,f=t.NamedNodeMap,d=void 0===f?t.NamedNodeMap||t.MozNamedAttrMap:f,p=t.HTMLFormElement,h=t.DOMParser,v=t.trustedTypes,m=s.prototype,y=B(m,"cloneNode"),b=B(m,"nextSibling"),_=B(m,"childNodes"),A=B(m,"parentNode");if("function"==typeof c){var P=i.createElement("template");P.content&&P.content.ownerDocument&&(i=P.content.ownerDocument)}var ae=oe(v,r),ce=ae?ae.createHTML(""):"",ue=i,se=ue.implementation,le=ue.createNodeIterator,fe=ue.createDocumentFragment,de=ue.getElementsByTagName,pe=r.importNode,he={};try{he=V(i).documentMode?i.documentMode:{}}catch(Pt){}var ge={};n.isSupported="function"==typeof A&&se&&se.createHTMLDocument!==undefined&&9!==he;var ve,me,ye=$,be=q,_e=X,we=Z,xe=Q,Se=ee,Ce=te,Ee=J,Ne=null,Oe=L({},[].concat(o(j),o(R),o(D),o(Y),o(U))),Me=null,ke=L({},[].concat(o(z),o(H),o(G),o(W))),Te=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ie=null,Ae=null,Pe=!0,Le=!0,Ve=!1,Be=!0,je=!1,Re=!1,De=!1,Fe=!1,Ye=!1,Ke=!1,Ue=!1,ze=!0,He=!1,Ge="user-content-",We=!0,$e=!1,qe={},Xe=null,Ze=L({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),Qe=null,Je=L({},["audio","video","img","source","image","track"]),et=null,tt=L({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),nt="http://www.w3.org/1998/Math/MathML",rt="http://www.w3.org/2000/svg",ot="http://www.w3.org/1999/xhtml",it=ot,at=!1,ct=null,ut=L({},[nt,rt,ot],E),st=["application/xhtml+xml","text/html"],lt="text/html",ft=null,dt=i.createElement("form"),pt=function(){function e(e){return e instanceof RegExp||e instanceof Function}return e}(),ht=function(){function t(t){ft&&ft===t||(t&&"object"===e(t)||(t={}),t=V(t),ve=ve=-1===st.indexOf(t.PARSER_MEDIA_TYPE)?lt:t.PARSER_MEDIA_TYPE,me="application/xhtml+xml"===ve?E:C,Ne="ALLOWED_TAGS"in t?L({},t.ALLOWED_TAGS,me):Oe,Me="ALLOWED_ATTR"in t?L({},t.ALLOWED_ATTR,me):ke,ct="ALLOWED_NAMESPACES"in t?L({},t.ALLOWED_NAMESPACES,E):ut,et="ADD_URI_SAFE_ATTR"in t?L(V(tt),t.ADD_URI_SAFE_ATTR,me):tt,Qe="ADD_DATA_URI_TAGS"in t?L(V(Je),t.ADD_DATA_URI_TAGS,me):Je,Xe="FORBID_CONTENTS"in t?L({},t.FORBID_CONTENTS,me):Ze,Ie="FORBID_TAGS"in t?L({},t.FORBID_TAGS,me):{},Ae="FORBID_ATTR"in t?L({},t.FORBID_ATTR,me):{},qe="USE_PROFILES"in t&&t.USE_PROFILES,Pe=!1!==t.ALLOW_ARIA_ATTR,Le=!1!==t.ALLOW_DATA_ATTR,Ve=t.ALLOW_UNKNOWN_PROTOCOLS||!1,Be=!1!==t.ALLOW_SELF_CLOSE_IN_ATTR,je=t.SAFE_FOR_TEMPLATES||!1,Re=t.WHOLE_DOCUMENT||!1,Ye=t.RETURN_DOM||!1,Ke=t.RETURN_DOM_FRAGMENT||!1,Ue=t.RETURN_TRUSTED_TYPE||!1,Fe=t.FORCE_BODY||!1,ze=!1!==t.SANITIZE_DOM,He=t.SANITIZE_NAMED_PROPS||!1,We=!1!==t.KEEP_CONTENT,$e=t.IN_PLACE||!1,Ee=t.ALLOWED_URI_REGEXP||Ee,it=t.NAMESPACE||ot,Te=t.CUSTOM_ELEMENT_HANDLING||{},t.CUSTOM_ELEMENT_HANDLING&&pt(t.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Te.tagNameCheck=t.CUSTOM_ELEMENT_HANDLING.tagNameCheck),t.CUSTOM_ELEMENT_HANDLING&&pt(t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Te.attributeNameCheck=t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),t.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Te.allowCustomizedBuiltInElements=t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),je&&(Le=!1),Ke&&(Ye=!0),qe&&(Ne=L({},o(U)),Me=[],!0===qe.html&&(L(Ne,j),L(Me,z)),!0===qe.svg&&(L(Ne,R),L(Me,H),L(Me,W)),!0===qe.svgFilters&&(L(Ne,D),L(Me,H),L(Me,W)),!0===qe.mathMl&&(L(Ne,Y),L(Me,G),L(Me,W))),t.ADD_TAGS&&(Ne===Oe&&(Ne=V(Ne)),L(Ne,t.ADD_TAGS,me)),t.ADD_ATTR&&(Me===ke&&(Me=V(Me)),L(Me,t.ADD_ATTR,me)),t.ADD_URI_SAFE_ATTR&&L(et,t.ADD_URI_SAFE_ATTR,me),t.FORBID_CONTENTS&&(Xe===Ze&&(Xe=V(Xe)),L(Xe,t.FORBID_CONTENTS,me)),We&&(Ne["#text"]=!0),Re&&L(Ne,["html","head","body"]),Ne.table&&(L(Ne,["tbody"]),delete Ie.tbody),g&&g(t),ft=t)}return t}(),gt=L({},["mi","mo","mn","ms","mtext"]),vt=L({},["foreignobject","desc","title","annotation-xml"]),mt=L({},["title","style","font","a","script"]),yt=L({},R);L(yt,D),L(yt,F);var bt=L({},Y);L(bt,K);var _t=function(){function e(e){var t=A(e);t&&t.tagName||(t={namespaceURI:it,tagName:"template"});var n=C(e.tagName),r=C(t.tagName);return!!ct[e.namespaceURI]&&(e.namespaceURI===rt?t.namespaceURI===ot?"svg"===n:t.namespaceURI===nt?"svg"===n&&("annotation-xml"===r||gt[r]):Boolean(yt[n]):e.namespaceURI===nt?t.namespaceURI===ot?"math"===n:t.namespaceURI===rt?"math"===n&&vt[r]:Boolean(bt[n]):e.namespaceURI===ot?!(t.namespaceURI===rt&&!vt[r])&&!(t.namespaceURI===nt&&!gt[r])&&!bt[n]&&(mt[n]||!yt[n]):!("application/xhtml+xml"!==ve||!ct[e.namespaceURI]))}return e}(),wt=function(){function e(e){S(n.removed,{element:e});try{e.parentNode.removeChild(e)}catch(Pt){try{e.outerHTML=ce}catch(Pt){e.remove()}}}return e}(),xt=function(){function e(e,t){try{S(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(Pt){S(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Me[e])if(Ye||Ke)try{wt(t)}catch(Pt){}else try{t.setAttribute(e,"")}catch(Pt){}}return e}(),St=function(){function e(e){var t,n;if(Fe)e=""+e;else{var r=N(e,/^[\r\n\t ]+/);n=r&&r[0]}"application/xhtml+xml"===ve&&it===ot&&(e=''+e+"");var o=ae?ae.createHTML(e):e;if(it===ot)try{t=(new h).parseFromString(o,ve)}catch(Pt){}if(!t||!t.documentElement){t=se.createDocument(it,"template",null);try{t.documentElement.innerHTML=at?ce:o}catch(Pt){}}var a=t.body||t.documentElement;return e&&n&&a.insertBefore(i.createTextNode(n),a.childNodes[0]||null),it===ot?de.call(t,Re?"html":"body")[0]:Re?t.documentElement:a}return e}(),Ct=function(){function e(e){return le.call(e.ownerDocument||e,e,l.SHOW_ELEMENT|l.SHOW_COMMENT|l.SHOW_TEXT,null,!1)}return e}(),Et=function(){function e(e){return e instanceof p&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof d)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)}return e}(),Nt=function(){function t(t){return"object"===e(u)?t instanceof u:t&&"object"===e(t)&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName}return t}(),Ot=function(){function e(e,t,r){ge[e]&&w(ge[e],(function(e){e.call(n,t,r,ft)}))}return e}(),Mt=function(){function e(e){var t;if(Ot("beforeSanitizeElements",e,null),Et(e))return wt(e),!0;if(T(/[\u0080-\uFFFF]/,e.nodeName))return wt(e),!0;var r=me(e.nodeName);if(Ot("uponSanitizeElement",e,{tagName:r,allowedTags:Ne}),e.hasChildNodes()&&!Nt(e.firstElementChild)&&(!Nt(e.content)||!Nt(e.content.firstElementChild))&&T(/<[/\w]/g,e.innerHTML)&&T(/<[/\w]/g,e.textContent))return wt(e),!0;if("select"===r&&T(/