diff --git a/code/game/machinery/magnetic_module.dm b/code/game/machinery/magnetic_module.dm
index 963ae462702..88a78dcfeea 100644
--- a/code/game/machinery/magnetic_module.dm
+++ b/code/game/machinery/magnetic_module.dm
@@ -1,3 +1,11 @@
+#define MIN_CONTROLLER_SPEED 1
+#define MAX_CONTROLLER_SPEED 10
+#define MIN_ELECTRICITY_LEVEL 1
+#define MAX_ELECTRICITY_LEVEL 12
+#define MIN_MAGNETIC_FIELD 1
+#define MAX_MAGNETIC_FIELD 4
+#define MAX_PATH_LENGTH 50
+
// Magnetic attractor, creates variable magnetic fields and attraction.
// Can also be used to emit electron/proton beams to create a center of magnetism on another tile
@@ -16,8 +24,8 @@
idle_power_consumption = 50
var/freq = AIRLOCK_FREQ // radio frequency
- var/electricity_level = 1 // intensity of the magnetic pull
- var/magnetic_field = 1 // the range of magnetic attraction
+ var/electricity_level = MIN_ELECTRICITY_LEVEL // intensity of the magnetic pull
+ var/magnetic_field = MIN_MAGNETIC_FIELD // the range of magnetic attraction
var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something
var/turf/center // the center of magnetic attraction
var/on = FALSE
@@ -71,20 +79,20 @@
if("add-elec")
electricity_level++
- if(electricity_level > 12)
- electricity_level = 12
+ if(electricity_level > MAX_ELECTRICITY_LEVEL)
+ electricity_level = MAX_ELECTRICITY_LEVEL
if("sub-elec")
electricity_level--
- if(electricity_level <= 0)
- electricity_level = 1
+ if(electricity_level < MIN_ELECTRICITY_LEVEL)
+ electricity_level = MIN_ELECTRICITY_LEVEL
if("add-mag")
magnetic_field++
- if(magnetic_field > 4)
- magnetic_field = 4
+ if(magnetic_field > MAX_MAGNETIC_FIELD)
+ magnetic_field = MAX_MAGNETIC_FIELD
if("sub-mag")
magnetic_field--
- if(magnetic_field <= 0)
- magnetic_field = 1
+ if(magnetic_field < MIN_MAGNETIC_FIELD)
+ magnetic_field = MIN_MAGNETIC_FIELD
if("set-x")
if(modifier) center_x = modifier
@@ -120,10 +128,10 @@
on = FALSE
// Sanity checks:
- if(electricity_level <= 0)
- electricity_level = 1
- if(magnetic_field <= 0)
- magnetic_field = 1
+ if(electricity_level < MIN_ELECTRICITY_LEVEL)
+ electricity_level = MIN_ELECTRICITY_LEVEL
+ if(magnetic_field < MIN_MAGNETIC_FIELD)
+ magnetic_field = MIN_MAGNETIC_FIELD
// Limitations:
@@ -131,10 +139,10 @@
center_x = max_dist
if(abs(center_y) > max_dist)
center_y = max_dist
- if(magnetic_field > 4)
- magnetic_field = 4
- if(electricity_level > 12)
- electricity_level = 12
+ if(magnetic_field > MAX_MAGNETIC_FIELD)
+ magnetic_field = MAX_MAGNETIC_FIELD
+ if(electricity_level > MAX_ELECTRICITY_LEVEL)
+ electricity_level = MAX_ELECTRICITY_LEVEL
// Update power usage:
if(on)
@@ -179,15 +187,17 @@
var/code = 0
var/list/magnets = list()
var/title = "Magnetic Control Console"
- var/autolink = 0 // if set to 1, can't probe for other magnets!
+ var/autolink = FALSE // if set to TRUE, can't probe for other magnets!
+ var/probing = FALSE
var/pathpos = 1 // position in the path
var/path = "NULL" // text path of the magnet
- var/speed = 1 // lowest = 1, highest = 10
+ var/speed = MIN_CONTROLLER_SPEED
var/list/rpath = list() // real path of the magnet, used in iterator
+ var/static/list/valid_paths = list("n", "s", "e", "w", "c", "r")
- var/moving = 0 // 1 if scheduled to loop
- var/looping = 0 // 1 if looping
+ var/moving = FALSE // TRUE if scheduled to loop
+ var/looping = FALSE // TRUE if looping
/obj/machinery/magnetic_controller/Initialize(mapload)
@@ -217,109 +227,188 @@
magnets -= magnet
/obj/machinery/magnetic_controller/proc/link_magnets()
+ magnets = list()
for(var/obj/machinery/magnetic_module/M in GLOB.machines)
if(M.freq == frequency && M.code == code)
magnets.Add(M)
- RegisterSignal(M, COMSIG_PARENT_QDELETING, PROC_REF(on_magnet_del))
+ RegisterSignal(M, COMSIG_PARENT_QDELETING, PROC_REF(on_magnet_del), TRUE)
/obj/machinery/magnetic_controller/process()
if(magnets.len == 0 && autolink)
link_magnets()
+/obj/machinery/magnetic_controller/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "MagnetController", name, 400, 600)
+ ui.open()
+
/obj/machinery/magnetic_controller/attack_ai(mob/user as mob)
- return src.attack_hand(user)
+ if(..())
+ return TRUE
+ ui_interact(user)
+
+/obj/machinery/magnetic_controller/attack_ghost(mob/user)
+ if(..())
+ return TRUE
+ ui_interact(user)
/obj/machinery/magnetic_controller/attack_hand(mob/user as mob)
- if(stat & (BROKEN|NOPOWER))
+ if(..())
+ return TRUE
+ ui_interact(user)
+
+/obj/machinery/magnetic_controller/proc/find_magnet(uid)
+ var/potential_magnet = locateUID(uid)
+ if(istype(potential_magnet, /obj/machinery/magnetic_module))
+ return potential_magnet
+
+/obj/machinery/magnetic_controller/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ if(..())
return
- user.set_machine(src)
- var/dat = "Magnetic Control Console
"
- if(!autolink)
- dat += {"
- Frequency: [frequency]
- Code: [code]
- Probe Generators
- "}
- if(magnets.len >= 1)
+ add_fingerprint(ui.user)
- dat += "Magnets confirmed:
"
- var/i = 0
- for(var/obj/machinery/magnetic_module/M in magnets)
- i++
- dat += " < \[[i]\] ([M.on ? "On":"Off"]) | Electricity level: - [M.electricity_level] +; Magnetic field: - [M.magnetic_field] +
"
+ if(ui_act_modal(action, params, ui, state))
+ return TRUE
- dat += "
Speed: - [speed] +
"
- dat += "Path: {[path]}
"
- dat += "Moving: [moving ? "Enabled":"Disabled"]"
+ . = TRUE
+ switch(action)
+ if("probe_magnets")
+ if(probing || autolink)
+ return
+ probing = TRUE
+ link_magnets()
+ addtimer(VARSET_CALLBACK(src, probing, FALSE), 5 SECONDS)
+ if("toggle_power")
+ moving = !moving
+ if(moving)
+ INVOKE_ASYNC(src, PROC_REF(MagnetMove))
+ if("set_speed")
+ var/new_speed = text2num(params["speed"])
+ if(isnull(new_speed))
+ return
+ speed = clamp(new_speed, MIN_CONTROLLER_SPEED, MAX_CONTROLLER_SPEED)
- user << browse(dat, "window=magnet;size=400x500")
- onclose(user, "magnet")
+ if("path_add")
+ if(length(rpath) >= MAX_PATH_LENGTH / 2)
+ return
+ var/code = params["code"]
+ if(!(code in valid_paths))
+ return
+ moving = FALSE
+ pathpos = 1
+ rpath += code
+ path = rpath.Join(";")
+ if("path_remove")
+ var/index = text2num(params["index"])
+ if(isnull(index) || index < 0 || index > length(rpath))
+ return
+ var/code = params["code"]
+ if(!(code in valid_paths))
+ return
+ moving = FALSE
+ pathpos = 1
+ if(rpath[index] == code)
+ rpath.Cut(index, index + 1)
+ path = rpath.Join(";")
+ if("path_clear")
+ moving = FALSE
+ pathpos = 1
+ rpath = list()
+ path = ""
-/obj/machinery/magnetic_controller/Topic(href, href_list)
- if(stat & (BROKEN|NOPOWER))
- return
- usr.set_machine(src)
- src.add_fingerprint(usr)
+ if("toggle_magnet_power")
+ var/obj/machinery/magnetic_module/magnet = find_magnet(params["id"])
+ if(!magnet)
+ return
+ magnet.Cmd("toggle-power")
+ if("set_electricity_level")
+ var/obj/machinery/magnetic_module/magnet = find_magnet(params["id"])
+ if(!magnet)
+ return
+ var/new_electricity_level = text2num(params["electricityLevel"])
+ if(isnull(new_electricity_level))
+ return
+ magnet.Cmd("set-electriclevel", clamp(new_electricity_level, MIN_ELECTRICITY_LEVEL, MAX_ELECTRICITY_LEVEL))
+ if("set_magnetic_field")
+ var/obj/machinery/magnetic_module/magnet = find_magnet(params["id"])
+ if(!magnet)
+ return
+ var/new_magnetic_field = text2num(params["magneticField"])
+ if(isnull(new_magnetic_field))
+ return
+ magnet.Cmd("set-magneticfield", clamp(new_magnetic_field, MIN_MAGNETIC_FIELD, MAX_MAGNETIC_FIELD))
- if(href_list["radio-op"])
+/obj/machinery/magnetic_controller/ui_data(mob/user)
+ var/data = list()
- // Prepare signal beforehand, because this is a radio operation
- var/datum/signal/signal = new
- signal.transmission_method = 1 // radio transmission
- signal.source = src
- signal.frequency = frequency
- signal.data["code"] = code
+ data["autolink"] = autolink
+ data["code"] = code
+ data["frequency"] = frequency
- // Apply any necessary commands
- switch(href_list["radio-op"])
- if("togglepower")
- signal.data["command"] = "toggle-power"
+ var/list/linked_magnets = list()
+ for(var/obj/machinery/magnetic_module/M in magnets)
+ linked_magnets += list(list(
+ "uid" = M.UID(),
+ "powerState" = M.on,
+ "electricityLevel" = M.electricity_level,
+ "magneticField" = M.magnetic_field,
+ ))
+ data["linkedMagnets"] = linked_magnets
- if("minuselec")
- signal.data["command"] = "sub-elec"
- if("pluselec")
- signal.data["command"] = "add-elec"
+ data["magnetConfiguration"] = list(
+ "electricityLevel" = list(
+ "min" = MIN_ELECTRICITY_LEVEL,
+ "max" = MAX_ELECTRICITY_LEVEL,
+ ),
+ "magneticField" = list(
+ "min" = MIN_MAGNETIC_FIELD,
+ "max" = MAX_MAGNETIC_FIELD,
+ ),
+ )
- if("minusmag")
- signal.data["command"] = "sub-mag"
- if("plusmag")
- signal.data["command"] = "add-mag"
+ data["path"] = rpath
+ data["pathPosition"] = pathpos
+ data["probing"] = probing
+ data["powerState"] = moving
+ data["speed"] = list(
+ "value" = speed,
+ "min" = MIN_CONTROLLER_SPEED,
+ "max" = MAX_CONTROLLER_SPEED,
+ )
+ data["modal"] = ui_modal_data(src)
- // Broadcast the signal
+ return data
- radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
-
- spawn(1)
- updateUsrDialog() // pretty sure this increases responsiveness
-
- if(href_list["operation"])
- switch(href_list["operation"])
- if("plusspeed")
- speed++
- if(speed > 10)
- speed = 10
- if("minusspeed")
- speed --
- if(speed <= 0)
- speed = 1
- if("setpath")
- var/newpath = sanitize(copytext(input(usr, "Please define a new path!",,path) as text|null,1,MAX_MESSAGE_LEN))
- if(newpath && newpath != "")
- moving = 0 // stop moving
- path = newpath
- pathpos = 1 // reset position
- filter_path() // renders rpath
-
- if("togglemoving")
- moving = !moving
- if(moving)
- spawn() MagnetMove()
-
-
- updateUsrDialog()
+/obj/machinery/magnetic_controller/proc/ui_act_modal(action, params, datum/tgui/ui, datum/ui_state/state)
+ . = TRUE
+ var/id = params["id"] // The modal's ID
+ var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
+ switch(ui_modal_act(src, action, params))
+ if(UI_MODAL_OPEN)
+ switch(id)
+ if("path_custom_input")
+ ui_modal_input(src, id, "Please enter the new path:", null, arguments, rpath.Join(";"), MAX_PATH_LENGTH)
+ else
+ return FALSE
+ if(UI_MODAL_ANSWER)
+ var/answer = params["answer"]
+ switch(id)
+ if("path_custom_input")
+ var/new_path = answer
+ if(!new_path || length(new_path) > MAX_PATH_LENGTH)
+ return
+ moving = FALSE
+ pathpos = 1
+ path = new_path
+ filter_path()
+ else
+ return FALSE
+ else
+ return FALSE
/obj/machinery/magnetic_controller/proc/MagnetMove()
if(looping) return
@@ -329,11 +418,11 @@
if(stat & (BROKEN|NOPOWER))
break
- looping = 1
+ looping = TRUE
// Prepare the radio signal
var/datum/signal/signal = new
- signal.transmission_method = 1 // radio transmission
+ signal.transmission_method = TRANSMISSION_RADIO // radio transmission
signal.source = src
signal.frequency = frequency
signal.data["code"] = code
@@ -359,19 +448,19 @@
spawn()
radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
- if(speed == 10)
+ if(speed >= MAX_CONTROLLER_SPEED)
sleep(1)
else
- sleep(12-speed)
+ sleep(MAX_ELECTRICITY_LEVEL - speed)
- looping = 0
+ looping = FALSE
/obj/machinery/magnetic_controller/proc/filter_path()
// Generates the rpath variable using the path string, think of this as "string2list"
// Doesn't use params2list() because of the akward way it stacks entities
rpath = list() // clear rpath
- var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length
+ var/maximum_character = min( MAX_PATH_LENGTH, length(path) ) // chooses the maximum length of the iterator. 50 max length
for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path
@@ -381,3 +470,13 @@
rpath += copytext(path, i, i+1) // else, add to list
// there doesn't HAVE to be separators but it makes paths syntatically visible
+
+
+
+#undef MIN_CONTROLLER_SPEED
+#undef MAX_CONTROLLER_SPEED
+#undef MIN_ELECTRICITY_LEVEL
+#undef MAX_ELECTRICITY_LEVEL
+#undef MIN_MAGNETIC_FIELD
+#undef MAX_MAGNETIC_FIELD
+#undef MAX_PATH_LENGTH
diff --git a/tgui/packages/tgui/interfaces/MagnetController.js b/tgui/packages/tgui/interfaces/MagnetController.js
new file mode 100644
index 00000000000..7a9aeee2d25
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/MagnetController.js
@@ -0,0 +1,230 @@
+import { toFixed } from 'common/math';
+import { useBackend } from '../backend';
+import {
+ BlockQuote,
+ Button,
+ LabeledList,
+ Section,
+ Slider,
+} from '../components';
+import { Window } from '../layouts';
+import { ComplexModal, modalOpen } from './common/ComplexModal';
+
+const pathCodeMap = new Map([
+ [
+ 'n',
+ {
+ icon: 'arrow-up',
+ tooltip: 'Move North',
+ },
+ ],
+ [
+ 'e',
+ {
+ icon: 'arrow-right',
+ tooltip: 'Move East',
+ },
+ ],
+ [
+ 's',
+ {
+ icon: 'arrow-down',
+ tooltip: 'Move South',
+ },
+ ],
+ [
+ 'w',
+ {
+ icon: 'arrow-left',
+ tooltip: 'Move West',
+ },
+ ],
+ [
+ 'c',
+ {
+ icon: 'crosshairs',
+ tooltip: 'Move to Magnet',
+ },
+ ],
+ [
+ 'r',
+ {
+ icon: 'dice',
+ tooltip: 'Move Randomly',
+ },
+ ],
+]);
+
+export const MagnetController = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ autolink,
+ code,
+ frequency,
+ linkedMagnets,
+ magnetConfiguration,
+ path,
+ pathPosition,
+ probing,
+ powerState,
+ speed,
+ } = data;
+
+ return (
+
+
+
+ {!autolink && (
+ act('probe_magnets')}
+ />
+ }
+ title="Magnet Linking"
+ >
+
+
+ {toFixed(frequency / 10, 1)}
+
+ {code}
+
+
+ )}
+ act('toggle_power')}
+ />
+ }
+ title="Controller Configuration"
+ >
+
+
+
+ act('set_speed', {
+ speed: value,
+ })
+ }
+ />
+
+
+ {Array.from(pathCodeMap.entries()).map(
+ ([code, { icon, tooltip }]) => (
+
+
+
+ {linkedMagnets.map(
+ ({ uid, powerState, electricityLevel, magneticField }, i) => {
+ return (
+
+ act('toggle_magnet_power', {
+ id: uid,
+ })
+ }
+ />
+ }
+ >
+
+
+
+ act('set_electricity_level', {
+ id: uid,
+ electricityLevel: value,
+ })
+ }
+ />
+
+
+
+ act('set_magnetic_field', {
+ id: uid,
+ magneticField: value,
+ })
+ }
+ />
+
+
+
+ );
+ }
+ )}
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/pai/pai_main_menu.js b/tgui/packages/tgui/interfaces/pai/pai_main_menu.js
index 175fd019cb0..575de068254 100644
--- a/tgui/packages/tgui/interfaces/pai/pai_main_menu.js
+++ b/tgui/packages/tgui/interfaces/pai/pai_main_menu.js
@@ -85,8 +85,8 @@ export const pai_main_menu = (props, context) => {
onClick={() => act('setSpeechStyle', { speech_state: s.name })}
/>
))}
-
-
+
+
{available_chassises.map((c) => (
1?n-1:0),r=1;rn?n:e};t.clamp01=function(e){return e<0?0:e>1?1:e};t.scale=function(e,t,n){return(e-t)/(n-t)};t.round=function(e,t){return!e||isNaN(e)?e:(t|=0,a=(e*=n=Math.pow(10,t))>0|-(e<0),r=Math.abs(e%1)>=.4999999999854481,o=Math.floor(e),r&&(e=o+(a>0)),(r?e:Math.round(e))/n);var n,o,r,a};t.toFixed=function(e,t){return void 0===t&&(t=0),Number(e).toFixed(Math.max(t,0))};var o=function(e,t){return t&&e>=t[0]&&e<=t[1]};t.inRange=o;t.keyOfMatchingRange=function(e,t){for(var n=0,r=Object.keys(t);n0&&(t.style=l),t};t.computeBoxProps=N;var b=function(e){var t=e.textColor||e.color,n=e.backgroundColor;return(0,o.classes)([u(t)&&"color-"+t,u(n)&&"color-bg-"+n])};t.computeBoxClassName=b;var V=function(e){var t=e.as,n=void 0===t?"div":t,o=e.className,c=e.children,l=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,i);if("function"==typeof c)return c(N(e));var d="string"==typeof o?o+" "+b(l):b(l),u=N(l);return(0,r.createVNode)(a.VNodeFlags.HtmlElement,n,d,c,a.ChildFlags.UnknownChildren,u)};t.Box=V,V.defaultHooks=o.pureComponentHooks},function(e,t,n){"use strict";function o(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,o=new Array(t);n",apos:"'"};return e.replace(/
/gi,"\n").replace(/<\/?[a-z0-9-_]+[^>]*>/gi,"").replace(/&(nbsp|amp|quot|lt|gt|apos);/g,(function(e,n){return t[n]})).replace(/?([0-9]+);/gi,(function(e,t){var n=parseInt(t,10);return String.fromCharCode(n)})).replace(/?([0-9a-f]+);/gi,(function(e,t){var n=parseInt(t,16);return String.fromCharCode(n)}))};t.buildQueryString=function(e){return Object.keys(e).map((function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])})).join("&")}},function(e,t,n){"use strict";var o=n(41);e.exports=function(e){return o(e.length)}},function(e,t,n){"use strict";var o=n(5),r=n(12),a=n(49),c=n(132),i=n(130);e.exports=function(e,t,n,l){var d=!!l&&!!l.unsafe,u=!!l&&!!l.enumerable,s=!!l&&!!l.noTargetGet,m=l&&l.name!==undefined?l.name:t;return r(n)&&c(n,m,l),e===o?(u?e[t]=n:i(t,n),e):(d?!s&&e[t]&&(u=!0):delete e[t],u?e[t]=n:a(e,t,n),e)}},function(e,t,n){"use strict";var o=n(60),r=n(7),a=n(85),c=n(19),i=n(23),l=n(91),d=r([].push),u=function(e){var t=1==e,n=2==e,r=3==e,u=4==e,s=6==e,m=7==e,p=5==e||s;return function(h,f,C,N){for(var b,V,g=c(h),v=a(g),y=o(f,C),_=i(v),x=0,k=N||l,L=t?k(h,_):n||m?k(h,0):undefined;_>x;x++)if((p||x in v)&&(V=y(b=v[x],x,g),e))if(t)L[x]=V;else if(V)switch(e){case 3:return!0;case 5:return b;case 6:return x;case 2:d(L,b)}else switch(e){case 4:return!1;case 7:d(L,b)}return s?-1:r||u?u:L}};e.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6),filterReject:u(7)}},function(e,t,n){"use strict";var o=n(8),r=n(14),a=n(101),c=n(64),i=n(30),l=n(56),d=n(18),u=n(174),s=Object.getOwnPropertyDescriptor;t.f=o?s:function(e,t){if(e=i(e),t=l(t),u)try{return s(e,t)}catch(n){}if(d(e,t))return c(!r(a.f,e,t),e[t])}},function(e,t,n){"use strict";var o=n(5),r=n(12),a=n(71),c=o.TypeError;e.exports=function(e){if(r(e))return e;throw c(a(e)+" is not a function")}},function(e,t,n){"use strict";var o=n(5),r=n(12),a=function(e){return r(e)?e:undefined};e.exports=function(e,t){return arguments.length<2?a(o[e]):o[e]&&o[e][t]}},function(e,t,n){"use strict";t.__esModule=!0,t.modalRegisterBodyOverride=t.modalOpen=t.modalClose=t.modalAnswer=t.ComplexModal=void 0;var o=n(0),r=n(1),a=n(2),c={};t.modalOpen=function(e,t,n){var o=(0,r.useBackend)(e),a=o.act,c=o.data,i=Object.assign(c.modal?c.modal.args:{},n||{});a("modal_open",{id:t,arguments:JSON.stringify(i)})};t.modalRegisterBodyOverride=function(e,t){c[e]=t};var i=function(e,t,n,o){var a=(0,r.useBackend)(e),c=a.act,i=a.data;if(i.modal){var l=Object.assign(i.modal.args||{},o||{});c("modal_answer",{id:t,answer:n,arguments:JSON.stringify(l)})}};t.modalAnswer=i;var l=function(e,t){(0,(0,r.useBackend)(e).act)("modal_close",{id:t})};t.modalClose=l;t.ComplexModal=function(e,t){var n=(0,r.useBackend)(t).data;if(n.modal){var d,u,s=n.modal,m=s.id,p=s.text,h=s.type,f=(0,o.createComponentVNode)(2,a.Button,{icon:"arrow-left",content:"Cancel",color:"grey",onClick:function(){return l(t)}}),C="auto";if(c[m])u=c[m](n.modal,t);else if("input"===h){var N=n.modal.value;d=function(e){return i(t,m,N)},u=(0,o.createComponentVNode)(2,a.Input,{value:n.modal.value,placeholder:"ENTER to submit",width:"100%",my:"0.5rem",autofocus:!0,onChange:function(e,t){N=t}}),f=(0,o.createComponentVNode)(2,a.Box,{mt:"0.5rem",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"arrow-left",content:"Cancel",color:"grey",onClick:function(){return l(t)}}),(0,o.createComponentVNode)(2,a.Button,{icon:"check",content:"Confirm",color:"good",float:"right",m:"0",onClick:function(){return i(t,m,N)}}),(0,o.createComponentVNode)(2,a.Box,{clear:"both"})]})}else if("choice"===h){var b="object"==typeof n.modal.choices?Object.values(n.modal.choices):n.modal.choices;u=(0,o.createComponentVNode)(2,a.Dropdown,{options:b,selected:n.modal.value,width:"100%",my:"0.5rem",onSelected:function(e){return i(t,m,e)}}),C="initial"}else"bento"===h?u=(0,o.createComponentVNode)(2,a.Flex,{spacingPrecise:"1",wrap:"wrap",my:"0.5rem",maxHeight:"1%",children:n.modal.choices.map((function(e,r){return(0,o.createComponentVNode)(2,a.Flex.Item,{flex:"1 1 auto",children:(0,o.createComponentVNode)(2,a.Button,{selected:r+1===parseInt(n.modal.value,10),onClick:function(){return i(t,m,r+1)},children:(0,o.createVNode)(1,"img",null,null,1,{src:e})})},r)}))}):"boolean"===h&&(f=(0,o.createComponentVNode)(2,a.Box,{mt:"0.5rem",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"times",content:n.modal.no_text,color:"bad",float:"left",mb:"0",onClick:function(){return i(t,m,0)}}),(0,o.createComponentVNode)(2,a.Button,{icon:"check",content:n.modal.yes_text,color:"good",float:"right",m:"0",onClick:function(){return i(t,m,1)}}),(0,o.createComponentVNode)(2,a.Box,{clear:"both"})]}));return(0,o.createComponentVNode)(2,a.Modal,{maxWidth:e.maxWidth||window.innerWidth/2+"px",maxHeight:e.maxHeight||window.innerHeight/2+"px",onEnter:d,mx:"auto",overflowY:C,children:[(0,o.createComponentVNode)(2,a.Box,{display:"inline",children:p}),u,f]})}}},function(e,t,n){"use strict";var o=n(85),r=n(31);e.exports=function(e){return o(r(e))}},function(e,t,n){"use strict";var o=n(5).TypeError;e.exports=function(e){if(e==undefined)throw o("Can't call method on "+e);return e}},function(e,t,n){"use strict";function o(e,t,n,o,r,a,c){try{var i=e[a](c),l=i.value}catch(d){return void n(d)}i.done?t(l):Promise.resolve(l).then(o,r)}t.__esModule=!0,t.winset=t.winget=t.runCommand=t.callByondAsync=t.callByond=t.IS_IE8=void 0;var r=window.Byond,a=function(){var e=navigator.userAgent.match(/Trident\/(\d+).+?;/i);if(!e)return null;var t=e[1];return t?parseInt(t,10):null}(),c=null!==a&&a<=6;t.IS_IE8=c;var i=function(e,t){void 0===t&&(t={}),r.call(e,t)};t.callByond=i;var l=function(e,t){void 0===t&&(t={}),window.__callbacks__=window.__callbacks__||[];var n=window.__callbacks__.length,o=new Promise((function(e){window.__callbacks__.push(e)}));return r.call(e,Object.assign({},t,{callback:"__callbacks__["+n+"]"})),o};t.callByondAsync=l;t.runCommand=function(e){return i("winset",{command:e})};var d=function(){var e,t=(e=regeneratorRuntime.mark((function n(e,t){var o;return regeneratorRuntime.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,l("winget",{id:e,property:t});case 2:return o=n.sent,n.abrupt("return",o[t]);case 4:case"end":return n.stop()}}),n)})),function(){var t=this,n=arguments;return new Promise((function(r,a){var c=e.apply(t,n);function i(e){o(c,r,a,i,l,"next",e)}function l(e){o(c,r,a,i,l,"throw",e)}i(undefined)}))});return function(e,n){return t.apply(this,arguments)}}();t.winget=d;t.winset=function(e,t,n){var o;return i("winset",((o={})[e+"."+t]=n,o))}},function(e,t,n){"use strict";t.__esModule=!0,t.zipWith=t.zip=t.uniqBy=t.toKeyedArray=t.toArray=t.sortBy=t.reduce=t.map=t.filter=void 0;t.toArray=function(e){if(Array.isArray(e))return e;if("object"==typeof e){var t=Object.prototype.hasOwnProperty,n=[];for(var o in e)t.call(e,o)&&n.push(e[o]);return n}return[]};t.toKeyedArray=function(e,t){return void 0===t&&(t="key"),o((function(e,n){var o;return Object.assign(((o={})[t]=n,o),e)}))(e)};t.filter=function(e){return function(t){if(null===t&&t===undefined)return t;if(Array.isArray(t)){for(var n=[],o=0;oi)return 1}return 0};t.sortBy=function(){for(var e=arguments.length,t=new Array(e),n=0;n"+l+""+t+">"}},function(e,t,n){"use strict";var o=n(6);e.exports=function(e){return o((function(){var t=""[e]('"');return t!==t.toLowerCase()||t.split('"').length>3}))}},function(e,t,n){"use strict";t.__esModule=!0,t.computeFlexProps=t.computeFlexItemProps=t.FlexItem=t.Flex=void 0;var o=n(0),r=n(10),a=n(32),c=n(21),i=["className","direction","wrap","align","alignContent","justify","inline","spacing","spacingPrecise"],l=["className","grow","order","shrink","basis","align"];function d(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var u=function(e){var t=e.className,n=e.direction,o=e.wrap,c=e.align,l=e.alignContent,u=e.justify,s=e.inline,m=e.spacing,p=void 0===m?0:m,h=e.spacingPrecise,f=void 0===h?0:h,C=d(e,i);return Object.assign({className:(0,r.classes)(["Flex",a.IS_IE8&&("column"===n?"Flex--ie8--column":"Flex--ie8"),s&&"Flex--inline",p>0&&"Flex--spacing--"+p,f>0&&"Flex--spacingPrecise--"+f,t]),style:Object.assign({},C.style,{"flex-direction":n,"flex-wrap":o,"align-items":c,"align-content":l,"justify-content":u})},C)};t.computeFlexProps=u;var s=function(e){return(0,o.normalizeProps)((0,o.createComponentVNode)(2,c.Box,Object.assign({},u(e))))};t.Flex=s,s.defaultHooks=r.pureComponentHooks;var m=function(e){var t=e.className,n=e.grow,o=e.order,i=e.shrink,u=e.basis,s=void 0===u?e.width:u,m=e.align,p=d(e,l);return Object.assign({className:(0,r.classes)(["Flex__item",a.IS_IE8&&"Flex__item--ie8",t]),style:Object.assign({},p.style,{"flex-grow":n,"flex-shrink":i,"flex-basis":(0,c.unit)(s),order:o,"align-self":m})},p)};t.computeFlexItemProps=m;var p=function(e){return(0,o.normalizeProps)((0,o.createComponentVNode)(2,c.Box,Object.assign({},m(e))))};t.FlexItem=p,p.defaultHooks=r.pureComponentHooks,s.Item=p},function(e,t,n){"use strict";var o,r,a,c=n(176),i=n(5),l=n(7),d=n(11),u=n(49),s=n(18),m=n(129),p=n(103),h=n(87),f=i.TypeError,C=i.WeakMap;if(c||m.state){var N=m.state||(m.state=new C),b=l(N.get),V=l(N.has),g=l(N.set);o=function(e,t){if(V(N,e))throw new f("Object already initialized");return t.facade=e,g(N,e,t),t},r=function(e){return b(N,e)||{}},a=function(e){return V(N,e)}}else{var v=p("state");h[v]=!0,o=function(e,t){if(s(e,v))throw new f("Object already initialized");return t.facade=e,u(e,v,t),t},r=function(e){return s(e,v)?e[v]:{}},a=function(e){return s(e,v)}}e.exports={set:o,get:r,has:a,enforce:function(e){return a(e)?r(e):o(e,{})},getterFor:function(e){return function(t){var n;if(!d(t)||(n=r(t)).type!==e)throw f("Incompatible receiver, "+e+" required");return n}}}},function(e,t,n){"use strict";var o=Math.ceil,r=Math.floor;e.exports=function(e){var t=+e;return t!=t||0===t?0:(t>0?r:o)(t)}},function(e,t,n){"use strict";var o=n(40),r=Math.min;e.exports=function(e){return e>0?r(o(e),9007199254740991):0}},function(e,t,n){"use strict";var o=n(5),r=n(18),a=n(12),c=n(19),i=n(103),l=n(142),d=i("IE_PROTO"),u=o.Object,s=u.prototype;e.exports=l?u.getPrototypeOf:function(e){var t=c(e);if(r(t,d))return t[d];var n=t.constructor;return a(n)&&t instanceof n?n.prototype:t instanceof u?s:null}},function(e,t,n){"use strict";t.__esModule=!0,t.timeAgo=t.getGasLabel=t.getGasColor=t.UI_UPDATE=t.UI_INTERACTIVE=t.UI_DISABLED=t.UI_CLOSE=t.RADIO_CHANNELS=t.CSS_COLORS=t.COLORS=void 0;t.UI_INTERACTIVE=2;t.UI_UPDATE=1;t.UI_DISABLED=0;t.UI_CLOSE=-1;t.COLORS={department:{command:"#526aff",security:"#CF0000",medical:"#009190",science:"#993399",engineering:"#A66300",supply:"#9F8545",service:"#80A000",centcom:"#78789B",other:"#C38312"},damageType:{oxy:"#3498db",toxin:"#2ecc71",burn:"#e67e22",brute:"#e74c3c"}};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:"Syndicate",freq:1213,color:"#a52a2a"},{name:"SyndTeam",freq:1244,color:"#a52a2a"},{name:"Red Team",freq:1215,color:"#ff4444"},{name:"Blue Team",freq:1217,color:"#3434fd"},{name:"Response Team",freq:1345,color:"#2681a5"},{name:"Special Ops",freq:1341,color:"#2681a5"},{name:"Supply",freq:1347,color:"#b88646"},{name:"Service",freq:1349,color:"#6ca729"},{name:"Science",freq:1351,color:"#c68cfa"},{name:"Command",freq:1353,color:"#5177ff"},{name:"Procedure",freq:1339,color:"#F70285"},{name:"Medical",freq:1355,color:"#57b8f0"},{name:"Medical(I)",freq:1485,color:"#57b8f0"},{name:"Engineering",freq:1357,color:"#f37746"},{name:"Security",freq:1359,color:"#dd3535"},{name:"Security(I)",freq:1475,color:"#dd3535"},{name:"AI Private",freq:1343,color:"#d65d95"},{name:"Common",freq:1459,color:"#1ecc43"}];var o=[{id:"o2",name:"Oxygen",label:"O\u2082",color:"blue"},{id:"n2",name:"Nitrogen",label:"N\u2082",color:"red"},{id:"co2",name:"Carbon Dioxide",label:"CO\u2082",color:"grey"},{id:"plasma",name:"Plasma",label:"Plasma",color:"pink"},{id:"water_vapor",name:"Water Vapor",label:"H\u2082O",color:"grey"},{id:"nob",name:"Hyper-noblium",label:"Hyper-nob",color:"teal"},{id:"n2o",name:"Nitrous Oxide",label:"N\u2082O",color:"red"},{id:"no2",name:"Nitryl",label:"NO\u2082",color:"brown"},{id:"tritium",name:"Tritium",label:"Tritium",color:"green"},{id:"bz",name:"BZ",label:"BZ",color:"purple"},{id:"stim",name:"Stimulum",label:"Stimulum",color:"purple"},{id:"pluox",name:"Pluoxium",label:"Pluoxium",color:"blue"},{id:"miasma",name:"Miasma",label:"Miasma",color:"olive"},{id:"hydrogen",name:"Hydrogen",label:"H\u2082",color:"white"},{id:"ab",name:"Agent B",label:"Agent B",color:"purple"}];t.getGasLabel=function(e,t){var n=String(e).toLowerCase(),r=o.find((function(e){return e.id===n||e.name.toLowerCase()===n}));return r&&r.label||t||e};t.getGasColor=function(e){var t=String(e).toLowerCase(),n=o.find((function(e){return e.id===t||e.name.toLowerCase()===t}));return n&&n.color};t.timeAgo=function(e,t){if(e>t)return"in the future";var n=(t/=10)-(e/=10);if(n>3600){var o=Math.round(n/3600);return o+" hour"+(1===o?"":"s")+" ago"}if(n>60){var r=Math.round(n/60);return r+" minute"+(1===r?"":"s")+" ago"}var a=Math.round(n);return a+" second"+(1===a?"":"s")+" ago"}},function(e,t,n){"use strict";t.__esModule=!0,t.LabeledListItem=t.LabeledListDivider=t.LabeledList=void 0;var o=n(0),r=n(10),a=n(21),c=n(222),i=["className","label","labelColor","color","textAlign","verticalAlign","buttons","content","children","noColon"];var l=function(e){var t=e.children;return(0,o.createVNode)(1,"table","LabeledList",t,0)};t.LabeledList=l,l.defaultHooks=r.pureComponentHooks;var d=function(e){var t=e.className,n=e.label,c=e.labelColor,l=void 0===c?"label":c,d=e.color,u=e.textAlign,s=e.verticalAlign,m=e.buttons,p=e.content,h=e.children,f=e.noColon,C=void 0!==f&&f,N=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,i),b=C?"":":";return(0,o.createVNode)(1,"tr",(0,r.classes)(["LabeledList__row",t]),[(0,o.createComponentVNode)(2,a.Box,{as:"td",color:l,verticalAlign:s,className:(0,r.classes)(["LabeledList__cell","LabeledList__label"]),children:n?n+b:null}),(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({as:"td",color:d,textAlign:u,verticalAlign:s,className:(0,r.classes)(["LabeledList__cell","LabeledList__content"]),colSpan:m?undefined:2},N,{children:[p,h]}))),m&&(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__buttons",m,0)],0)};t.LabeledListItem=d,d.defaultHooks=r.pureComponentHooks;var u=function(e){var t=e.size?(0,a.unit)(Math.max(0,e.size-1)):0;return(0,o.createVNode)(1,"tr","LabeledList__row",(0,o.createVNode)(1,"td",null,(0,o.createComponentVNode)(2,c.Divider),2,{colSpan:3,style:{"padding-top":t,"padding-bottom":t}}),2)};t.LabeledListDivider=u,u.defaultHooks=r.pureComponentHooks,l.Item=d,l.Divider=u},function(e,t,n){"use strict";var o=n(7),r=o({}.toString),a=o("".slice);e.exports=function(e){return a(r(e),8,-1)}},function(e,t,n){"use strict";var o=n(7);e.exports=o({}.isPrototypeOf)},function(e,t,n){"use strict";var o=n(84),r=Function.prototype,a=r.apply,c=r.call;e.exports="object"==typeof Reflect&&Reflect.apply||(o?c.bind(a):function(){return c.apply(a,arguments)})},function(e,t,n){"use strict";var o=n(28);e.exports=o("navigator","userAgent")||""},function(e,t,n){"use strict";var o=n(8),r=n(17),a=n(64);e.exports=o?function(e,t,n){return r.f(e,t,a(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){"use strict";var o=n(40),r=Math.max,a=Math.min;e.exports=function(e,t){var n=o(e);return n<0?r(n+t,0):a(n,t)}},function(e,t,n){"use strict";var o,r=n(9),a=n(136),c=n(134),i=n(87),l=n(179),d=n(131),u=n(103),s=u("IE_PROTO"),m=function(){},p=function(e){return"