diff --git a/.gitignore b/.gitignore index f67727febb..f65245c021 100644 --- a/.gitignore +++ b/.gitignore @@ -195,6 +195,7 @@ Temporary Items #Visual studio stuff *.vscode/* +!/.vscode/extensions.json tools/MapAtmosFixer/MapAtmosFixer/obj/* tools/MapAtmosFixer/MapAtmosFixer/bin/* diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..ca0e6ad997 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "gbasood.byond-dm-language-support", + "platymuus.dm-langclient", + "EditorConfig.EditorConfig" + ] +} diff --git a/Dockerfile b/Dockerfile index ad347079cd..5f755e3dc1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM tgstation/byond:513.1490 as base +FROM tgstation/byond:513.1503 as base FROM base as build_base diff --git a/_maps/shuttles/infiltrator_basic.dmm b/_maps/shuttles/infiltrator_basic.dmm index f7ec35c667..1dffe12884 100644 --- a/_maps/shuttles/infiltrator_basic.dmm +++ b/_maps/shuttles/infiltrator_basic.dmm @@ -924,25 +924,16 @@ /turf/open/floor/plasteel/dark, /area/shuttle/syndicate/medical) "ce" = ( -/obj/item/sbeacondrop/bomb{ - pixel_y = 5 - }, -/obj/item/sbeacondrop/bomb, /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/effect/landmark/start/nuclear_equipment, +/obj/effect/landmark/start/nuclear_equipment, /turf/open/floor/plasteel/dark, /area/shuttle/syndicate/armory) "cf" = ( -/obj/item/grenade/syndieminibomb{ - pixel_x = 4; - pixel_y = 2 - }, -/obj/item/grenade/syndieminibomb{ - pixel_x = -1 - }, /obj/structure/table/reinforced, /obj/structure/window/reinforced{ dir = 4 @@ -956,6 +947,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/effect/landmark/start/nuclear_equipment/minibomb, /turf/open/floor/plasteel/dark, /area/shuttle/syndicate/armory) "cg" = ( diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index e8e91b73f0..0d2e88042d 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -276,8 +276,6 @@ #define COMSIG_TURF_MAKE_DRY "make_turf_try" //(max_strength, immediate, duration_decrease = INFINITY): Returns bool. #define COMSIG_COMPONENT_CLEAN_ACT "clean_act" //called on an object to clean it of cleanables. Usualy with soap: (num/strength) -//Blood color -#define COMSIG_BLOOD_COLOR "blood_DNA_to_color" //RGB blood stuff //Food #define COMSIG_FOOD_EATEN "food_eaten" //from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder) diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 8ae4e5c167..eee0676dec 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -96,12 +96,22 @@ #define NUKESTATE_CORE_EXPOSED 1 #define NUKESTATE_CORE_REMOVED 0 +#define NUKEUI_AWAIT_DISK 0 +#define NUKEUI_AWAIT_CODE 1 +#define NUKEUI_AWAIT_TIMER 2 +#define NUKEUI_AWAIT_ARM 3 +#define NUKEUI_TIMING 4 +#define NUKEUI_EXPLODED 5 + #define NUKE_OFF_LOCKED 0 #define NUKE_OFF_UNLOCKED 1 #define NUKE_ON_TIMING 2 #define NUKE_ON_EXPLODING 3 +#define MACHINE_NOT_ELECTRIFIED 0 +#define MACHINE_ELECTRIFIED_PERMANENT -1 +#define MACHINE_DEFAULT_ELECTRIFY_TIME 30 //these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified. #define PLANT_GENE_REMOVABLE (1<<0) -#define PLANT_GENE_EXTRACTABLE (1<<1) \ No newline at end of file +#define PLANT_GENE_EXTRACTABLE (1<<1) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8d2913629a..a7d6056ab9 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -200,9 +200,11 @@ #define NO_SLIP_WHEN_WALKING (1<<0) #define SLIDE (1<<1) #define GALOSHES_DONT_HELP (1<<2) -#define SLIDE_ICE (1<<3) -#define SLIP_WHEN_CRAWLING (1<<4) //clown planet ruin -#define SLIP_WHEN_JOGGING (1<<5) //slips prevented by walking are also dodged if the mob is not sprinting or fatigued... unless this flag is on. +#define FLYING_DOESNT_HELP (1<<3) +#define SLIDE_ICE (1<<4) +#define SLIP_WHEN_CRAWLING (1<<5) //clown planet ruin amongst others +#define SLIP_WHEN_JOGGING (1<<6) //slips prevented by walking are also dodged if the mob is nor sprinting or fatigued... unless this flag is on. + #define MAX_CHICKENS 50 diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm index e1fff1879e..af618cf828 100644 --- a/code/__DEFINES/time.dm +++ b/code/__DEFINES/time.dm @@ -54,5 +54,5 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using #define WORLDTIME2TEXT(format) GAMETIMESTAMP(format, world.time) #define WORLDTIMEOFDAY2TEXT(format) GAMETIMESTAMP(format, world.timeofday) #define TIME_STAMP(format, showds) showds ? "[WORLDTIMEOFDAY2TEXT(format)]:[world.timeofday % 10]" : WORLDTIMEOFDAY2TEXT(format) -#define STATION_TIME(display_only) ((((world.time - SSticker.round_start_time) * SSticker.station_time_rate_multiplier) + SSticker.gametime_offset) % 864000) - (display_only? GLOB.timezoneOffset : 0) -#define STATION_TIME_TIMESTAMP(format) time2text(STATION_TIME(TRUE), format) +#define STATION_TIME(display_only, wtime) ((((wtime - SSticker.round_start_time) * SSticker.station_time_rate_multiplier) + SSticker.gametime_offset) % 864000) - (display_only? GLOB.timezoneOffset : 0) +#define STATION_TIME_TIMESTAMP(format, wtime) time2text(STATION_TIME(TRUE, wtime), format) diff --git a/code/__DEFINES/typeids.dm b/code/__DEFINES/typeids.dm index 8bfe6216e2..275f7719f0 100644 --- a/code/__DEFINES/typeids.dm +++ b/code/__DEFINES/typeids.dm @@ -2,7 +2,7 @@ #define TYPEID_NULL "0" #define TYPEID_NORMAL_LIST "f" //helper macros -#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref)-6) ) ) +#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, -7) ) ) #define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 6ea1de0e2c..db8f4a1d0d 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -175,6 +175,11 @@ /proc/start_log(log) WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") +/* ui logging */ + +/proc/log_tgui(text) + WRITE_LOG(GLOB.tgui_log, text) + /* Close open log handles. This should be called as late as possible, and no logging should hapen after. */ /proc/shutdown_logging() rustg_log_close_all() diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index 4160c1976a..7c6c186bca 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -20,7 +20,7 @@ continue path += choice - if(copytext(path,-1,0) != "/") //didn't choose a directory, no need to iterate again + if(copytext_char(path, -1) != "/") //didn't choose a directory, no need to iterate again break var/extensions for(var/i in valid_extensions) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 8e88f869a9..aee0f3d7f7 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -985,7 +985,7 @@ world var/icon/atom_icon = new(A.icon, A.icon_state) if(!letter) - letter = copytext(A.name, 1, 2) + letter = A.name[1] if(uppercase == 1) letter = uppertext(letter) else if(uppercase == -1) @@ -1113,7 +1113,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 WRITE_FILE(GLOB.iconCache[iconKey], icon) var/iconData = GLOB.iconCache.ExportText(iconKey) var/list/partial = splittext(iconData, "{") - return replacetext(copytext(partial[2], 3, -5), "\n", "") + return replacetext(copytext_char(partial[2], 3, -5), "\n", "") /proc/icon2html(thing, target, icon_state, dir, frame = 1, moving = FALSE) if (!thing) diff --git a/code/__HELPERS/pronouns.dm b/code/__HELPERS/pronouns.dm index d1add9cb4c..bab286bafe 100644 --- a/code/__HELPERS/pronouns.dm +++ b/code/__HELPERS/pronouns.dm @@ -28,10 +28,10 @@ . = "does" /datum/proc/p_theyve(capitalized, temp_gender) - . = p_they(capitalized, temp_gender) + "'" + copytext(p_have(temp_gender), 3) + . = p_they(capitalized, temp_gender) + "'" + copytext_char(p_have(temp_gender), 3) /datum/proc/p_theyre(capitalized, temp_gender) - . = p_they(capitalized, temp_gender) + "'" + copytext(p_are(temp_gender), 2) + . = p_they(capitalized, temp_gender) + "'" + copytext_char(p_are(temp_gender), 2) /datum/proc/p_s(temp_gender) //is this a descriptive proc name, or what? . = "s" diff --git a/code/__HELPERS/radio.dm b/code/__HELPERS/radio.dm index 7ab21d0402..5fe87bdf5b 100644 --- a/code/__HELPERS/radio.dm +++ b/code/__HELPERS/radio.dm @@ -1,6 +1,6 @@ // Ensure the frequency is within bounds of what it should be sending/receiving at /proc/sanitize_frequency(frequency, free = FALSE) - . = round(frequency) + frequency = round(frequency) if(free) . = CLAMP(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ) else diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index b511c61971..faa8c22f38 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -43,24 +43,30 @@ if(!istext(color)) color = "" - var/start = 1 + (text2ascii(color,1)==35) + var/start = 1 + (text2ascii(color, 1) == 35) var/len = length(color) - var/step_size = 1 + ((len+1)-start != desired_format) + var/char = "" + // RRGGBB -> RGB but awful + var/convert_to_shorthand = desired_format == 3 && length_char(color) > 3 . = "" - for(var/i=start, i<=len, i+=step_size) - var/ascii = text2ascii(color,i) - switch(ascii) - if(48 to 57) - . += ascii2text(ascii) //numbers 0 to 9 - if(97 to 102) - . += ascii2text(ascii) //letters a to f - if(65 to 70) - . += ascii2text(ascii+32) //letters A to F - translates to lowercase + var/i = start + while(i <= len) + char = color[i] + switch(text2ascii(char)) + if(48 to 57) //numbers 0 to 9 + . += char + if(97 to 102) //letters a to f + . += char + if(65 to 70) //letters A to F + . += lowertext(char) else break + i += length(char) + if(convert_to_shorthand && i <= len) //skip next one + i += length(color[i]) - if(length(.) != desired_format) + if(length_char(.) != desired_format) if(default) return default return crunch + repeat_string(desired_format, "0") @@ -68,7 +74,9 @@ return crunch + . /proc/sanitize_ooccolor(color) - var/list/HSL = rgb2hsl(hex2num(copytext(color,2,4)),hex2num(copytext(color,4,6)),hex2num(copytext(color,6,8))) + if(length(color) != length_char(color)) + CRASH("Invalid characters in color '[color]'") + var/list/HSL = rgb2hsl(hex2num(copytext(color, 2, 4)), hex2num(copytext(color, 4, 6)), hex2num(copytext(color, 6, 8))) HSL[3] = min(HSL[3],0.4) var/list/RGB = hsl2rgb(arglist(HSL)) - return "#[num2hex(RGB[1],2)][num2hex(RGB[2],2)][num2hex(RGB[3],2)]" \ No newline at end of file + return "#[num2hex(RGB[1],2)][num2hex(RGB[2],2)][num2hex(RGB[3],2)]" diff --git a/code/__HELPERS/shell.dm b/code/__HELPERS/shell.dm index 8b615eac0a..3438f38b85 100644 --- a/code/__HELPERS/shell.dm +++ b/code/__HELPERS/shell.dm @@ -52,6 +52,6 @@ if(bad_chars) bad_match = url_encode(bad_chars_regex.match) scrubbed_url += bad_match - last_good = bad_chars + length(bad_match) + last_good = bad_chars + length(bad_chars_regex.match) while(bad_chars) . = scrubbed_url diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 60c43b0869..3985659b71 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -40,8 +40,8 @@ for(var/char in repl_chars) var/index = findtext(t, char) while(index) - t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+1) - index = findtext(t, char, index+1) + t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index + length(char)) + index = findtext(t, char, index + length(char)) return t /proc/sanitize_filename(t) @@ -63,22 +63,28 @@ //Returns null if there is any bad text in the string -/proc/reject_bad_text(text, max_length=512) - if(length(text) > max_length) - return //message too long - var/non_whitespace = 0 - for(var/i=1, i<=length(text), i++) - switch(text2ascii(text,i)) - if(62,60,92,47) - return //rejects the text if it contains these bad characters: <, >, \ or / - if(127 to 255) - return //rejects weird letters like � +/proc/reject_bad_text(text, max_length = 512, ascii_only = TRUE) + var/char_count = 0 + var/non_whitespace = FALSE + var/lenbytes = length(text) + var/char = "" + for(var/i = 1, i <= lenbytes, i += length(char)) + char = text[i] + char_count++ + if(char_count > max_length) + return + switch(text2ascii(char)) + if(62,60,92,47) // <, >, \, / + return if(0 to 31) - return //more weird stuff + return if(32) continue //whitespace + if(127 to INFINITY) + if(ascii_only) + return else - non_whitespace = 1 + non_whitespace = TRUE if(non_whitespace) return text //only accepts the text if it has some non-spaces @@ -101,73 +107,84 @@ else return trim(html_encode(name), max_length) +#define NO_CHARS_DETECTED 0 +#define SPACES_DETECTED 1 +#define SYMBOLS_DETECTED 2 +#define NUMBERS_DETECTED 3 +#define LETTERS_DETECTED 4 + //Filters out undesirable characters from names -/proc/reject_bad_name(t_in, allow_numbers=0, max_length=MAX_NAME_LEN) - if(!t_in || length(t_in) > max_length) - return //Rejects the input if it is null or if it is longer then the max length allowed +/proc/reject_bad_name(t_in, allow_numbers = FALSE, max_length = MAX_NAME_LEN, ascii_only = TRUE) + if(!t_in) + return //Rejects the input if it is null - var/number_of_alphanumeric = 0 - var/last_char_group = 0 + var/number_of_alphanumeric = 0 + var/last_char_group = NO_CHARS_DETECTED var/t_out = "" + var/t_len = length(t_in) + var/charcount = 0 + var/char = "" - for(var/i=1, i<=length(t_in), i++) - var/ascii_char = text2ascii(t_in,i) - switch(ascii_char) + + for(var/i = 1, i <= t_len, i += length(char)) + char = t_in[i] + + switch(text2ascii(char)) // A .. Z if(65 to 90) //Uppercase Letters - t_out += ascii2text(ascii_char) number_of_alphanumeric++ - last_char_group = 4 + last_char_group = LETTERS_DETECTED // a .. z if(97 to 122) //Lowercase Letters - if(last_char_group<2) - t_out += ascii2text(ascii_char-32) //Force uppercase first character - else - t_out += ascii2text(ascii_char) + if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED || last_char_group == SYMBOLS_DETECTED) //start of a word + char = uppertext(char) number_of_alphanumeric++ - last_char_group = 4 + last_char_group = LETTERS_DETECTED // 0 .. 9 if(48 to 57) //Numbers - if(!last_char_group) - continue //suppress at start of string - if(!allow_numbers) + if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string continue - t_out += ascii2text(ascii_char) number_of_alphanumeric++ - last_char_group = 3 + last_char_group = NUMBERS_DETECTED // ' - . if(39,45,46) //Common name punctuation - if(!last_char_group) + if(last_char_group == NO_CHARS_DETECTED) continue - t_out += ascii2text(ascii_char) - last_char_group = 2 + last_char_group = SYMBOLS_DETECTED // ~ | @ : # $ % & * + if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI) - if(!last_char_group) - continue //suppress at start of string - if(!allow_numbers) + if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string continue - t_out += ascii2text(ascii_char) - last_char_group = 2 + last_char_group = SYMBOLS_DETECTED //Space if(32) - if(last_char_group <= 1) - continue //suppress double-spaces and spaces at start of string - t_out += ascii2text(ascii_char) - last_char_group = 1 + if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED) //suppress double-spaces and spaces at start of string + continue + last_char_group = SPACES_DETECTED + + if(127 to INFINITY) + if(ascii_only) + continue + last_char_group = SYMBOLS_DETECTED //for now, we'll treat all non-ascii characters like symbols even though most are letters + else - return + continue + + t_out += char + charcount++ + if(charcount >= max_length) + break if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '" - if(last_char_group == 1) - t_out = copytext(t_out,1,length(t_out)) //removes the last character (in this case a space) + if(last_char_group == SPACES_DETECTED) + t_out = copytext_char(t_out, 1, -1) //removes the last character (in this case a space) for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai")) //prevents these common metagamey names if(cmptext(t_out,bad_name)) @@ -175,6 +192,11 @@ return t_out +#undef NO_CHARS_DETECTED +#undef SPACES_DETECTED +#undef NUMBERS_DETECTED +#undef LETTERS_DETECTED + //html_encode helper proc that returns the smallest non null of two numbers //or 0 if they're both null (needed because of findtext returning 0 when a value is not present) /proc/non_zero_min(a, b) @@ -184,39 +206,6 @@ return a return (a < b ? a : b) -/* - * Text searches - */ - -//Checks the beginning of a string for a specified sub-string -//Returns the position of the substring or 0 if it was not found -/proc/dd_hasprefix(text, prefix) - var/start = 1 - var/end = length(prefix) + 1 - return findtext(text, prefix, start, end) - -//Checks the beginning of a string for a specified sub-string. This proc is case sensitive -//Returns the position of the substring or 0 if it was not found -/proc/dd_hasprefix_case(text, prefix) - var/start = 1 - var/end = length(prefix) + 1 - return findtextEx(text, prefix, start, end) - -//Checks the end of a string for a specified substring. -//Returns the position of the substring or 0 if it was not found -/proc/dd_hassuffix(text, suffix) - var/start = length(text) - length(suffix) - if(start) - return findtext(text, suffix, start, null) - return - -//Checks the end of a string for a specified substring. This proc is case sensitive -//Returns the position of the substring or 0 if it was not found -/proc/dd_hassuffix_case(text, suffix) - var/start = length(text) - length(suffix) - if(start) - return findtextEx(text, suffix, start, null) - //Checks if any of a given list of needles is in the haystack /proc/text_in_list(haystack, list/needle_list, start=1, end=0) for(var/needle in needle_list) @@ -231,23 +220,19 @@ return 1 return 0 -//Adds 'u' number of zeros ahead of the text 't' -/proc/add_zero(t, u) - while (length(t) < u) - t = "0[t]" - return t +//Adds 'char' ahead of 'text' until there are 'count' characters total +/proc/add_leading(text, count, char = " ") + text = "[text]" + var/charcount = count - length_char(text) + var/list/chars_to_add[max(charcount + 1, 0)] + return jointext(chars_to_add, char) + text -//Adds 'u' number of spaces ahead of the text 't' -/proc/add_lspace(t, u) - while(length(t) < u) - t = " [t]" - return t - -//Adds 'u' number of spaces behind the text 't' -/proc/add_tspace(t, u) - while(length(t) < u) - t = "[t] " - return t +//Adds 'char' behind 'text' until there are 'count' characters total +/proc/add_trailing(text, count, char = " ") + text = "[text]" + var/charcount = count - length_char(text) + var/list/chars_to_add[max(charcount + 1, 0)] + return text + jointext(chars_to_add, char) //Returns a string with reserved characters and spaces before the first letter removed /proc/trim_left(text) @@ -267,57 +252,41 @@ //Returns a string with reserved characters and spaces before the first word and after the last word removed. /proc/trim(text, max_length) if(max_length) - text = copytext(text, 1, max_length) + text = copytext_char(text, 1, max_length) return trim_left(trim_right(text)) //Returns a string with the first element of the string capitalized. /proc/capitalize(t as text) - return uppertext(copytext(t, 1, 2)) + copytext(t, 2) - -//Centers text by adding spaces to either side of the string. -/proc/dd_centertext(message, length) - var/new_message = message - var/size = length(message) - var/delta = length - size - if(size == length) - return new_message - if(size > length) - return copytext(new_message, 1, length + 1) - if(delta == 1) - return new_message + " " - if(delta % 2) - new_message = " " + new_message - delta-- - var/spaces = add_lspace("",delta/2-1) - return spaces + new_message + spaces - -//Limits the length of the text. Note: MAX_MESSAGE_LEN and MAX_NAME_LEN are widely used for this purpose -/proc/dd_limittext(message, length) - var/size = length(message) - if(size <= length) - return message - return copytext(message, 1, length + 1) - + . = t + if(t) + . = t[1] + return uppertext(.) + copytext(t, 1 + length(.)) /proc/stringmerge(text,compare,replace = "*") //This proc fills in all spaces with the "replace" var (* by default) with whatever //is in the other string at the same spot (assuming it is not a replace char). //This is used for fingerprints var/newtext = text - if(length(text) != length(compare)) - return 0 - for(var/i = 1, i < length(text), i++) - var/a = copytext(text,i,i+1) - var/b = copytext(compare,i,i+1) + var/text_it = 1 //iterators + var/comp_it = 1 + var/newtext_it = 1 + var/text_length = length(text) + var/comp_length = length(compare) + while(comp_it <= comp_length && text_it <= text_length) + var/a = text[text_it] + var/b = compare[comp_it] //if it isn't both the same letter, or if they are both the replacement character //(no way to know what it was supposed to be) if(a != b) if(a == replace) //if A is the replacement char - newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1) + newtext = copytext(newtext, 1, newtext_it) + b + copytext(newtext, newtext_it + length(newtext[newtext_it])) else if(b == replace) //if B is the replacement char - newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1) + newtext = copytext(newtext, 1, newtext_it) + a + copytext(newtext, newtext_it + length(newtext[newtext_it])) else //The lists disagree, Uh-oh! return 0 + text_it += length(a) + comp_it += length(b) + newtext_it += length(newtext[newtext_it]) return newtext /proc/stringpercent(text,character = "*") @@ -326,16 +295,21 @@ if(!text || !character) return 0 var/count = 0 - for(var/i = 1, i <= length(text), i++) - var/a = copytext(text,i,i+1) + var/lentext = length(text) + var/a = "" + for(var/i = 1, i <= lentext, i += length(a)) + a = text[i] if(a == character) count++ return count /proc/reverse_text(text = "") var/new_text = "" - for(var/i = length(text); i > 0; i--) - new_text += copytext(text, i, i+1) + var/lentext = length(text) + var/letter = "" + for(var/i = 1, i <= lentext, i += length(letter)) + letter = text[i] + new_text = letter + new_text return new_text GLOBAL_LIST_INIT(zero_character_only, list("0")) @@ -358,15 +332,6 @@ GLOBAL_LIST_INIT(binary, list("0","1")) /proc/random_color() return random_string(6, GLOB.hex_characters) -/proc/add_zero2(t, u) - var/temp1 - while (length(t) < u) - t = "0[t]" - temp1 = t - if (length(t) > u) - temp1 = copytext(t,2,u+1) - return temp1 - //merges non-null characters (3rd argument) from "from" into "into". Returns result //e.g. into = "Hello World" // from = "Seeya______" @@ -379,41 +344,48 @@ GLOBAL_LIST_INIT(binary, list("0","1")) into = "" if(!istext(from)) from = "" - var/null_ascii = istext(null_char) ? text2ascii(null_char,1) : null_char - - var/previous = 0 + var/null_ascii = istext(null_char) ? text2ascii(null_char, 1) : null_char + var/copying_into = FALSE + var/char = "" var/start = 1 - var/end = length(into) + 1 - - for(var/i=1, i= text2ascii("a") && ca <= text2ascii("m")) - ca += 13 - else if(ca >= text2ascii("n") && ca <= text2ascii("z")) - ca -= 13 - else if(ca >= text2ascii("A") && ca <= text2ascii("M")) - ca += 13 - else if(ca >= text2ascii("N") && ca <= text2ascii("Z")) - ca -= 13 - result += ascii2text(ca) - return jointext(result, "") + var/lentext = length(text) + var/char = "" + var/ascii = 0 + . = "" + for(var/i = 1, i <= lentext, i += length(char)) + char = text[i] + ascii = text2ascii(char) + switch(ascii) + if(65 to 77, 97 to 109) //A to M, a to m + ascii += 13 + if(78 to 90, 110 to 122) //N to Z, n to z + ascii -= 13 + . += ascii2text(ascii) //Takes a list of values, sanitizes it down for readability and character count, //then exports it as a json file at data/npc_saves/[filename].json. @@ -599,7 +576,8 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return //Regular expressions are, as usual, absolute magic - var/regex/all_invalid_symbols = new("\[^ -~]+") + //Any characters outside of 32 (space) to 126 (~) because treating things you don't understand as "magic" is really stupid + var/regex/all_invalid_symbols = new(@"[^ -~]{1}") var/list/accepted = list() for(var/string in proposed) @@ -607,34 +585,44 @@ GLOBAL_LIST_INIT(binary, list("0","1")) continue var/buffer = "" var/early_culling = TRUE - for(var/pos = 1, pos <= length(string), pos++) - var/let = copytext(string, pos, (pos + 1) % length(string)) - if(early_culling && !findtext(let,GLOB.is_alphanumeric)) + var/lentext = length(string) + var/let = "" + + for(var/pos = 1, pos <= lentext, pos += length(let)) + let = string[pos] + if(!findtext(let, GLOB.is_alphanumeric)) continue early_culling = FALSE - buffer += let - if(!findtext(buffer,GLOB.is_alphanumeric)) + buffer = copytext(string, pos) + break + if(early_culling) //Never found any letters! Bail! continue + var/punctbuffer = "" - var/cutoff = length(buffer) - for(var/pos = length(buffer), pos >= 0, pos--) - var/let = copytext(buffer, pos, (pos + 1) % length(buffer)) - if(findtext(let,GLOB.is_alphanumeric)) + var/cutoff = 0 + lentext = length_char(buffer) + for(var/pos = 1, pos <= lentext, pos++) + let = copytext_char(buffer, -pos, -pos + 1) + if(!findtext(let, GLOB.is_punctuation)) //This won't handle things like Nyaaaa!~ but that's fine break - if(findtext(let,GLOB.is_punctuation)) - punctbuffer = let + punctbuffer //Note this isn't the same thing as using += - cutoff = pos + punctbuffer += let + cutoff += length(let) if(punctbuffer) //We clip down excessive punctuation to get the letter count lower and reduce repeats. It's not perfect but it helps. var/exclaim = FALSE var/question = FALSE var/periods = 0 - for(var/pos = length(punctbuffer), pos >= 0, pos--) - var/punct = copytext(punctbuffer, pos, (pos + 1) % length(punctbuffer)) - if(!exclaim && findtext(punct,"!")) + lentext = length(punctbuffer) + for(var/pos = 1, pos <= lentext, pos += length(let)) + let = punctbuffer[pos] + if(!exclaim && findtext(let, "!")) exclaim = TRUE - if(!question && findtext(punct,"?")) + if(question) + break + if(!question && findtext(let, "?")) question = TRUE - if(!exclaim && !question && findtext(punct,".")) + if(exclaim) + break + if(!exclaim && !question && findtext(let, ".")) //? and ! take priority over periods periods += 1 if(exclaim) if(question) @@ -643,15 +631,13 @@ GLOBAL_LIST_INIT(binary, list("0","1")) punctbuffer = "!" else if(question) punctbuffer = "?" - else if(periods) - if(periods > 1) - punctbuffer = "..." - else - punctbuffer = "" //Grammer nazis be damned - buffer = copytext(buffer, 1, cutoff) + punctbuffer - if(!findtext(buffer,GLOB.is_alphanumeric)) - continue - if(!buffer || length(buffer) > 280 || length(buffer) <= cullshort || buffer in accepted) + else if(periods > 1) + punctbuffer = "..." + else + punctbuffer = "" //Grammer nazis be damned + buffer = copytext(buffer, 1, -cutoff) + punctbuffer + lentext = length_char(buffer) + if(!buffer || lentext > 280 || lentext <= cullshort || (buffer in accepted)) continue accepted += buffer @@ -688,7 +674,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) var/leng = length(string) - var/next_space = findtext(string, " ", next_backslash + 1) + var/next_space = findtext(string, " ", next_backslash + length(string[next_backslash])) if(!next_space) next_space = leng - next_backslash @@ -696,8 +682,8 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return string var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash) - var/macro = lowertext(copytext(string, next_backslash + 1, next_space)) - var/rest = next_backslash > leng ? "" : copytext(string, next_space + 1) + var/macro = lowertext(copytext(string, next_backslash + length(string[next_space]), next_space)) + var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space])) //See https://secure.byond.com/docs/ref/info.html#/DM/text/macros switch(macro) @@ -769,28 +755,24 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return "[number]\th" /proc/unintelligize(message) - var/prefix=copytext(message,1,2) + var/regex/word_boundaries = regex(@"\b[\S]+\b", "g") + var/prefix = message[1] if(prefix == ";") - message = copytext(message,2) - else if(prefix in list(":","#")) - prefix += copytext(message,2,3) - message = copytext(message,3) + message = copytext(message, 1 + length(prefix)) + else if(prefix in list(":", "#")) + prefix += message[1 + length(prefix)] + message = copytext(message, length(prefix)) else - prefix="" + prefix = "" - var/list/words = splittext(message," ") var/list/rearranged = list() - for(var/i=1;i<=words.len;i++) - var/cword = pick(words) - words.Remove(cword) - var/suffix = copytext(cword,length(cword)-1,length(cword)) - while(length(cword)>0 && suffix in list(".",",",";","!",":","?")) - cword = copytext(cword,1 ,length(cword)-1) - suffix = copytext(cword,length(cword)-1,length(cword) ) + while(word_boundaries.Find(message)) + var/cword = word_boundaries.match if(length(cword)) rearranged += cword - message = "[prefix][jointext(rearranged," ")]" - . = message + shuffle_inplace(rearranged) + return "[prefix][jointext(rearranged, " ")]" + #define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97)) #define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1)) \ No newline at end of file diff --git a/code/__HELPERS/text_vr.dm b/code/__HELPERS/text_vr.dm index 9be806fc54..3c1e1eff12 100644 --- a/code/__HELPERS/text_vr.dm +++ b/code/__HELPERS/text_vr.dm @@ -8,14 +8,15 @@ index = findtext(t, char) return t -proc/TextPreview(var/string,var/len=40) - if(length(string) <= len) - if(!length(string)) +/proc/TextPreview(string, len = 40) + var/char_len = length_char(string) + if(char_len <= len) + if(char_len) return "\[...\]" else return string else - return "[copytext(string, 1, 37)]..." + return "[copytext_char(string, 1, 37)]..." GLOBAL_LIST_EMPTY(mentorlog) GLOBAL_PROTECT(mentorlog) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 823e893670..09047d32bf 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -542,17 +542,17 @@ //assumes format #RRGGBB #rrggbb /proc/color_hex2num(A) - if(!A) + if(!A || length(A) != length_char(A)) return 0 - var/R = hex2num(copytext(A,2,4)) - var/G = hex2num(copytext(A,4,6)) - var/B = hex2num(copytext(A,6,0)) + var/R = hex2num(copytext(A, 2, 4)) + var/G = hex2num(copytext(A, 4, 6)) + var/B = hex2num(copytext(A, 6, 0)) return R+G+B //word of warning: using a matrix like this as a color value will simplify it back to a string after being set /proc/color_hex2color_matrix(string) var/length = length(string) - if(length != 7 && length != 9) + if((length != 7 && length != 9) || length != length_char(string)) return color_matrix_identity() var/r = hex2num(copytext(string, 2, 4))/255 var/g = hex2num(copytext(string, 4, 6))/255 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 2f960e350b..86dde3d6a6 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -6,25 +6,18 @@ //Inverts the colour of an HTML string /proc/invertHTML(HTMLstring) - - if (!( istext(HTMLstring) )) + if(!istext(HTMLstring)) CRASH("Given non-text argument!") return - else - if (length(HTMLstring) != 7) - CRASH("Given non-HTML argument!") - return + else if(length(HTMLstring) != 7) + CRASH("Given non-HTML argument!") + return + else if(length_char(HTMLstring) != 7) + CRASH("Given non-hex symbols in argument!") var/textr = copytext(HTMLstring, 2, 4) var/textg = copytext(HTMLstring, 4, 6) var/textb = copytext(HTMLstring, 6, 8) - var/r = hex2num(textr) - var/g = hex2num(textg) - var/b = hex2num(textb) - textr = num2hex(255 - r, 2) - textg = num2hex(255 - g, 2) - textb = num2hex(255 - b, 2) - return text("#[][][]", textr, textg, textb) - return + return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb)) /proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. if(!start || !end) @@ -184,15 +177,15 @@ Turf and target are separate in case you want to teleport some distance from a t //Returns whether or not a player is a guest using their ckey as an input /proc/IsGuestKey(key) if (findtext(key, "Guest-", 1, 7) != 1) //was findtextEx - return 0 + return FALSE var/i, ch, len = length(key) - for (i = 7, i <= len, ++i) + for (i = 7, i <= len, ++i) //we know the first 6 chars are Guest- ch = text2ascii(key, i) - if (ch < 48 || ch > 57) - return 0 - return 1 + if (ch < 48 || ch > 57) //0-9 + return FALSE + return TRUE //Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame() /mob/proc/apply_pref_name(role, client/C) @@ -1314,7 +1307,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) /proc/GUID() var/const/GUID_VERSION = "b" var/const/GUID_VARIANT = "d" - var/node_id = copytext(md5("[rand()*rand(1,9999999)][world.name][world.hub][world.hub_password][world.internet_address][world.address][world.contents.len][world.status][world.port][rand()*rand(1,9999999)]"), 1, 13) + var/node_id = copytext_char(md5("[rand()*rand(1,9999999)][world.name][world.hub][world.hub_password][world.internet_address][world.address][world.contents.len][world.status][world.port][rand()*rand(1,9999999)]"), 1, 13) var/time_high = "[num2hex(text2num(time2text(world.realtime,"YYYY")), 2)][num2hex(world.realtime, 6)]" @@ -1501,3 +1494,47 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) return -1 else return 0 + +// Converts browser keycodes to BYOND keycodes. +/proc/browser_keycode_to_byond(keycode) + keycode = text2num(keycode) + switch(keycode) + // letters and numbers + if(65 to 90, 48 to 57) + return ascii2text(keycode) + if(17) + return "Ctrl" + if(18) + return "Alt" + if(16) + return "Shift" + if(37) + return "West" + if(38) + return "North" + if(39) + return "East" + if(40) + return "South" + if(45) + return "Insert" + if(46) + return "Delete" + if(36) + return "Northwest" + if(35) + return "Southwest" + if(33) + return "Northeast" + if(34) + return "Southeast" + if(112 to 123) + return "F[keycode-111]" + if(96 to 105) + return "Numpad[keycode-96]" + if(188) + return "," + if(190) + return "." + if(189) + return "-" \ No newline at end of file diff --git a/code/_compile_options.dm b/code/_compile_options.dm index af948086df..fe4761ddcd 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -39,6 +39,26 @@ #error You need version 512 or higher #endif +//Compatability -- These procs were added in 513.1493, not 513.1490 +//Which really shoulda bumped us up to 514 right then and there but instead Lummox is a dumb dumb +#if DM_BUILD < 1493 +#define length_char(args...) length(args) +#define text2ascii_char(args...) text2ascii(args) +#define copytext_char(args...) copytext(args) +#define splittext_char(args...) splittext(args) +#define spantext_char(args...) spantext(args) +#define nonspantext_char(args...) nonspantext(args) +#define findtext_char(args...) findtext(args) +#define findtextEx_char(args...) findtextEx(args) +#define findlasttext_char(args...) findlasttext(args) +#define findlasttextEx_char(args...) findlasttextEx(args) +#define replacetext_char(args...) replacetext(args) +#define replacetextEx_char(args...) replacetextEx(args) +// /regex procs +#define Find_char(args...) Find(args) +#define Replace_char(args...) Replace(args) +#endif + //Additional code for the above flags. #ifdef TESTING #warn compiling in TESTING mode. testing() debug messages will be visible. diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index ae385339be..ffad931cd8 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -91,13 +91,7 @@ GLOBAL_LIST_INIT(all_types_bloods,list( "BUG" )) -GLOBAL_LIST_INIT(blood_types, list( - "blood", - "jellyblood" +GLOBAL_LIST_INIT(blood_reagent_types, list( + /datum/reagent/blood, + /datum/reagent/blood/jellyblood )) - -GLOBAL_LIST_INIT(blood_id_types, list( - "blood" = /datum/reagent/blood, - "jellyblood" = /datum/reagent/blood/jellyblood - )) - diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 2d5d2388ec..ba75fbfc9c 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -46,6 +46,9 @@ GLOBAL_PROTECT(lastsignalers) GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was GLOBAL_PROTECT(lawchanges) +GLOBAL_VAR(tgui_log) +GLOBAL_PROTECT(tgui_log) + GLOBAL_LIST_EMPTY(combatlog) GLOBAL_PROTECT(combatlog) GLOBAL_LIST_EMPTY(IClog) diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 2a8289697b..ec4784bd1f 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -140,10 +140,7 @@ if(obj_flags & EMAGGED) return - if(locked) - bolt_raise(usr) - else - bolt_drop(usr) + toggle_bolt(usr) /obj/machinery/door/airlock/AIAltClick() // Eletrifies doors. if(obj_flags & EMAGGED) @@ -165,10 +162,7 @@ if(obj_flags & EMAGGED) return - if(!emergency) - emergency_on(usr) - else - emergency_off(usr) + toggle_emergency(usr) /* APC */ /obj/machinery/power/apc/AICtrlClick() // turns off/on APCs. diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm index d97e7c379a..d7323700e4 100644 --- a/code/controllers/configuration/config_entry.dm +++ b/code/controllers/configuration/config_entry.dm @@ -171,7 +171,8 @@ key_name = copytext(str_val, 1, key_pos) if(lowercase) key_name = lowertext(key_name) - key_value = copytext(str_val, key_pos + 1) + if(key_pos) + key_value = copytext(str_val, key_pos + length(str_val[key_pos])) var/new_key var/new_value var/continue_check_value diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index ad1f869057..79d125f608 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -109,13 +109,13 @@ if(!L) continue - var/firstchar = copytext(L, 1, 2) + var/firstchar = L[1] if(firstchar == "#") continue var/lockthis = firstchar == "@" if(lockthis) - L = copytext(L, 2) + L = copytext(L, length(firstchar) + 1) var/pos = findtext(L, " ") var/entry = null @@ -123,7 +123,7 @@ if(pos) entry = lowertext(copytext(L, 1, pos)) - value = copytext(L, pos + 1) + value = copytext(L, pos + length(L[pos])) else entry = lowertext(L) @@ -269,7 +269,7 @@ t = trim(t) if(length(t) == 0) continue - else if(copytext(t, 1, 2) == "#") + else if(t[1] == "#") continue var/pos = findtext(t, " ") @@ -278,7 +278,7 @@ if(pos) command = lowertext(copytext(t, 1, pos)) - data = copytext(t, pos + 1) + data = copytext(t, pos + length(t[pos])) else command = lowertext(t) diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm index 1ecbbede1f..78b2e63cf2 100644 --- a/code/controllers/subsystem/nightshift.dm +++ b/code/controllers/subsystem/nightshift.dm @@ -26,7 +26,7 @@ SUBSYSTEM_DEF(nightshift) /datum/controller/subsystem/nightshift/proc/check_nightshift() var/emergency = GLOB.security_level >= SEC_LEVEL_RED var/announcing = TRUE - var/time = STATION_TIME(FALSE) + var/time = STATION_TIME(FALSE, world.time) var/night_time = (time < nightshift_end_time) || (time > nightshift_start_time) if(high_security_mode != emergency) high_security_mode = emergency diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index 5aa109b63a..dd9848e465 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -39,34 +39,34 @@ SUBSYSTEM_DEF(pai) switch(option) if("name") - t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text + t = reject_bad_name(stripped_input(usr, "Enter a name for your pAI", "pAI Name", candidate.name, MAX_NAME_LEN), TRUE) if(t) - candidate.name = copytext(sanitize(t),1,MAX_NAME_LEN) + candidate.name = t if("desc") - t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message + t = stripped_multiline_input(usr, "Enter a description for your pAI", "pAI Description", candidate.description, MAX_MESSAGE_LEN) if(t) - candidate.description = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + candidate.description = t if("role") - t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text + t = stripped_input(usr, "Enter a role for your pAI", "pAI Role", candidate.role, MAX_MESSAGE_LEN) if(t) - candidate.role = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + candidate.role = t if("ooc") - t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message + t = stripped_multiline_input(usr, "Enter any OOC comments", "pAI OOC Comments", candidate.comments, MAX_MESSAGE_LEN) if(t) - candidate.comments = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + candidate.comments = t if("save") candidate.savefile_save(usr) if("load") candidate.savefile_load(usr) //In case people have saved unsanitized stuff. if(candidate.name) - candidate.name = copytext(sanitize(candidate.name),1,MAX_NAME_LEN) + candidate.name = copytext_char(sanitize(candidate.name),1,MAX_NAME_LEN) if(candidate.description) - candidate.description = copytext(sanitize(candidate.description),1,MAX_MESSAGE_LEN) + candidate.description = copytext_char(sanitize(candidate.description),1,MAX_MESSAGE_LEN) if(candidate.role) - candidate.role = copytext(sanitize(candidate.role),1,MAX_MESSAGE_LEN) + candidate.role = copytext_char(sanitize(candidate.role),1,MAX_MESSAGE_LEN) if(candidate.comments) - candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN) + candidate.comments = copytext_char(sanitize(candidate.comments),1,MAX_MESSAGE_LEN) if("submit") if(isobserver(usr)) diff --git a/code/controllers/subsystem/processing/networks.dm b/code/controllers/subsystem/processing/networks.dm index 03276d5b26..f7f16538a6 100644 --- a/code/controllers/subsystem/processing/networks.dm +++ b/code/controllers/subsystem/processing/networks.dm @@ -46,6 +46,6 @@ PROCESSING_SUBSYSTEM_DEF(networks) var/hex = md5(string) if(!hex) return //errored - . = "[copytext(hex, 1, 9)]" //16 ^ 8 possibilities I think. + . = "[copytext_char(hex, 1, 9)]" //16 ^ 8 possibilities I think. if(interfaces_by_id[.]) return resolve_collisions? make_address("[num2text(rand(HID_RESTRICTED_END, 999999999), 12)]"):null diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm index b10d0af8c5..dacbac409d 100644 --- a/code/controllers/subsystem/tgui.dm +++ b/code/controllers/subsystem/tgui.dm @@ -11,7 +11,7 @@ SUBSYSTEM_DEF(tgui) var/basehtml // The HTML base used for all UIs. /datum/controller/subsystem/tgui/PreInit() - basehtml = file2text('tgui/tgui.html') + basehtml = file2text('tgui-next/packages/tgui/public/tgui-main.html') /datum/controller/subsystem/tgui/Shutdown() close_all_uis() diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm index 779b186d08..cd53c8f0ba 100644 --- a/code/controllers/subsystem/time_track.dm +++ b/code/controllers/subsystem/time_track.dm @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(time_track) var/time_dilation_text /datum/controller/subsystem/time_track/fire() - stat_time_text = "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]\n\nRound Time: [WORLDTIME2TEXT("hh:mm:ss")]\n\nStation Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]\n\n[time_dilation_text]" + stat_time_text = "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]\n\nRound Time: [WORLDTIME2TEXT("hh:mm:ss")]\n\nStation Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]\n\n[time_dilation_text]" if(++last_measurement == measurement_delay) last_measurement = 0 diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 9005a788b7..d8bfe2c35c 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -153,7 +153,7 @@ to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)) /mob/camera/imaginary_friend/proc/friend_talk(message) - message = capitalize(trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))) + message = capitalize(trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))) if(!message) return diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 235417d62c..d653671b5a 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -199,13 +199,16 @@ var/list/new_message = list() for(var/word in message_split) - var/suffix = copytext(word,-1) + var/suffix = "" + var/suffix_foundon = 0 + for(var/potential_suffix in list("." , "," , ";" , "!" , ":" , "?")) + suffix_foundon = findtext(word, potential_suffix, -length(potential_suffix)) + if(suffix_foundon) + suffix = potential_suffix + break - // Check if we have a suffix and break it out of the word - if(suffix in list("." , "," , ";" , "!" , ":" , "?")) - word = copytext(word,1,-1) - else - suffix = "" + if(suffix_foundon) + word = copytext(word, 1, suffix_foundon) word = html_decode(word) @@ -216,10 +219,9 @@ new_message += pick("uh","erm") break else - var/list/charlist = string2charlist(word) // Stupid shit code + var/list/charlist = text2charlist(word) shuffle_inplace(charlist) - charlist.len = round(charlist.len * 0.5,1) - new_message += html_encode(jointext(charlist,"")) + suffix + new_message += jointext(charlist, "") + suffix message = jointext(new_message, " ") diff --git a/code/datums/browser.dm b/code/datums/browser.dm index b226d85112..779391c4de 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -39,12 +39,12 @@ //title_image = ntitle_image /datum/browser/proc/add_stylesheet(name, file) - stylesheets["[ckey(name)].css"] = file - register_asset("[ckey(name)].css", file) - -/datum/browser/proc/add_script(name, file) - scripts["[ckey(name)].js"] = file - register_asset("[ckey(name)].js", file) + if(istype(name, /datum/asset/spritesheet)) + var/datum/asset/spritesheet/sheet = name + stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]" + else + stylesheets["[ckey(name)].css"] = file + register_asset("[ckey(name)].css", file) /datum/browser/proc/set_content(ncontent) content = ncontent diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 6682c3901d..bf53414537 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -11,5 +11,5 @@ /datum/component/slippery/proc/Slip(datum/source, atom/movable/AM) var/mob/victim = AM - if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags) && callback) + if(istype(victim) && victim.slip(intensity, parent, lube_flags) && callback) callback.Invoke(victim) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 2c3b7518ba..5057253522 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -294,4 +294,4 @@ GLOBAL_LIST_EMPTY(uplinks) if(!T) return explosion(T,1,2,3) - qdel(parent) //Alternatively could brick the uplink. + qdel(parent) //Alternatively could brick the uplink. \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index f127023e8a..c34ab566cf 100644 --- a/code/datums/diseases/advance/symptoms/choking.dm +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -28,8 +28,10 @@ Bonus base_message_chance = 15 symptom_delay_min = 10 symptom_delay_max = 30 - threshold_desc = "Stage Speed 8: Causes choking more frequently.
\ - Stealth 4: The symptom remains hidden until active." + threshold_desc = list( + "Stage Speed 8" = "Causes choking more frequently.", + "Stealth 4" = "The symptom remains hidden until active." + ) /datum/symptom/choking/Start(datum/disease/advance/A) if(!..()) @@ -99,8 +101,10 @@ Bonus symptom_delay_min = 14 symptom_delay_max = 30 var/paralysis = FALSE - threshold_desc = "Stage Speed 8: Additionally synthesizes pancuronium and sodium thiopental inside the host.
\ - Transmission 8: Doubles the damage caused by the symptom." + threshold_desc = list( + "Stage Speed 8" = "Additionally synthesizes pancuronium and sodium thiopental inside the host.", + "Transmission 8" = "Doubles the damage caused by the symptom." + ) /datum/symptom/asphyxiation/Start(datum/disease/advance/A) diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm index eb6c5342f9..b8a1064c34 100644 --- a/code/datums/diseases/advance/symptoms/confusion.dm +++ b/code/datums/diseases/advance/symptoms/confusion.dm @@ -29,9 +29,11 @@ Bonus symptom_delay_min = 10 symptom_delay_max = 30 var/brain_damage = FALSE - threshold_desc = "Resistance 6: Causes brain damage over time.
\ - Transmission 6: Increases confusion duration.
\ - Stealth 4: The symptom remains hidden until active." + threshold_desc = list( + "Resistance 6" = "Causes brain damage over time.", + "Transmission 6" = "Increases confusion duration and strength.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/confusion/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm index 62c64159d1..cf15ec407a 100644 --- a/code/datums/diseases/advance/symptoms/cough.dm +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -29,12 +29,13 @@ BONUS symptom_delay_min = 2 symptom_delay_max = 15 var/infective = FALSE - threshold_desc = "Resistance 3: Host will drop small items when coughing.
\ - Resistance 10: Occasionally causes coughing fits that stun the host.
\ - Stage Speed 6: Increases cough frequency.
\ - If Airborne: Coughing will infect bystanders.
\ - Stealth 4: The symptom remains hidden until active." - + threshold_desc = list( + "Resistance 11" = "The host will drop small items when coughing.", + "Resistance 15" = "Occasionally causes coughing fits that stun the host. The extra coughs do not spread the virus.", + "Stage Speed 6" = "Increases cough frequency.", + "Transmission 7" = "Coughing will now infect bystanders up to 2 tiles away.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/cough/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm index e0336506e3..b6dd185b36 100644 --- a/code/datums/diseases/advance/symptoms/deafness.dm +++ b/code/datums/diseases/advance/symptoms/deafness.dm @@ -28,8 +28,10 @@ Bonus base_message_chance = 100 symptom_delay_min = 25 symptom_delay_max = 80 - threshold_desc = "Resistance 9: Causes permanent deafness, instead of intermittent.
\ - Stealth 4: The symptom remains hidden until active." + threshold_desc = list( + "Resistance 9" = "Causes permanent deafness, instead of intermittent.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/deafness/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm index b4b06be5ac..be444e3916 100644 --- a/code/datums/diseases/advance/symptoms/dizzy.dm +++ b/code/datums/diseases/advance/symptoms/dizzy.dm @@ -27,8 +27,10 @@ Bonus base_message_chance = 50 symptom_delay_min = 15 symptom_delay_max = 40 - threshold_desc = "Transmission 6: Also causes druggy vision.
\ - Stealth 4: The symptom remains hidden until active." + threshold_desc = list( + "Transmission 6" = "Also causes druggy vision.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/dizzy/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm index a178cba196..0348e39818 100644 --- a/code/datums/diseases/advance/symptoms/fever.dm +++ b/code/datums/diseases/advance/symptoms/fever.dm @@ -28,9 +28,10 @@ Bonus symptom_delay_min = 10 symptom_delay_max = 30 var/unsafe = FALSE //over the heat threshold - threshold_desc = "Resistance 5: Increases fever intensity, fever can overheat and harm the host.
\ - Resistance 10: Further increases fever intensity." - + threshold_desc = list( + "Resistance 5" = "Increases fever intensity, fever can overheat and harm the host.", + "Resistance 10" = "Further increases fever intensity.", + ) /datum/symptom/fever/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm index 7ad030594d..ea1897b67d 100644 --- a/code/datums/diseases/advance/symptoms/fire.dm +++ b/code/datums/diseases/advance/symptoms/fire.dm @@ -29,11 +29,12 @@ Bonus symptom_delay_min = 20 symptom_delay_max = 75 var/infective = FALSE - threshold_desc = "Stage Speed 4: Increases the intensity of the flames.
\ - Stage Speed 8: Further increases flame intensity.
\ - Transmission 8: Host will spread the virus through skin flakes when bursting into flame.
\ - Stealth 4: The symptom remains hidden until active." - + threshold_desc = list( + "Stage Speed 4" = "Increases the intensity of the flames.", + "Stage Speed 8" = "Further increases flame intensity.", + "Transmission 8" = "Host will spread the virus through skin flakes when bursting into flame.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/fire/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm index 5ed50b998f..774d97202e 100644 --- a/code/datums/diseases/advance/symptoms/flesh_eating.dm +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -30,8 +30,11 @@ Bonus symptom_delay_max = 60 var/bleed = FALSE var/pain = FALSE - threshold_desc = "Resistance 7: Host will bleed profusely during necrosis.
\ - Transmission 8: Causes extreme pain to the host, weakening it." + threshold_desc = list( + "Resistance 9" = "Doubles the intensity of the immolation effect, but reduces the frequency of all of this symptom's effects.", + "Stage Speed 8" = "Increases explosion radius and explosion damage to the host when the host is wet.", + "Transmission 8" = "Additionally synthesizes chlorine trifluoride and napalm inside the host. More chemicals are synthesized if the resistance 9 threshold has been met." + ) /datum/symptom/flesh_eating/Start(datum/disease/advance/A) if(!..()) @@ -96,8 +99,11 @@ Bonus symptom_delay_max = 6 var/chems = FALSE var/zombie = FALSE - threshold_desc = "Stage Speed 7: Synthesizes Heparin and Lipolicide inside the host, causing increased bleeding and hunger.
\ - Stealth 5: The symptom remains hidden until active." + threshold_desc = list( + "Stage Speed 7" = "Synthesizes Heparin and Lipolicide inside the host, causing increased bleeding and hunger.", + "Stealth 5" = "The symptom remains hidden until active.", + ) + /datum/symptom/flesh_death/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm index 7f21b03dff..f6780df3fa 100644 --- a/code/datums/diseases/advance/symptoms/genetics.dm +++ b/code/datums/diseases/advance/symptoms/genetics.dm @@ -30,9 +30,12 @@ Bonus symptom_delay_min = 60 symptom_delay_max = 120 var/no_reset = FALSE - threshold_desc = "Resistance 8: Causes two harmful mutations at once.
\ - Stage Speed 10: Increases mutation frequency.
\ - Stealth 5: The mutations persist even if the virus is cured." + threshold_desc = list( + "Resistance 8" = "The negative and mildly negative mutations caused by the virus are mutadone-proof (but will still be undone when the virus is cured if the resistance 14 threshold is not met).", + "Resistance 14" = "The host's genetic alterations are not undone when the virus is cured.", + "Stage Speed 10" = "The virus activates dormant mutations at a much faster rate.", + "Stealth 5" = "Only activates negative mutations in hosts." + ) /datum/symptom/genetic_mutation/Activate(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm index 62f88cda54..4778e7d863 100644 --- a/code/datums/diseases/advance/symptoms/hallucigen.dm +++ b/code/datums/diseases/advance/symptoms/hallucigen.dm @@ -28,8 +28,10 @@ Bonus symptom_delay_min = 25 symptom_delay_max = 90 var/fake_healthy = FALSE - threshold_desc = "Stage Speed 7: Increases the amount of hallucinations.
\ - Stealth 4: The virus mimics positive symptoms.." + threshold_desc = list( + "Stage Speed 7" = "Increases the amount of hallucinations.", + "Stealth 4" = "The virus mimics positive symptoms.", + ) /datum/symptom/hallucigen/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm index 72b03000ed..944333d9cf 100644 --- a/code/datums/diseases/advance/symptoms/headache.dm +++ b/code/datums/diseases/advance/symptoms/headache.dm @@ -29,9 +29,11 @@ BONUS base_message_chance = 100 symptom_delay_min = 15 symptom_delay_max = 30 - threshold_desc = "Stage Speed 6: Headaches will cause severe pain, that weakens the host.
\ - Stage Speed 9: Headaches become less frequent but far more intense, preventing any action from the host.
\ - Stealth 4: Reduces headache frequency until later stages." + threshold_desc = list( + "Stage Speed 6" = "Headaches will cause severe pain, that weakens the host.", + "Stage Speed 9" = "Headaches become less frequent but far more intense, preventing any action from the host.", + "Stealth 4" = "Reduces headache frequency until later stages.", + ) /datum/symptom/headache/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index c1b3526f41..cf14da36a0 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -10,9 +10,10 @@ symptom_delay_min = 1 symptom_delay_max = 1 var/passive_message = "" //random message to infected but not actively healing people - threshold_desc = "Stage Speed 6: Doubles healing speed.
\ - Stealth 4: Healing will no longer be visible to onlookers." - + threshold_desc = list( + "Stage Speed 6" = "Doubles healing speed.", + "Stealth 4" = "Healing will no longer be visible to onlookers.", + ) /datum/symptom/heal/Start(datum/disease/advance/A) if(!..()) return @@ -54,8 +55,10 @@ level = 6 passive_message = "You miss the feeling of starlight on your skin." var/nearspace_penalty = 0.3 - threshold_desc = "Stage Speed 6: Increases healing speed.
\ - Transmission 6: Removes penalty for only being close to space." + threshold_desc = list( + "Stage Speed 6" = "Increases healing speed.", + "Transmission 6" = "Removes penalty for only being close to space.", + ) /datum/symptom/heal/starlight/Start(datum/disease/advance/A) if(!..()) @@ -105,8 +108,10 @@ level = 7 var/food_conversion = FALSE desc = "The virus rapidly breaks down any foreign chemicals in the bloodstream." - threshold_desc = "Resistance 7: Increases chem removal speed.
\ - Stage Speed 6: Consumed chemicals nourish the host." + threshold_desc = list( + "Resistance 7" = "Increases chem removal speed.", + "Stage Speed 6" = "Consumed chemicals nourish the host.", + ) /datum/symptom/heal/chem/Start(datum/disease/advance/A) if(!..()) @@ -139,9 +144,10 @@ var/reduced_hunger = FALSE desc = "The virus causes the host's metabolism to accelerate rapidly, making them process chemicals twice as fast,\ but also causing increased hunger." - threshold_desc = "Stealth 3: Reduces hunger rate.
\ - Stage Speed 10: Chemical metabolization is tripled instead of doubled." - + threshold_desc = list( + "Stealth 3" = "Reduces hunger rate.", + "Stage Speed 10" = "Chemical metabolization is tripled instead of doubled.", + ) /datum/symptom/heal/metabolism/Start(datum/disease/advance/A) if(!..()) return @@ -172,8 +178,9 @@ transmittable = -1 level = 6 passive_message = "You feel tingling on your skin as light passes over it." - threshold_desc = "Stage Speed 8: Doubles healing speed." - + threshold_desc = list( + "Stage Speed 8" = "Doubles healing speed.", + ) /datum/symptom/heal/darkness/Start(datum/disease/advance/A) if(!..()) return @@ -222,9 +229,11 @@ var/deathgasp = FALSE var/stabilize = FALSE var/active_coma = FALSE //to prevent multiple coma procs - threshold_desc = "Stealth 2: Host appears to die when falling into a coma.
\ - Resistance 4: The virus also stabilizes the host while they are in critical condition.
\ - Stage Speed 7: Increases healing speed." + threshold_desc = list( + "Stealth 2" = "Host appears to die when falling into a coma.", + "Resistance 4" = "The virus also stabilizes the host while they are in critical condition.", + "Stage Speed 7" = "Increases healing speed.", + ) /datum/symptom/heal/coma/Start(datum/disease/advance/A) if(!..()) @@ -313,8 +322,10 @@ level = 6 passive_message = "Your skin feels oddly dry..." var/absorption_coeff = 1 - threshold_desc = "Resistance 5: Water is consumed at a much slower rate.
\ - Stage Speed 7: Increases healing speed." + threshold_desc = list( + "Resistance 5" = "Water is consumed at a much slower rate.", + "Stage Speed 7" = "Increases healing speed.", + ) /datum/symptom/heal/water/Start(datum/disease/advance/A) if(!..()) @@ -369,9 +380,10 @@ level = 8 passive_message = "You feel an odd attraction to plasma." var/temp_rate = 1 - threshold_desc = "Transmission 6: Increases temperature adjustment rate and heals toxin lovers.
\ - Stage Speed 7: Increases healing speed." - + threshold_desc = list( + "Transmission 6" = "Additionally increases temperature adjustment rate and heals those who love toxins", + "Resistance 7" = "Increases healing speed.", + ) /datum/symptom/heal/plasma/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm index b0812e0235..c0c312cbc2 100644 --- a/code/datums/diseases/advance/symptoms/itching.dm +++ b/code/datums/diseases/advance/symptoms/itching.dm @@ -29,8 +29,10 @@ BONUS symptom_delay_min = 5 symptom_delay_max = 25 var/scratch = FALSE - threshold_desc = "Transmission 6: Increases frequency of itching.
\ - Stage Speed 7: The host will scrath itself when itching, causing superficial damage." + threshold_desc = list( + "Transmission 6" = "Increases frequency of itching.", + "Stage Speed 7" = "The host will scrath itself when itching, causing superficial damage.", + ) /datum/symptom/itching/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/nanites.dm b/code/datums/diseases/advance/symptoms/nanites.dm index b18e089a41..9598b3fd33 100644 --- a/code/datums/diseases/advance/symptoms/nanites.dm +++ b/code/datums/diseases/advance/symptoms/nanites.dm @@ -10,8 +10,10 @@ symptom_delay_min = 1 symptom_delay_max = 1 var/reverse_boost = FALSE - threshold_desc = "Transmission 5: Increases the virus' growth rate while nanites are present.
\ - Stage Speed 7: Increases the replication boost." + threshold_desc = list( + "Transmission 5" = "Increases the virus' growth rate while nanites are present.", + "Stage Speed 7" = "Increases the replication boost." + ) /datum/symptom/nano_boost/Start(datum/disease/advance/A) if(!..()) @@ -42,8 +44,10 @@ symptom_delay_min = 1 symptom_delay_max = 1 var/reverse_boost = FALSE - threshold_desc = "Stage Speed 5: Increases the virus' growth rate while nanites are present.
\ - Resistance 7: Severely increases the rate at which the nanites are destroyed." + threshold_desc = list( + "Stage Speed 5" = "Increases the virus' growth rate while nanites are present.", + "Resistance 7" = "Severely increases the rate at which the nanites are destroyed." + ) /datum/symptom/nano_destroy/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/narcolepsy.dm b/code/datums/diseases/advance/symptoms/narcolepsy.dm index 839a184609..3f9405328a 100644 --- a/code/datums/diseases/advance/symptoms/narcolepsy.dm +++ b/code/datums/diseases/advance/symptoms/narcolepsy.dm @@ -26,8 +26,10 @@ Bonus var/sleep_level = 0 var/sleepy_ticks = 0 var/stamina = FALSE - threshold_desc = "Transmission 7: Also relaxes the muscles, weakening and slowing the host.
\ - Resistance 10: Causes narcolepsy more often, increasing the chance of the host falling asleep." + threshold_desc = list( + "Transmission 4" = "Causes the host to periodically emit a yawn that spreads the virus in a manner similar to that of a sneeze.", + "Stage Speed 10" = "Causes narcolepsy more often, increasing the chance of the host falling asleep.", + ) /datum/symptom/narcolepsy/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm index e66bdf5ee0..3821c0585e 100644 --- a/code/datums/diseases/advance/symptoms/oxygen.dm +++ b/code/datums/diseases/advance/symptoms/oxygen.dm @@ -28,7 +28,9 @@ Bonus symptom_delay_min = 1 symptom_delay_max = 1 var/regenerate_blood = FALSE - threshold_desc = "Resistance 8:Additionally regenerates lost blood.
" + threshold_desc = list( + "Resistance 8" = "Additionally regenerates lost blood." + ) /datum/symptom/oxygen/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index 1f8cc8d7af..bbacdd885d 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -11,9 +11,11 @@ var/purge_alcohol = FALSE var/trauma_heal_mild = FALSE var/trauma_heal_severe = FALSE - threshold_desc = "Resistance 6: Heals minor brain traumas.
\ - Resistance 9: Heals severe brain traumas.
\ - Transmission 8: Purges alcohol in the bloodstream." + threshold_desc = list( + "Resistance 6" = "Heals minor brain traumas.", + "Resistance 9" = "Heals severe brain traumas.", + "Transmission 8" = "Purges alcohol in the bloodstream.", + ) /datum/symptom/mind_restoration/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm index de51d9e2a2..da14ed87cf 100644 --- a/code/datums/diseases/advance/symptoms/shivering.dm +++ b/code/datums/diseases/advance/symptoms/shivering.dm @@ -27,8 +27,10 @@ Bonus symptom_delay_min = 10 symptom_delay_max = 30 var/unsafe = FALSE //over the cold threshold - threshold_desc = "Stage Speed 5: Increases cooling speed; the host can fall below safe temperature levels.
\ - Stage Speed 10: Further increases cooling speed." + threshold_desc = list( + "Stage Speed 5" = "Increases cooling speed,; the host can fall below safe temperature levels.", + "Stage Speed 10" = "Further increases cooling speed." + ) /datum/symptom/fever/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 9f1696c963..439f391fe4 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -27,8 +27,10 @@ Bonus severity = 1 symptom_delay_min = 5 symptom_delay_max = 35 - threshold_desc = "Transmission 9: Increases sneezing range, spreading the virus over a larger area.
\ - Stealth 4: The symptom remains hidden until active." + threshold_desc = list( + "Transmission 9" = "Increases sneezing range, spreading the virus over 6 meter cone instead of over a 4 meter cone.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/sneeze/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm index b4a33cb837..6c9ad5a941 100644 --- a/code/datums/diseases/advance/symptoms/vision.dm +++ b/code/datums/diseases/advance/symptoms/vision.dm @@ -29,9 +29,10 @@ Bonus symptom_delay_min = 25 symptom_delay_max = 80 var/remove_eyes = FALSE - threshold_desc = "Resistance 12: Weakens extraocular muscles, eventually leading to complete detachment of the eyes.
\ - Stealth 4: The symptom remains hidden until active." - + threshold_desc = list( + "Resistance 12" = "Weakens extraocular muscles, eventually leading to complete detachment of the eyes.", + "Stealth 4" = "The symptom remains hidden until active.", + ) /datum/symptom/visionloss/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/voice_change.dm b/code/datums/diseases/advance/symptoms/voice_change.dm index 8b9b7d069a..9be484d99a 100644 --- a/code/datums/diseases/advance/symptoms/voice_change.dm +++ b/code/datums/diseases/advance/symptoms/voice_change.dm @@ -31,9 +31,11 @@ Bonus var/scramble_language = FALSE var/datum/language/current_language var/datum/language_holder/original_language - threshold_desc = "Transmission 14: The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.
\ - Stage Speed 7: Changes voice more often.
\ - Stealth 3: The symptom remains hidden until active." + threshold_desc = list( + "Transmission 14" = "The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.", + "Stage Speed 7" = "Changes voice more often.", + "Stealth 3" = "The symptom remains hidden until active." + ) /datum/symptom/voice_change/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm index 905a9827d5..22e249a388 100644 --- a/code/datums/diseases/advance/symptoms/vomit.dm +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -34,9 +34,11 @@ Bonus symptom_delay_max = 80 var/vomit_blood = FALSE var/proj_vomit = 0 - threshold_desc = "Resistance 7: Host will vomit blood, causing internal damage.
\ - Transmission 7: Host will projectile vomit, increasing vomiting range.
\ - Stealth 4: The symptom remains hidden until active." + threshold_desc = list( + "Resistance 7" = "Host will vomit blood, causing internal damage.", + "Transmission 7" = "Host will projectile vomit, increasing vomiting range.", + "Stealth 4" = "The symptom remains hidden until active." + ) /datum/symptom/vomit/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index 66fc90f1f8..5eab698750 100644 --- a/code/datums/diseases/advance/symptoms/weight.dm +++ b/code/datums/diseases/advance/symptoms/weight.dm @@ -29,7 +29,9 @@ Bonus base_message_chance = 100 symptom_delay_min = 15 symptom_delay_max = 45 - threshold_desc = "Stealth 4: The symptom is less noticeable." + threshold_desc = list( + "Stealth 4" = "The symptom is less noticeable." + ) /datum/symptom/weight_loss/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 5fa991c10c..68c6839482 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -370,14 +370,14 @@ /////////////////////////// DNA HELPER-PROCS ////////////////////////////// /proc/getleftblocks(input,blocknumber,blocksize) if(blocknumber > 1) - return copytext(input,1,((blocksize*blocknumber)-(blocksize-1))) + return copytext_char(input,1,((blocksize*blocknumber)-(blocksize-1))) /proc/getrightblocks(input,blocknumber,blocksize) if(blocknumber < (length(input)/blocksize)) - return copytext(input,blocksize*blocknumber+1,length(input)+1) + return copytext_char(input,blocksize*blocknumber+1,length(input)+1) /proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) - return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) + return copytext_char(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) /proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) if(!istring || !blocknumber || !replacement || !blocksize) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 599c492d4c..e653e3e36b 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -18,6 +18,7 @@ var/list/mob_type_ignore_stat_typecache var/stat_allowed = CONSCIOUS var/static/list/emote_list = list() + var/static/regex/stop_bad_mime = regex(@"says|exclaims|yells|asks") /datum/emote/New() if(key_third_person) diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 420602cc7f..7d040a4982 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -43,7 +43,7 @@ for(var/line in testmerge) var/datum/tgs_revision_information/test_merge/tm = line var/cm = tm.pull_request_commit - var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 11))) + var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext_char(cm, 1, 11)) if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder)) continue . += "#[tm.number][details]
" @@ -57,11 +57,11 @@ // Round ID if(GLOB.round_id) msg += "Round ID: [GLOB.round_id]" - + msg += "BYOND Version: [world.byond_version].[world.byond_build]" if(DM_VERSION != world.byond_version || DM_BUILD != world.byond_build) msg += "Compiled with BYOND Version: [DM_VERSION].[DM_BUILD]" - + // Revision information var/datum/getrev/revdata = GLOB.revdata msg += "Server revision compiled on: [revdata.date]" diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 5a4600432d..72fe6f5a1c 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -257,8 +257,8 @@ var/splitpoint = findtext(prepared_line," ") if(!splitpoint) continue - var/command = copytext(prepared_line,1,splitpoint) - var/value = copytext(prepared_line,splitpoint+1) + var/command = copytext(prepared_line, 1, splitpoint) + var/value = copytext(prepared_line, splitpoint + length(prepared_line[splitpoint])) switch(command) if("DELAY") var/delay_value = text2num(value) diff --git a/code/datums/martial.dm b/code/datums/martial.dm index c8caa853c3..cf2adfce8c 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -31,7 +31,7 @@ reset_streak(D) streak = streak+element if(length(streak) > max_streak_length) - streak = copytext(streak,2) + streak = copytext(streak, 1 + length(streak[1])) return /datum/martial_art/proc/reset_streak(mob/living/carbon/human/new_target) diff --git a/code/datums/martial/rising_bass.dm b/code/datums/martial/rising_bass.dm index 9e00c90a92..779428669c 100644 --- a/code/datums/martial/rising_bass.dm +++ b/code/datums/martial/rising_bass.dm @@ -1,8 +1,6 @@ #define SIDE_KICK_COMBO "DH" #define SHOULDER_FLIP_COMBO "GHDGHH" -#define REPULSE_PUNCH_COMBO "GHGH" #define FOOT_SMASH_COMBO "HH" -#define DEFT_SWITCH_COMBO "GDD" /datum/martial_art/the_rising_bass name = "The Rising Bass" @@ -10,6 +8,9 @@ dodge_chance = 100 allow_temp_override = FALSE help_verb = /mob/living/carbon/human/proc/rising_bass_help + var/datum/action/risingbassmove/repulsepunch = new/datum/action/risingbassmove/repulsepunch() + var/datum/action/risingbassmove/deftswitch = new/datum/action/risingbassmove/deftswitch() + var/repulsecool = 0 /datum/martial_art/the_rising_bass/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) if(findtext(streak,SIDE_KICK_COMBO)) @@ -20,7 +21,7 @@ streak = "" shoulderFlip(A,D) return 1 - if(findtext(streak,REPULSE_PUNCH_COMBO)) + if(findtext(streak,"rplse")) streak = "" repulsePunch(A,D) return 1 @@ -28,13 +29,46 @@ streak = "" footSmash(A,D) return 1 - if(findtext(streak,DEFT_SWITCH_COMBO)) + if(findtext(streak,"deft")) streak = "" deftSwitch(A,D) return 1 return 0 +//Repulse Punch - Slams the opponent far away from you. +/datum/action/risingbassmove + name = "" + icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon_state = "" + var/movestreak = "" + +/datum/action/risingbassmove/Trigger() + if(owner.incapacitated()) + to_chat(owner, "You can't use [name] while you're incapacitated.") + return + var/mob/living/carbon/human/H = owner + if (H.mind.martial_art.streak == "[movestreak]") + H.mind.martial_art.streak = "" + to_chat(H,"You relax your muscles and return to a neutral position.") + else + if(HAS_TRAIT(H, TRAIT_PACIFISM)) + to_chat(H, "You don't want to harm other people!") + return + to_chat(H,"You get ready to use the [name] maneuver!") + H.mind.martial_art.streak = "[movestreak]" + +/datum/action/risingbassmove/repulsepunch + name = "Repulse Punch" + button_icon_state = "repulsepunch" + movestreak = "rplse" + +/datum/action/risingbassmove/deftswitch + name = "Deft Switch" + button_icon_state = "deftswitch" + movestreak = "deft" + + /datum/martial_art/the_rising_bass/proc/sideKick(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!D.IsKnockdown() || D.lying == 0) var/turf/H = get_step(D, A.dir & (NORTH | SOUTH) ? pick(EAST, WEST) : pick(NORTH, SOUTH)) @@ -75,7 +109,7 @@ return basic_hit(A,D) /datum/martial_art/the_rising_bass/proc/repulsePunch(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.IsKnockdown() || !D.lying) + if(!D.IsKnockdown() || !D.lying || repulsecool > world.time) A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) D.visible_message("[A] smashes [D] in the chest, throwing them away!", \ "[A] smashes you in the chest, repelling you away!") @@ -85,6 +119,7 @@ D.apply_damage(10, BRUTE, BODY_ZONE_CHEST) D.Knockdown(90) log_combat(A, D, "repulse punched (Rising Bass)") + repulsecool = world.time + 3 SECONDS return 1 return basic_hit(A,D) @@ -132,6 +167,11 @@ return 1 return ..() +/datum/martial_art/the_rising_bass/add_to_streak(element,mob/living/carbon/human/D) + if (streak == "deft" || streak == "rplse") + return + . = ..() + /mob/living/carbon/human/proc/rising_bass_help() set name = "Recall Teachings" set desc = "Remember the martial techniques of the Rising Bass clan." @@ -149,10 +189,14 @@ . = ..() if(!.) return + deftswitch.Grant(H) + repulsepunch.Grant(H) ADD_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT) ADD_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT) /datum/martial_art/the_rising_bass/on_remove(mob/living/carbon/human/H) . = ..() + deftswitch.Remove(H) + repulsepunch.Remove(H) REMOVE_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT) REMOVE_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT) \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index f4e675d98b..a3c5979b6e 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -139,7 +139,7 @@ SEND_SIGNAL(new_character, COMSIG_MOB_ON_NEW_MIND) /datum/mind/proc/store_memory(new_text) - if((length(memory) + length(new_text)) <= MAX_MESSAGE_LEN) + if((length_char(memory) + length_char(new_text)) <= MAX_MESSAGE_LEN) memory += "[new_text]
" /datum/mind/proc/wipe_memory() @@ -409,7 +409,7 @@ assigned_role = new_role else if (href_list["memory_edit"]) - var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN) + var/new_memo = stripped_multiline_input(usr, "Write new memory", "Memory", memory, MAX_MESSAGE_LEN) if (isnull(new_memo)) return memory = new_memo diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm index f689ff903e..6397bbe66b 100644 --- a/code/datums/mutations.dm +++ b/code/datums/mutations.dm @@ -32,9 +32,9 @@ GLOBAL_LIST_EMPTY(mutations_list) /datum/mutation/human/proc/set_se(se_string, on = 1) if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE) return - var/before = copytext(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1) + var/before = copytext_char(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1) var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE) - var/after = copytext(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0) + var/after = copytext_char(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0) return before + injection + after /datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1) diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index bb7dc4cdb7..1adcb6fde6 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -18,14 +18,18 @@ for(var/spawner in GLOB.mob_spawners) var/list/this = list() this["name"] = spawner - this["desc"] = "" + this["short_desc"] = "" + this["flavor_text"] = "" + this["important_warning"] = "" this["refs"] = list() for(var/spawner_obj in GLOB.mob_spawners[spawner]) this["refs"] += "[REF(spawner_obj)]" if(!this["desc"]) if(istype(spawner_obj, /obj/effect/mob_spawn)) var/obj/effect/mob_spawn/MS = spawner_obj - this["desc"] = MS.flavour_text + this["short_desc"] = MS.short_desc + this["flavor_text"] = MS.flavour_text + this["important_info"] = MS.important_info else var/obj/O = spawner_obj this["desc"] = O.desc diff --git a/code/datums/verbs.dm b/code/datums/verbs.dm index 442997288a..39afde14d0 100644 --- a/code/datums/verbs.dm +++ b/code/datums/verbs.dm @@ -88,8 +88,8 @@ var/list/entry = list() entry["parent"] = "[type]" entry["name"] = verbpath.desc - if (copytext(verbpath.name,1,2) == "@") - entry["command"] = copytext(verbpath.name,2) + if (verbpath.name[1] == "@") + entry["command"] = copytext(verbpath.name, length(verbpath.name[1]) + 1) else entry["command"] = replacetext(verbpath.name, " ", "-") diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index fab5a1313c..d4a5dcdeb3 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -118,7 +118,7 @@ return TRUE /datum/wires/proc/is_dud(wire) - return dd_hasprefix(wire, WIRE_DUD_PREFIX) + return findtext(wire, WIRE_DUD_PREFIX) /datum/wires/proc/is_dud_color(color) return is_dud(get_wire(color)) @@ -215,8 +215,8 @@ /datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if (!ui) - ui = new(user, src, ui_key, "wires", "[holder.name] wires", 350, 150 + wires.len * 30, master_ui, state) + if(!ui) + ui = new(user, src, ui_key, "wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state) ui.open() /datum/wires/ui_data(mob/user) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1f62be8a24..960e1cc513 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -505,9 +505,8 @@ return final_rgb /atom/proc/clean_blood() - if(islist(blood_DNA)) - blood_DNA = null - return TRUE + . = blood_DNA? TRUE : FALSE + blood_DNA = null /atom/proc/wash_cream() return TRUE @@ -728,6 +727,13 @@ /atom/proc/multitool_act(mob/living/user, obj/item/I) return +/atom/proc/multitool_check_buffer(user, obj/item/I, silent = FALSE) + if(!istype(I, /obj/item/multitool)) + if(user && !silent) + to_chat(user, "[I] has no data buffer!") + return FALSE + return TRUE + /atom/proc/screwdriver_act(mob/living/user, obj/item/I) SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I) diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index e443d6ad37..21b7bd19db 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -57,10 +57,8 @@ /obj/item/melee/transforming/energy/sword/bananium name = "bananium sword" desc = "An elegant weapon, for a more civilized age." - force = 0 - throwforce = 0 - force_on = 0 - throwforce_on = 0 + force_on = 15 + throwforce_on = 15 hitsound = null attack_verb_on = list("slipped") clumsy_check = FALSE @@ -69,24 +67,26 @@ heat = 0 light_color = "#ffff00" var/next_trombone_allowed = 0 + var/datum/component/slippery/slipper /obj/item/melee/transforming/energy/sword/bananium/Initialize() . = ..() - AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) + slipper = LoadComponent(/datum/component/slippery, 81, GALOSHES_DONT_HELP) slipper.signal_enabled = active /obj/item/melee/transforming/energy/sword/bananium/attack(mob/living/M, mob/living/user) ..() if(active) - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) - slipper.Slip(M) + slipper.lube_flags |= FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING + slipper.Slip(src, M) + slipper.lube_flags &= ~(FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING) /obj/item/melee/transforming/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum) . = ..() if(active) - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) - slipper.Slip(hit_atom) + slipper.lube_flags |= FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING + slipper.Slip(src, hit_atom) + slipper.lube_flags &= ~(FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING) /obj/item/melee/transforming/energy/sword/bananium/attackby(obj/item/I, mob/living/user, params) if((world.time > next_trombone_allowed) && istype(I, /obj/item/melee/transforming/energy/sword/bananium)) @@ -98,7 +98,6 @@ /obj/item/melee/transforming/energy/sword/bananium/transform_weapon(mob/living/user, supress_message_text) ..() - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.signal_enabled = active /obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user) @@ -108,8 +107,9 @@ if(!active) transform_weapon(user, TRUE) user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku, but the blade slips off of [user.p_them()] harmlessly!") - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) - slipper.Slip(user) + slipper.lube_flags |= FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING + slipper.Slip(src, user) + slipper.lube_flags &= ~(FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING) return SHAME //BANANIUM SHIELD @@ -126,16 +126,15 @@ on_force = 0 on_throwforce = 0 on_throw_speed = 1 + var/datum/component/slippery/slipper /obj/item/shield/energy/bananium/Initialize() . = ..() - AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) + slipper = LoadComponent(/datum/component/slippery, 81, GALOSHES_DONT_HELP) slipper.signal_enabled = active /obj/item/shield/energy/bananium/attack_self(mob/living/carbon/human/user) ..() - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.signal_enabled = active /obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) @@ -149,8 +148,9 @@ if(active) var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it - var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) - slipper.Slip(hit_atom) + slipper.lube_flags |= FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING + slipper.Slip(src, hit_atom) + slipper.lube_flags &= ~(FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING) if(thrownby && !caught) throw_at(thrownby, throw_range+2, throw_speed, null, 1) else @@ -212,7 +212,7 @@ M.equip_to_slot_or_del(the_stash, SLOT_WEAR_MASK, TRUE, TRUE, TRUE, TRUE) /obj/item/clothing/mask/fakemoustache/sticky - var/unstick_time = 600 + var/unstick_time = 2 MINUTES /obj/item/clothing/mask/fakemoustache/sticky/Initialize() . = ..() diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 005b2c52d6..7132f046e6 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -113,6 +113,11 @@ Class Procs: var/atom/movable/occupant = null var/speed_process = FALSE // Process as fast as possible? var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created + // For storing and overriding ui id and dimensions + var/tgui_id // ID of TGUI interface + var/ui_style // ID of custom TGUI style (optional) + var/ui_x + var/ui_y var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm index 0b9ed6bb3f..41867a8520 100644 --- a/code/game/machinery/bank_machine.dm +++ b/code/game/machinery/bank_machine.dm @@ -46,34 +46,37 @@ new /obj/item/stack/spacecash/c200(drop_location()) // will autostack playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1) SSshuttle.points -= 200 - if(next_warning < world.time && prob(15)) - var/area/A = get_area(loc) - var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!" - radio.talk_into(src, message, radio_channel) - next_warning = world.time + minimum_time_between_warnings + if(next_warning < world.time && prob(15)) + var/area/A = get_area(loc) + var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!" + radio.talk_into(src, message, radio_channel) + next_warning = world.time + minimum_time_between_warnings -/obj/machinery/computer/bank_machine/ui_interact(mob/user) - . = ..() - var/dat = "[station_name()] secure vault. Authorized personnel only.
" - dat += "Current Balance: [SSshuttle.points] credits.
" - if(!siphoning) - dat += "Siphon Credits
" - else - dat += "Halt Credit Siphon
" +/obj/machinery/computer/bank_machine/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, "bank_machine", name, 320, 165, master_ui, state) + ui.open() - dat += "Close" +/obj/machinery/computer/bank_machine/ui_data(mob/user) + var/list/data = list() + data["current_balance"] = SSshuttle.points + data["siphoning"] = siphoning + data["station_name"] = station_name() - var/datum/browser/popup = new(user, "computer", "Bank Vault", 300, 200) - popup.set_content("
[dat]
") - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() + return data -/obj/machinery/computer/bank_machine/Topic(href, href_list) +/obj/machinery/computer/bank_machine/ui_act(action, params) if(..()) return - if(href_list["siphon"]) - say("Siphon of station credits has begun!") - siphoning = TRUE - if(href_list["halt"]) - say("Station credit withdrawal halted.") - siphoning = FALSE + + switch(action) + if("siphon") + say("Siphon of station credits has begun!") + siphoning = TRUE + . = TRUE + if("halt") + say("Station credit withdrawal halted.") + siphoning = FALSE + . = TRUE diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 3c021d0bd1..7439fd1b8b 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -11,7 +11,6 @@ var/obj/structure/table/optable/table var/list/advanced_surgeries = list() var/datum/techweb/linked_techweb - var/menu = MENU_OPERATION light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/operating/Initialize() @@ -54,8 +53,6 @@ var/list/data = list() data["table"] = table if(table) - data["menu"] = menu - var/list/surgeries = list() for(var/X in advanced_surgeries) var/datum/surgery/S = X @@ -64,9 +61,8 @@ surgery["desc"] = initial(S.desc) surgeries += list(surgery) data["surgeries"] = surgeries - - data["patient"] = list() if(table.check_patient()) + data["patient"] = list() patient = table.patient switch(patient.stat) if(CONSCIOUS) @@ -110,15 +106,14 @@ "alternative_step" = alternative_step, "alt_chems_needed" = alt_chems_needed )) + else + data["patient"] = null return data /obj/machinery/computer/operating/ui_act(action, params) if(..()) return switch(action) - if("change_menu") - menu = text2num(params["menu"]) - . = TRUE if("sync") sync_surgeries() . = TRUE diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index 8ddbd68c7b..6d22f9d6c8 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -198,7 +198,7 @@ /obj/machinery/computer/apc_control/proc/log_activity(log_text) var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]" - LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss")]) [op_string] [log_text]") + LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]) [op_string] [log_text]") /mob/proc/using_power_flow_console() for(var/obj/machinery/computer/apc_control/A in range(1, src)) diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index f9d2a3c103..d6ce850da8 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -91,6 +91,8 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) icon_screen = "tank" icon_keyboard = "atmos_key" circuit = /obj/item/circuitboard/computer/atmos_control + ui_x = 400 + ui_y = 925 var/frequency = FREQ_ATMOS_STORAGE var/list/sensors = list( @@ -125,7 +127,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) 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, "atmos_control", name, 400, 925, master_ui, state) + ui = new(user, src, ui_key, "atmos_control", name, ui_x, ui_y, master_ui, state) ui.open() /obj/machinery/computer/atmos_control/ui_data(mob/user) @@ -161,6 +163,20 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) frequency = new_frequency radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) +//Incinerator sensor only +/obj/machinery/computer/atmos_control/incinerator + name = "Incinerator Air Control" + sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber") + ui_x = 400 + ui_y = 300 + +//Toxins mix sensor only +/obj/machinery/computer/atmos_control/toxinsmix + name = "Toxins Mixing Air Control" + sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber") + ui_x = 400 + ui_y = 300 + ///////////////////////////////////////////////////////////// // LARGE TANK CONTROL ///////////////////////////////////////////////////////////// @@ -174,6 +190,9 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) var/list/input_info var/list/output_info + ui_x = 500 + ui_y = 315 + /obj/machinery/computer/atmos_control/tank/oxygen_tank name = "Oxygen Supply Control" input_tag = ATMOS_GAS_MONITOR_INPUT_O2 @@ -216,12 +235,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2 sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank") -/obj/machinery/computer/atmos_control/tank/incinerator - name = "Incinerator Air Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_INCINERATOR - output_tag = ATMOS_GAS_MONITOR_OUTPUT_INCINERATOR - sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber") - // This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this /obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user) var/list/IO = list() @@ -235,7 +248,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) IO |= text[1] if(!IO.len) to_chat(user, "No machinery detected.") - var/S = input("Select the device set: ", "Selection", IO[1]) as anything in IO + var/S = input("Select the device set: ", "Selection", IO[1]) as anything in sortList(IO) if(src) src.input_tag = "[S]_in" src.output_tag = "[S]_out" @@ -256,7 +269,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) 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, "atmos_control", name, 500, 305, master_ui, state) + ui = new(user, src, ui_key, "atmos_control", name, ui_x, ui_y, master_ui, state) ui.open() /obj/machinery/computer/atmos_control/tank/ui_data(mob/user) @@ -280,13 +293,19 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) if("input") signal.data += list("tag" = input_tag, "power_toggle" = TRUE) . = TRUE + if("rate") + var/target = text2num(params["rate"]) + if(!isnull(target)) + target = CLAMP(target, 0, MAX_TRANSFER_RATE) + signal.data += list("tag" = input_tag, "set_volume_rate" = target) + . = TRUE if("output") signal.data += list("tag" = output_tag, "power_toggle" = TRUE) . = TRUE if("pressure") - var/target = input("New target pressure:", name, output_info ? output_info["internal"] : 0) as num|null - if(!isnull(target) && !..()) - target = CLAMP(target, 0, 50 * ONE_ATMOSPHERE) + var/target = text2num(params["pressure"]) + if(!isnull(target)) + target = CLAMP(target, 0, MAX_OUTPUT_PRESSURE) signal.data += list("tag" = output_tag, "set_internal_pressure" = target) . = TRUE radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 90969bf4a1..4d21ae77b0 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -482,7 +482,7 @@ R.fields["ckey"] = mob_occupant.ckey R.fields["name"] = mob_occupant.real_name - R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6) + R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6) R.fields["UE"] = dna.unique_enzymes R.fields["UI"] = dna.uni_identity R.fields["SE"] = dna.struc_enzymes diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 629ee9c9ae..9d0053c9b2 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -443,7 +443,7 @@ var/dat = "" if(SSshuttle.emergency.mode == SHUTTLE_CALL) var/timeleft = SSshuttle.emergency.timeLeft() - dat += "Emergency shuttle\n
\nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" + dat += "Emergency shuttle\n
\nETA: [timeleft / 60 % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]" var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index f050246f26..5049a10d2b 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -274,13 +274,18 @@ var/max_line_len = 7*DNA_BLOCK_SIZE if(viable_occupant) temp_html += "
1
" - var/len = length(viable_occupant.dna.uni_identity) - for(var/i=1, i<=len, i++) - temp_html += "[copytext(viable_occupant.dna.uni_identity,i,i+1)]" - if ((i % max_line_len) == 0) + var/char = "" + var/ui_text = viable_occupant.dna.uni_identity + var/len_byte = length(ui_text) + var/char_it = 0 + for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char)) + char_it++ + char = ui_text[byte_it] + temp_html += "[char]" + if((char_it % max_line_len) == 0) temp_html += "
" - if((i % DNA_BLOCK_SIZE) == 0 && i < len) - temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" + if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte) + temp_html += "
[(char_it / DNA_BLOCK_SIZE) + 1]
" else temp_html += "----" temp_html += "

" @@ -288,13 +293,18 @@ temp_html += "
Structural Enzymes:
" if(viable_occupant) temp_html += "
1
" - var/len = length(viable_occupant.dna.struc_enzymes) - for(var/i=1, i<=len, i++) - temp_html += "[copytext(viable_occupant.dna.struc_enzymes,i,i+1)]" - if ((i % max_line_len) == 0) + var/char = "" + var/se_text = viable_occupant.dna.struc_enzymes + var/len_byte = length(se_text) + var/char_it = 0 + for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char)) + char_it++ + char = se_text[byte_it] + temp_html += "[char]" + if((char_it % max_line_len) == 0) temp_html += "
" - if((i % DNA_BLOCK_SIZE) == 0 && i < len) - temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" + if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte) + temp_html += "
[(char_it / DNA_BLOCK_SIZE) + 1]
" else temp_html += "----" temp_html += "
" @@ -465,7 +475,7 @@ viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage if("pulseui") - var/len = length(viable_occupant.dna.uni_identity) + var/len = length_char(viable_occupant.dna.uni_identity) num = WRAP(num, 1, len+1) num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2 //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low @@ -473,12 +483,12 @@ var/subblock = num - block*DNA_BLOCK_SIZE last_change = "UI #[block]-[subblock]; " - var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1) + var/hex = copytext_char(viable_occupant.dna.uni_identity, num, num+1) last_change += "[hex]" hex = scramble(hex, radstrength, radduration) last_change += "->[hex]" - viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0) + viable_occupant.dna.uni_identity = copytext_char(viable_occupant.dna.uni_identity, 1, num) + hex + copytext_char(viable_occupant.dna.uni_identity, num + 1) viable_occupant.updateappearance(mutations_overlay_update=1) if("pulsese") var/len = length(viable_occupant.dna.struc_enzymes) @@ -489,12 +499,12 @@ var/subblock = num - block*DNA_BLOCK_SIZE last_change = "SE #[block]-[subblock]; " - var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1) + var/hex = copytext_char(viable_occupant.dna.struc_enzymes, num, num+1) last_change += "[hex]" hex = scramble(hex, radstrength, radduration) last_change += "->[hex]" - viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0) + viable_occupant.dna.struc_enzymes = copytext_char(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext_char(viable_occupant.dna.struc_enzymes, num + 1) viable_occupant.domutcheck() else current_screen = "mainmenu" diff --git a/code/game/machinery/computer/launchpad_control.dm b/code/game/machinery/computer/launchpad_control.dm index b5d393bce0..1924cd9f23 100644 --- a/code/game/machinery/computer/launchpad_control.dm +++ b/code/game/machinery/computer/launchpad_control.dm @@ -1,11 +1,13 @@ /obj/machinery/computer/launchpad - name = "\improper launchpad control console" + name = "launchpad control console" desc = "Used to teleport objects to and from a launchpad." icon_screen = "teleport" icon_keyboard = "teleport_key" circuit = /obj/item/circuitboard/computer/launchpad_console - var/sending = TRUE - var/current_pad //current pad viewed on the screen + ui_x = 475 + ui_y = 260 + + var/selected_id var/list/obj/machinery/launchpad/launchpads var/maximum_pads = 4 @@ -18,7 +20,9 @@ return /obj/machinery/computer/launchpad/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/multitool)) + if(W.tool_behaviour == TOOL_MULTITOOL) + if(!multitool_check_buffer(user, W)) + return var/obj/item/multitool/M = W if(M.buffer && istype(M.buffer, /obj/machinery/launchpad)) if(LAZYLEN(launchpads) < maximum_pads) @@ -36,55 +40,7 @@ return FALSE return TRUE -/obj/machinery/computer/launchpad/proc/get_pad(number) - var/obj/machinery/launchpad/pad = launchpads[number] - return pad - -/obj/machinery/computer/launchpad/ui_interact(mob/user) - . = ..() - var/list/t = list() - if(!LAZYLEN(launchpads)) - obj_flags &= ~IN_USE //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console - t += "
No launchpad located.

" - else - for(var/i in 1 to LAZYLEN(launchpads)) - if(pad_exists(i)) - var/obj/machinery/launchpad/pad = get_pad(i) - if(pad.stat & NOPOWER) - t+= "[pad.display_name]" - else - t+= "[pad.display_name]" - else - launchpads -= get_pad(i) - t += "
" - - if(current_pad) - var/obj/machinery/launchpad/pad = get_pad(current_pad) - t += "
[pad.display_name]
" - t += "Rename" - t += "Remove

" - t += "O" //up-left - t += "^" //up - t += "O
" //up-right - t += "<"//left - t += "R"//reset to 0 - t += ">
"//right - t += "O"//down-left - t += "v"//down - t += "O
"//down-right - t += "
" - t += "
Current offset:

" - t += "
[abs(pad.y_offset)] [pad.y_offset > 0 ? "N":"S"] \[SET\]

" - t += "
[abs(pad.x_offset)] [pad.x_offset > 0 ? "E":"W"] \[SET\]

" - - t += "
Launch" - t += " Pull" - - var/datum/browser/popup = new(user, "launchpad", name, 300, 500) - popup.set_content(t.Join()) - popup.open() - -/obj/machinery/computer/launchpad/proc/teleport(mob/user, obj/machinery/launchpad/pad) +/obj/machinery/computer/launchpad/proc/teleport(mob/user, obj/machinery/launchpad/pad, sending) if(QDELETED(pad)) to_chat(user, "ERROR: Launchpad not responding. Check launchpad integrity.") return @@ -93,66 +49,83 @@ return pad.doteleport(user, sending) -/obj/machinery/computer/launchpad/Topic(href, href_list) - var/obj/machinery/launchpad/pad - if(href_list["pad"]) - pad = get_pad(text2num(href_list["pad"])) +/obj/machinery/computer/launchpad/proc/get_pad(number) + var/obj/machinery/launchpad/pad = launchpads[number] + return pad +/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, 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, "launchpad_console", name, ui_x, ui_y, master_ui, state) + ui.open() + +/obj/machinery/computer/launchpad/ui_data(mob/user) + var/list/data = list() + var/list/pad_list = list() + for(var/i in 1 to LAZYLEN(launchpads)) + if(pad_exists(i)) + var/obj/machinery/launchpad/pad = get_pad(i) + var/list/this_pad = list() + this_pad["name"] = pad.display_name + this_pad["id"] = i + if(pad.stat & NOPOWER) + this_pad["inactive"] = TRUE + pad_list += list(this_pad) + else + launchpads -= get_pad(i) + data["launchpads"] = pad_list + data["selected_id"] = selected_id + if(selected_id) + var/obj/machinery/launchpad/current_pad = launchpads[selected_id] + data["x"] = current_pad.x_offset + data["y"] = current_pad.y_offset + data["pad_name"] = current_pad.display_name + data["range"] = current_pad.range + data["selected_pad"] = current_pad + if(QDELETED(current_pad) || (current_pad.stat & NOPOWER)) + data["pad_active"] = FALSE + return data + data["pad_active"] = TRUE + + return data + +/obj/machinery/computer/launchpad/ui_act(action, params) if(..()) return - if(!LAZYLEN(launchpads)) - updateDialog() - return + var/obj/machinery/launchpad/current_pad = launchpads[selected_id] + switch(action) + if("select_pad") + selected_id = text2num(params["id"]) + . = TRUE + if("set_pos") + var/new_x = text2num(params["x"]) + var/new_y = text2num(params["y"]) + current_pad.set_offset(new_x, new_y) + . = TRUE + if("move_pos") + var/plus_x = text2num(params["x"]) + var/plus_y = text2num(params["y"]) + current_pad.set_offset( + x = current_pad.x_offset + plus_x, + y = current_pad.y_offset + plus_y + ) + . = TRUE + if("rename") + . = TRUE + var/new_name = params["name"] + if(!new_name) + return + current_pad.display_name = new_name + if("remove") + if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort") + launchpads -= current_pad + selected_id = null + . = TRUE + if("launch") + teleport(usr, current_pad, TRUE) + . = TRUE - if(href_list["choose_pad"]) - current_pad = text2num(href_list["pad"]) - - if(href_list["raisex"]) - if(pad.x_offset < pad.range) - pad.x_offset++ - - if(href_list["lowerx"]) - if(pad.x_offset > (pad.range * -1)) - pad.x_offset-- - - if(href_list["raisey"]) - if(pad.y_offset < pad.range) - pad.y_offset++ - - if(href_list["lowery"]) - if(pad.y_offset > (pad.range * -1)) - pad.y_offset-- - - if(href_list["reset"]) - pad.y_offset = 0 - pad.x_offset = 0 - - if(href_list["change_name"]) - var/new_name = stripped_input(usr, "What do you wish to name the launchpad?", "Launchpad", pad.display_name, 15) - if(!new_name) - return - pad.display_name = new_name - - if(href_list["setx"]) - var/newx = input(usr, "Input new x offset", pad.display_name, pad.x_offset) as null|num - if(!isnull(newx)) - pad.x_offset = CLAMP(newx, -pad.range, pad.range) - - if(href_list["sety"]) - var/newy = input(usr, "Input new y offset", pad.display_name, pad.y_offset) as null|num - if(!isnull(newy)) - pad.y_offset = CLAMP(newy, -pad.range, pad.range) - - if(href_list["remove"]) - if(usr && alert(usr, "Are you sure?", "Remove Launchpad", "I'm Sure", "Abort") != "Abort") - launchpads -= pad - - if(href_list["launch"]) - sending = TRUE - teleport(usr, pad) - - if(href_list["pull"]) - sending = FALSE - teleport(usr, pad) - - updateDialog() + if("pull") + teleport(usr, current_pad, FALSE) + . = TRUE + . = TRUE \ No newline at end of file diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 25d375c14a..f8dac1b100 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -478,7 +478,7 @@ var/counter = 1 while(active2.fields[text("com_[]", counter)]) counter++ - active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) + active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) else if(href_list["del_c"]) if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) diff --git a/code/game/machinery/computer/prisoner/gulag_teleporter.dm b/code/game/machinery/computer/prisoner/gulag_teleporter.dm index f6e164efe9..e4a6a0b2d4 100644 --- a/code/game/machinery/computer/prisoner/gulag_teleporter.dm +++ b/code/game/machinery/computer/prisoner/gulag_teleporter.dm @@ -6,6 +6,9 @@ icon_keyboard = "security_key" req_access = list(ACCESS_ARMORY) circuit = /obj/item/circuitboard/computer/gulag_teleporter_console + ui_x = 350 + ui_y = 295 + var/default_goal = 200 var/obj/machinery/gulag_teleporter/teleporter = null var/obj/structure/gulag_beacon/beacon = null @@ -22,7 +25,7 @@ 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, "gulag_console", name, 455, 440, master_ui, state) + ui = new(user, src, ui_key, "gulag_console", name, ui_x, ui_y, master_ui, state) ui.open() /obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user) @@ -50,13 +53,19 @@ data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.z])" data["teleporter_lock"] = teleporter.locked data["teleporter_state_open"] = teleporter.state_open + else + data["teleporter"] = null if(beacon) data["beacon"] = beacon data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.z])" + else + data["beacon"] = null if(contained_id) data["id"] = contained_id data["id_name"] = contained_id.registered_name data["goal"] = contained_id.goal + else + data["id"] = null data["can_teleport"] = can_teleport return data @@ -72,36 +81,41 @@ switch(action) if("scan_teleporter") teleporter = findteleporter() + return TRUE if("scan_beacon") beacon = findbeacon() + return TRUE if("handle_id") if(contained_id) id_eject(usr) else id_insert(usr) + return TRUE if("set_goal") - var/new_goal = input("Set the amount of points:", "Points", contained_id.goal) as num|null + var/new_goal = text2num(params["value"]) if(!isnum(new_goal)) return if(!new_goal) new_goal = default_goal - if (new_goal > 1000) - to_chat(usr, "The entered amount of points is too large. Points have instead been set to the maximum allowed amount.") contained_id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points + return TRUE if("toggle_open") if(teleporter.locked) - to_chat(usr, "The teleporter is locked") + to_chat(usr, "The teleporter must be unlocked first.") return teleporter.toggle_open() + return TRUE if("teleporter_lock") if(teleporter.state_open) - to_chat(usr, "Close the teleporter before locking!") + to_chat(usr, "The teleporter must be closed first.") return teleporter.locked = !teleporter.locked + return TRUE if("teleport") if(!teleporter || !beacon) return addtimer(CALLBACK(src, .proc/teleport, usr), 5) + return TRUE /obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/scan_machinery() teleporter = findteleporter() @@ -129,12 +143,12 @@ say("[contained_id]'s ID card goal defaulting to [contained_id.goal] points.") log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][contained_id.goal] points.") teleporter.handle_prisoner(contained_id, temporary_record) - playsound(src, 'sound/weapons/emitter.ogg', 50, 1) + playsound(src, 'sound/weapons/emitter.ogg', 50, TRUE) prisoner.forceMove(get_turf(beacon)) prisoner.Stun(40) // small travel dizziness to_chat(prisoner, "The teleportation makes you a little dizzy.") new /obj/effect/particle_effect/sparks(get_turf(prisoner)) - playsound(src, "sparks", 50, 1) + playsound(src, "sparks", 50, TRUE) if(teleporter.locked) teleporter.locked = FALSE teleporter.toggle_open() diff --git a/code/game/machinery/computer/prisoner/management.dm b/code/game/machinery/computer/prisoner/management.dm index 04f0b9b79a..4b4b39740a 100644 --- a/code/game/machinery/computer/prisoner/management.dm +++ b/code/game/machinery/computer/prisoner/management.dm @@ -125,7 +125,7 @@ to_chat(usr, "Unauthorized access.") else if(href_list["warn"]) - var/warning = copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN) + var/warning = stripped_input(usr, "Message:", "Enter your message here!", "", MAX_MESSAGE_LEN) if(!warning) return var/obj/item/implant/I = locate(href_list["warn"]) in GLOB.tracked_implants diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index f0c8fbe3c7..25f4237439 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -456,7 +456,7 @@ What a mess.*/ var/counter = 1 while(active2.fields[text("com_[]", counter)]) counter++ - active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) + active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) if("Delete Record (ALL)") if(active1) @@ -544,7 +544,7 @@ What a mess.*/ switch(href_list["field"]) if("name") if(istype(active1, /datum/data/record) || istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input name:", "Secure. records", active1.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = stripped_input(usr, "Please input name:", "Secure. records", active1.fields["name"], MAX_MESSAGE_LEN) if(!canUseSecurityRecordsConsole(usr, t1, a1)) return if(istype(active1, /datum/data/record)) @@ -636,7 +636,7 @@ What a mess.*/ var/t2 = stripped_input(usr, "Please input minor crime details:", "Secure. records", "", null) if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss")) + var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)) GLOB.data_core.addMinorCrime(active1.fields["id"], crime) investigate_log("New Minor Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) if("mi_crim_delete") @@ -651,7 +651,7 @@ What a mess.*/ var/t2 = stripped_input(usr, "Please input major crime details:", "Secure. records", "", null) if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss")) + var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)) GLOB.data_core.addMajorCrime(active1.fields["id"], crime) investigate_log("New Major Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) if("ma_crim_delete") diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 1b700fdf36..c3fef3ff92 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -20,17 +20,18 @@ 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, "station_alert", name, 300, 500, master_ui, state) + ui = new(user, src, ui_key, "station_alert", name, 325, 500, master_ui, state) ui.open() /obj/machinery/computer/station_alert/ui_data(mob/user) - . = list() + var/list/data = list() - .["alarms"] = list() + data["alarms"] = list() for(var/class in alarms) - .["alarms"][class] = list() + data["alarms"][class] = list() for(var/area in alarms[class]) - .["alarms"][class] += area + data["alarms"][class] += area + return data /obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source) if(source.z != z) diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index 768faa8301..72c8979006 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -136,7 +136,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E var/list/transferlog = list() /obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage) - transferlog += ("[STATION_TIME_TIMESTAMP("hh:mm:ss")] [logmessage]") + transferlog += ("[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)] [logmessage]") /obj/machinery/computer/telecrystals/boss/proc/scanUplinkers() for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc)) diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index 836d965e05..6710258626 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -5,6 +5,8 @@ icon_keyboard = "teleport_key" light_color = LIGHT_COLOR_BLUE circuit = /obj/item/circuitboard/computer/teleporter + ui_x = 475 + ui_y = 130 var/regime_set = "Teleporter" var/id var/obj/machinery/teleport/station/power_station @@ -32,34 +34,30 @@ break return power_station -/obj/machinery/computer/teleporter/ui_interact(mob/user) - . = ..() - var/data = "

Teleporter Status

" - if(!power_station) - data += "
No power station linked.
" - else if(!power_station.teleporter_hub) - data += "
No hub linked.
" +obj/machinery/computer/teleporter/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, "teleporter", name, ui_x, ui_y, master_ui, state) + ui.open() + +/obj/machinery/computer/teleporter/ui_data(mob/user) + var/list/data = list() + data["power_station"] = power_station ? TRUE : FALSE + data["teleporter_hub"] = power_station?.teleporter_hub ? TRUE : FALSE + data["regime_set"] = regime_set + data["target"] = !target ? "None" : "[get_area(target)] [(regime_set != "Gate") ? "" : "Teleporter"]" + data["calibrating"] = calibrating + + if(power_station?.teleporter_hub?.calibrated || power_station?.teleporter_hub?.accuracy >= 3) + data["calibrated"] = TRUE else - data += "
Current regime: [regime_set]
" - data += "Current target: [(!target) ? "None" : "[get_area(target)] [(regime_set != "Gate") ? "" : "Teleporter"]"]
" - if(calibrating) - data += "Calibration: In Progress" - else if(power_station.teleporter_hub.calibrated || power_station.efficiency >= 3) - data += "Calibration: Optimal" - else - data += "Calibration: Sub-Optimal" - data += "

" + data["calibrated"] = FALSE - data += "Change regime
" - data += "Set target
" + return data - data += "
Calibrate Hub" - var/datum/browser/popup = new(user, "teleporter", name, 400, 400) - popup.set_content(data) - popup.open() - -/obj/machinery/computer/teleporter/Topic(href, href_list) +/obj/machinery/computer/teleporter/ui_act(action, params) if(..()) return @@ -70,38 +68,39 @@ say("Error: Calibration in progress. Stand by.") return - if(href_list["regimeset"]) - power_station.engaged = 0 - power_station.teleporter_hub.update_icon() - power_station.teleporter_hub.calibrated = 0 - reset_regime() - if(href_list["settarget"]) - power_station.engaged = 0 - power_station.teleporter_hub.update_icon() - power_station.teleporter_hub.calibrated = 0 - set_target(usr) - if(href_list["calibrate"]) - if(!target) - say("Error: No target set to calibrate to.") - return - if(power_station.teleporter_hub.calibrated || power_station.efficiency >= 3) - say("Hub is already calibrated!") - return - say("Processing hub calibration to target...") + switch(action) + if("regimeset") + power_station.engaged = FALSE + power_station.teleporter_hub.update_icon() + power_station.teleporter_hub.calibrated = FALSE + reset_regime() + . = TRUE + if("settarget") + power_station.engaged = FALSE + power_station.teleporter_hub.update_icon() + power_station.teleporter_hub.calibrated = FALSE + set_target(usr) + . = TRUE + if("calibrate") + if(!target) + say("Error: No target set to calibrate to.") + return + if(power_station.teleporter_hub.calibrated || power_station.teleporter_hub.accuracy >= 3) + say("Hub is already calibrated!") + return - calibrating = 1 - power_station.update_icon() - spawn(50 * (3 - power_station.efficiency)) //Better parts mean faster calibration - calibrating = 0 - if(check_hub_connection()) - power_station.teleporter_hub.calibrated = 1 - say("Calibration complete.") - else - say("Error: Unable to detect hub.") + say("Processing hub calibration to target...") + calibrating = TRUE power_station.update_icon() - updateDialog() - - updateDialog() + spawn(50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration + calibrating = FALSE + if(check_hub_connection()) + power_station.teleporter_hub.calibrated = TRUE + say("Calibration complete.") + else + say("Error: Unable to detect hub.") + power_station.update_icon() + . = TRUE /obj/machinery/computer/teleporter/proc/check_hub_connection() if(!power_station) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 0d7f3bea9a..863f1e7b46 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1434,7 +1434,7 @@ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "ai_airlock", name, 550, 456, master_ui, state) + ui = new(user, src, ui_key, "ai_airlock", name, 500, 390, master_ui, state) ui.open() return TRUE @@ -1503,83 +1503,24 @@ if("shock-perm") shock_perm(usr) . = TRUE - if("idscan-on") - if(wires.is_cut(WIRE_IDSCAN)) - to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.") - else if(src.aiDisabledIdScanner) - aiDisabledIdScanner = FALSE - else - to_chat(usr, "The IdScan feature is not disabled.") + if("idscan-toggle") + aiDisabledIdScanner = !aiDisabledIdScanner . = TRUE - if("idscan-off") - if(wires.is_cut(WIRE_IDSCAN)) - to_chat(usr, "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways.") - else if(aiDisabledIdScanner) - to_chat(usr, "You've already disabled the IdScan feature.") - else - aiDisabledIdScanner = TRUE + if("emergency-toggle") + toggle_emergency(usr) . = TRUE - if("emergency-on") - emergency_on(usr) + if("bolt-toggle") + toggle_bolt(usr) . = TRUE - if("emergency-off") - emergency_off(usr) + if("light-toggle") + lights = !lights + update_icon() . = TRUE - if("bolt-raise") - bolt_raise(usr) + if("safe-toggle") + safe = !safe . = TRUE - if("bolt-drop") - bolt_drop(usr) - . = TRUE - if("light-on") - if(wires.is_cut(WIRE_LIGHT)) - to_chat(usr, "Control to door bolt lights has been severed.") - else if (!src.lights) - lights = TRUE - update_icon() - else - to_chat(usr, text("Door bolt lights are already enabled!")) - . = TRUE - if("light-off") - if(wires.is_cut(WIRE_LIGHT)) - to_chat(usr, "Control to door bolt lights has been severed.") - else if (lights) - lights = FALSE - update_icon() - else - to_chat(usr, "Door bolt lights are already disabled!") - . = TRUE - if("safe-on") - if(wires.is_cut(WIRE_SAFETY)) - to_chat(usr, "Control to door sensors is disabled.") - else if (!src.safe) - safe = TRUE - else - to_chat(usr, "Firmware reports safeties already in place.") - . = TRUE - if("safe-off") - if(wires.is_cut(WIRE_SAFETY)) - to_chat(usr, "Control to door sensors is disabled.") - else if (safe) - safe = FALSE - else - to_chat(usr, "Firmware reports safeties already overridden.") - . = TRUE - if("speed-on") - if(wires.is_cut(WIRE_TIMING)) - to_chat(usr, "Control to door timing circuitry has been severed.") - else if (!src.normalspeed) - normalspeed = 1 - else - to_chat(usr,"Door timing circuitry currently operating normally.") - . = TRUE - if("speed-off") - if(wires.is_cut(WIRE_TIMING)) - to_chat(usr, "Control to door timing circuitry has been severed.") - else if (normalspeed) - normalspeed = 0 - else - to_chat(usr, "Door timing circuitry already accelerated.") + if("speed-toggle") + normalspeed = !normalspeed . = TRUE if("open-close") @@ -1617,45 +1558,26 @@ log_combat(user, src, "electrified") set_electrified(ELECTRIFIED_PERMANENT) -/obj/machinery/door/airlock/proc/emergency_on(mob/user) - if(!user_allowed(user)) - return - if (!emergency) - emergency = TRUE - update_icon() - else - to_chat(user, "Emergency access is already enabled!") - -/obj/machinery/door/airlock/proc/emergency_off(mob/user) - if(!user_allowed(user)) - return - if (emergency) - emergency = FALSE - update_icon() - else - to_chat(user, "Emergency access is already disabled!") - -/obj/machinery/door/airlock/proc/bolt_raise(mob/user) +/obj/machinery/door/airlock/proc/toggle_bolt(mob/user) if(!user_allowed(user)) return if(wires.is_cut(WIRE_BOLTS)) - to_chat(user, "The door bolt drop wire is cut - you can't raise the door bolts") - else if(!src.locked) - to_chat(user, "The door bolts are already up") - else - if(src.hasPower()) - unbolt() + to_chat(user, "The door bolt drop wire is cut - you can't toggle the door bolts.") + return + if(locked) + if(!hasPower()) + to_chat(user, "The door has no power - you can't raise the door bolts.") else - to_chat(user, "Cannot raise door bolts due to power failure") - -/obj/machinery/door/airlock/proc/bolt_drop(mob/user) - if(!user_allowed(user)) - return - if(wires.is_cut(WIRE_BOLTS)) - to_chat(user, "You can't drop the door bolts - The door bolt dropping wire has been cut.") + unbolt() else bolt() +/obj/machinery/door/airlock/proc/toggle_emergency(mob/user) + if(!user_allowed(user)) + return + emergency = !emergency + update_icon() + /obj/machinery/door/airlock/proc/user_toggle_open(mob/user) if(!user_allowed(user)) return diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 54774a8f99..7b90715f2b 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -14,7 +14,7 @@ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "airlock_electronics", name, 975, 420, master_ui, state) + ui = new(user, src, ui_key, "airlock_electronics", name, 420, 485, master_ui, state) ui.open() /obj/item/electronics/airlock/ui_data() @@ -43,13 +43,16 @@ if(..()) return switch(action) - if("clear") + if("clear_all") accesses = list() one_access = 0 . = TRUE if("one_access") one_access = !one_access . = TRUE + if("grant_all") + accesses = get_all_accesses() + . = TRUE if("set") var/access = text2num(params["access"]) if (!(access in accesses)) diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index beaf47d0a3..3bfcececda 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -149,7 +149,7 @@ 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, "brig_timer", name, 300, 200, master_ui, state) + ui = new(user, src, ui_key, "brig_timer", name, 300, 138, master_ui, state) ui.open() //icon update function @@ -168,7 +168,7 @@ if(timing) var/disp1 = id var/time_left = time_left(seconds = TRUE) - var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]" + var/disp2 = "[add_leading(num2text((time_left / 60) % 60), 2, "0")]:[add_leading(num2text(time_left % 60), 2, "0")]" if(length(disp2) > CHARS_PER_LINE) disp2 = "Error" update_display(disp1, disp2) diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm index f51c145635..55b1e34022 100644 --- a/code/game/machinery/gulag_item_reclaimer.dm +++ b/code/game/machinery/gulag_item_reclaimer.dm @@ -31,7 +31,7 @@ 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, "gulag_item_reclaimer", name, 455, 440, master_ui, state) + ui = new(user, src, ui_key, "gulag_item_reclaimer", name, 300, 400, master_ui, state) ui.open() /obj/machinery/gulag_item_reclaimer/ui_data(mob/user) diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index b4a9584368..0f5e51215d 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -16,6 +16,7 @@ var/power_efficiency = 1 var/x_offset = 0 var/y_offset = 0 + var/indicator_icon = "launchpad_target" /obj/machinery/launchpad/RefreshParts() var/E = 0 @@ -34,17 +35,28 @@ return if(panel_open) - if(istype(I, /obj/item/multitool)) + if(I.tool_behaviour == TOOL_MULTITOOL) + if(!multitool_check_buffer(user, I)) + return var/obj/item/multitool/M = I M.buffer = src to_chat(user, "You save the data in the [I.name]'s buffer.") - return 1 + return TRUE if(default_deconstruction_crowbar(I)) return return ..() +/obj/machinery/launchpad/attack_ghost(mob/dead/observer/ghost) + . = ..() + if(.) + return + var/target_x = x + x_offset + var/target_y = y + y_offset + var/turf/target = locate(target_x, target_y, z) + ghost.forceMove(target) + /obj/machinery/launchpad/proc/isAvailable() if(stat & NOPOWER) return FALSE @@ -52,6 +64,14 @@ return FALSE return TRUE +/obj/machinery/launchpad/proc/set_offset(x, y) + if(teleporting) + return + if(!isnull(x)) + x_offset = CLAMP(x, -range, range) + if(!isnull(y)) + y_offset = CLAMP(y, -range, range) + /obj/machinery/launchpad/proc/doteleport(mob/user, sending) if(teleporting) to_chat(user, "ERROR: Launchpad busy.") @@ -69,12 +89,22 @@ var/area/A = get_area(target) flick(icon_teleport, src) - playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, 1) + + //Change the indicator's icon to show that we're teleporting + if(sending) + indicator_icon = "launchpad_launch" + else + indicator_icon = "launchpad_pull" + + playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, TRUE) teleporting = TRUE sleep(teleport_speed) + //Set the indicator icon back to normal + indicator_icon = "launchpad_target" + if(QDELETED(src) || !isAvailable()) return @@ -91,25 +121,25 @@ source = dest dest = target - playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, 1) + playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, TRUE) var/first = TRUE for(var/atom/movable/ROI in source) if(ROI == src) continue - // if it's anchored, don't teleport + if(!istype(ROI) || isdead(ROI) || iscameramob(ROI) || istype(ROI, /obj/effect/dummy/phased_mob)) + continue//don't teleport these var/on_chair = "" - if(ROI.anchored) + if(ROI.anchored)// if it's anchored, don't teleport if(isliving(ROI)) var/mob/living/L = ROI if(L.buckled) // TP people on office chairs if(L.buckled.anchored) continue - on_chair = " (on a chair)" else continue - else if(!isobserver(ROI)) + else continue if(!first) log_msg += ", " @@ -158,11 +188,11 @@ var/obj/item/storage/briefcase/launchpad/briefcase /obj/machinery/launchpad/briefcase/Initialize(mapload, briefcase) - . = ..() - if(!briefcase) - log_game("[src] has been spawned without a briefcase.") - return INITIALIZE_HINT_QDEL - src.briefcase = briefcase + . = ..() + if(!briefcase) + log_game("[src] has been spawned without a briefcase.") + return INITIALIZE_HINT_QDEL + src.briefcase = briefcase /obj/machinery/launchpad/briefcase/Destroy() QDEL_NULL(briefcase) @@ -255,7 +285,7 @@ /obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", 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, "launchpad_remote", "Briefcase Launchpad Remote", 550, 400, master_ui, state) //width, height + ui = new(user, src, ui_key, "launchpad_remote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height ui.set_style("syndicate") ui.open() @@ -270,10 +300,9 @@ return data data["pad_name"] = pad.display_name - data["abs_x"] = abs(pad.x_offset) - data["abs_y"] = abs(pad.y_offset) - data["north_south"] = pad.y_offset > 0 ? "N":"S" - data["east_west"] = pad.x_offset > 0 ? "E":"W" + data["range"] = pad.range + data["x"] = pad.x_offset + data["y"] = pad.y_offset return data /obj/item/launchpad_remote/proc/teleport(mob/user, obj/machinery/launchpad/pad) @@ -289,76 +318,33 @@ if(..()) return switch(action) - if("right") - if(pad.x_offset < pad.range) - pad.x_offset++ + if("set_pos") + var/new_x = text2num(params["x"]) + var/new_y = text2num(params["y"]) + pad.set_offset(new_x, new_y) . = TRUE - - if("left") - if(pad.x_offset > (pad.range * -1)) - pad.x_offset-- + if("move_pos") + var/plus_x = text2num(params["x"]) + var/plus_y = text2num(params["y"]) + pad.set_offset( + x = pad.x_offset + plus_x, + y = pad.y_offset + plus_y + ) . = TRUE - - if("up") - if(pad.y_offset < pad.range) - pad.y_offset++ - . = TRUE - - if("down") - if(pad.y_offset > (pad.range * -1)) - pad.y_offset-- - . = TRUE - - if("up-right") - if(pad.y_offset < pad.range) - pad.y_offset++ - if(pad.x_offset < pad.range) - pad.x_offset++ - . = TRUE - - if("up-left") - if(pad.y_offset < pad.range) - pad.y_offset++ - if(pad.x_offset > (pad.range * -1)) - pad.x_offset-- - . = TRUE - - if("down-right") - if(pad.y_offset > (pad.range * -1)) - pad.y_offset-- - if(pad.x_offset < pad.range) - pad.x_offset++ - . = TRUE - - if("down-left") - if(pad.y_offset > (pad.range * -1)) - pad.y_offset-- - if(pad.x_offset > (pad.range * -1)) - pad.x_offset-- - . = TRUE - - if("reset") - pad.y_offset = 0 - pad.x_offset = 0 - . = TRUE - if("rename") . = TRUE - var/new_name = stripped_input(usr, "How do you want to rename the launchpad?", "Launchpad", pad.display_name, 15) + var/new_name = params["name"] if(!new_name) return pad.display_name = new_name - if("remove") . = TRUE if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort") pad = null - if("launch") sending = TRUE teleport(usr, pad) . = TRUE - if("pull") sending = FALSE teleport(usr, pad) diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 9a10ede1ac..b010f77cac 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -306,7 +306,7 @@ if(speed <= 0) speed = 1 if("setpath") - var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) + var/newpath = stripped_input(usr, "Please define a new path!", "New Path", path, MAX_MESSAGE_LEN) if(newpath && newpath != "") moving = 0 // stop moving path = newpath @@ -368,13 +368,19 @@ // 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_characters = 50 - for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path + var/lentext = length(path) + var/nextchar = "" + var/charcount = 0 - var/nextchar = copytext(path, i, i+1) // find next character - - if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore - rpath += copytext(path, i, i+1) // else, add to list + for(var/i = 1, i <= lentext, i += length(nextchar)) // iterates through all characters in path + nextchar = path[i] // find next character + if(nextchar in list(";", "&", "*", " ")) // if char is a separator, ignore + continue + rpath += nextchar // else, add to list // there doesn't HAVE to be separators but it makes paths syntatically visible + charcount++ + if(charcount >= maximum_characters) + break diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 5a567886b8..93c94ae8b6 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -62,7 +62,7 @@ var/index = findtext(e, "=") // format is "key=value" if(index) var/key = copytext(e, 1, index) - var/val = copytext(e, index+1) + var/val = copytext(e, index + length(e[index])) codes[key] = val else codes[e] = "1" @@ -167,7 +167,7 @@ Transponder Codes: + + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosControlConsole.js b/tgui-next/packages/tgui/interfaces/AtmosControlConsole.js new file mode 100644 index 0000000000..80c23d434b --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/AtmosControlConsole.js @@ -0,0 +1,100 @@ +import { map } from 'common/collections'; +import { toFixed } from 'common/math'; +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Button, LabeledList, NumberInput, Section } from '../components'; + +export const AtmosControlConsole = props => { + const { act, data } = useBackend(props); + const sensors = data.sensors || []; + return ( + +
+ {sensors.map(sensor => { + const gases = sensor.gases || {}; + return ( +
+ + + {toFixed(sensor.pressure, 2) + ' kPa'} + + {!!sensor.temperature && ( + + {toFixed(sensor.temperature, 2) + ' K'} + + )} + {map((gasPercent, gasId) => { + return ( + + {toFixed(gasPercent, 2) + '%'} + + ); + })(gases)} + +
+ ); + })} +
+ {data.tank && ( +
act('reconnect')} /> + )}> + + +
+ )} +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosFilter.js b/tgui-next/packages/tgui/interfaces/AtmosFilter.js new file mode 100644 index 0000000000..35bbf34686 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/AtmosFilter.js @@ -0,0 +1,52 @@ +import { useBackend } from '../backend'; +import { Button, LabeledList, NumberInput, Section } from '../components'; +import { getGasLabel } from '../constants'; + +export const AtmosFilter = props => { + const { act, data } = useBackend(props); + const filterTypes = data.filter_types || []; + return ( +
+ + +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosMixer.js b/tgui-next/packages/tgui/interfaces/AtmosMixer.js new file mode 100644 index 0000000000..a944bfb686 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/AtmosMixer.js @@ -0,0 +1,66 @@ +import { useBackend } from '../backend'; +import { Button, LabeledList, NumberInput, Section } from '../components'; + +export const AtmosMixer = props => { + const { act, data } = useBackend(props); + return ( +
+ + +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosPump.js b/tgui-next/packages/tgui/interfaces/AtmosPump.js new file mode 100644 index 0000000000..01c50de4d4 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/AtmosPump.js @@ -0,0 +1,63 @@ +import { useBackend } from '../backend'; +import { Button, LabeledList, NumberInput, Section } from '../components'; + +export const AtmosPump = props => { + const { act, data } = useBackend(props); + return ( +
+ + +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/BankMachine.js b/tgui-next/packages/tgui/interfaces/BankMachine.js new file mode 100644 index 0000000000..a3d52097ec --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/BankMachine.js @@ -0,0 +1,33 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Button, LabeledList, NoticeBox, Section } from '../components'; + +export const BankMachine = props => { + const { act, data } = useBackend(props); + const { + current_balance, + siphoning, + station_name, + } = data; + return ( + +
+ + act(siphoning ? 'halt' : 'siphon')} /> + )}> + {current_balance + ' cr'} + + +
+ + Authorized personnel only + +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/Bepis.js b/tgui-next/packages/tgui/interfaces/Bepis.js new file mode 100644 index 0000000000..da23cb11aa --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Bepis.js @@ -0,0 +1,109 @@ +import { multiline } from 'common/string'; +import { Fragment } from 'inferno'; +import { act } from '../byond'; +import { Section, LabeledList, Button, NumberInput, Box, Grid } from '../components'; + +export const Bepis = props => { + const { state } = props; + const { config, data } = state; + const { ref } = config; + const { + amount, + } = data; + return ( +
+
act(ref, 'toggle_power')} /> + )}> + All you need to know about the B.E.P.I.S. and you! + The B.E.P.I.S. performs hundreds of tests a second + using electrical and financial resources to invent + new products, or discover new technologies otherwise + overlooked for being too risky or too niche to produce! +
+
act(ref, 'account_reset')} /> + )}> + Console is currently being operated + by {data.account_owner ? data.account_owner : 'no one'}. +
+ + +
+ + + {data.stored_cash} + + + {data.accuracy_percentage}% + + + {data.positive_cash_offset} + + + {data.negative_cash_offset} + + + act(ref, 'amount', { + amount: value, + })} /> + + +
+ +
+ + + + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/BluespaceArtillery.js b/tgui-next/packages/tgui/interfaces/BluespaceArtillery.js new file mode 100644 index 0000000000..b9f07eabe9 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/BluespaceArtillery.js @@ -0,0 +1,78 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, LabeledList, NoticeBox, Section } from '../components'; + +export const BluespaceArtillery = props => { + const { act, data } = useBackend(props); + const { + notice, + connected, + unlocked, + target, + } = data; + return ( + + {!!notice && ( + + {notice} + + )} + {connected ? ( + +
act('recalibrate')} /> + )}> + + {target || 'No Target Set'} + +
+
+ {unlocked ? ( + +
+
+ ) : ( +
+ + +
+ )} +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/BorgPanel.js b/tgui-next/packages/tgui/interfaces/BorgPanel.js new file mode 100644 index 0000000000..7cc4c860e6 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/BorgPanel.js @@ -0,0 +1,135 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; + +export const BorgPanel = props => { + const { act, data } = useBackend(props); + const borg = data.borg || {}; + const cell = data.cell || {}; + const cellPercent = cell.charge / cell.maxcharge; + const channels = data.channels || []; + const modules = data.modules || []; + const upgrades = data.upgrades || []; + const ais = data.ais || []; + const laws = data.laws || []; + return ( + +
act('rename')} /> + )}> + + +
+
act('toggle_lawupdate')} /> + )}> + {laws.map(law => ( + + {law} + + ))} +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/BrigTimer.js b/tgui-next/packages/tgui/interfaces/BrigTimer.js new file mode 100644 index 0000000000..a83d643334 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/BrigTimer.js @@ -0,0 +1,55 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Button, Section } from '../components'; + +export const BrigTimer = props => { + const { act, data } = useBackend(props); + return ( +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/Canister.js b/tgui-next/packages/tgui/interfaces/Canister.js new file mode 100644 index 0000000000..0e2810e290 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Canister.js @@ -0,0 +1,121 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { AnimatedNumber, Box, Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components'; + +export const Canister = props => { + const { act, data } = useBackend(props); + return ( + + + The regulator {data.hasHoldingTank ? 'is' : 'is not'} connected + to a tank. + +
act('relabel')} /> + )}> + + + kPa + + + {!!data.isPrototype && ( + +
+ +
+ + + + kPa + + + +
+ +
act('eject')} /> + )}> + {!!data.hasHoldingTank && ( + + + {data.holdingTank.name} + + + kPa + + + )} + {!data.hasHoldingTank && ( + + No Holding Tank + + )} +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/Cargo.js b/tgui-next/packages/tgui/interfaces/Cargo.js new file mode 100644 index 0000000000..85ae19755e --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Cargo.js @@ -0,0 +1,339 @@ +import { map } from 'common/collections'; +import { Fragment } from 'inferno'; +import { act } from '../byond'; +import { AnimatedNumber, Box, Button, LabeledList, Section, Tabs } from '../components'; +import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; + +export const Cargo = props => { + const { state } = props; + const { config, data } = state; + const { ref } = config; + const supplies = data.supplies || {}; + const requests = data.requests || []; + const cart = data.cart || []; + + const cartTotalAmount = cart + .reduce((total, entry) => total + entry.cost, 0); + + const cartButtons = !data.requestonly && ( + + + {cart.length === 0 && 'Cart is empty'} + {cart.length === 1 && '1 item'} + {cart.length >= 2 && cart.length + ' items'} + {' '} + {cartTotalAmount > 0 && `(${cartTotalAmount} cr)`} + + + + ))} + + + + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/ChemReactionChamber.js b/tgui-next/packages/tgui/interfaces/ChemReactionChamber.js new file mode 100644 index 0000000000..8c829258ec --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ChemReactionChamber.js @@ -0,0 +1,98 @@ +import { Component } from 'inferno'; +import { act } from '../byond'; +import { Box, Button, LabeledList, NumberInput, Section, Input } from '../components'; +import { map } from 'common/collections'; +import { classes } from 'common/react'; + + +export class ChemReactionChamber extends Component { + constructor() { + super(); + this.state = { + reagentName: "", + reagentQuantity: 1, + }; + } + + setReagentName(reagentName) { + this.setState({ + reagentName, + }); + } + + setReagentQuantity(reagentQuantity) { + this.setState({ + reagentQuantity, + }); + } + + render() { + const { state } = this.props; + const { config, data } = state; + const { ref } = config; + const emptying = data.emptying; + const reagents = data.reagents || []; + return ( +
+ {emptying ? "Emptying" : "Filling"} + + )} > + + + + this.setReagentName(value)} /> + + + this.setReagentQuantity(value)} /> + +
+ ); + } +} diff --git a/tgui-next/packages/tgui/interfaces/ChemSplitter.js b/tgui-next/packages/tgui/interfaces/ChemSplitter.js new file mode 100644 index 0000000000..8e64c43e0f --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ChemSplitter.js @@ -0,0 +1,48 @@ +import { toFixed } from 'common/math'; +import { useBackend } from '../backend'; +import { LabeledList, NumberInput, Section } from '../components'; + +export const ChemSplitter = props => { + const { act, data } = useBackend(props); + const { + straight, + side, + max_transfer, + } = data; + return ( +
+ + + toFixed(value, 2)} + step={0.05} + stepPixelSize={4} + onChange={(e, value) => act('set_amount', { + target: 'straight', + amount: value, + })} /> + + + toFixed(value, 2)} + step={0.05} + stepPixelSize={4} + onChange={(e, value) => act('set_amount', { + target: 'side', + amount: value, + })} /> + + +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/ChemSynthesizer.js b/tgui-next/packages/tgui/interfaces/ChemSynthesizer.js new file mode 100644 index 0000000000..df56dfdc07 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ChemSynthesizer.js @@ -0,0 +1,42 @@ +import { toFixed } from 'common/math'; +import { useBackend } from '../backend'; +import { Box, Button, Section } from '../components'; + +export const ChemSynthesizer = props => { + const { act, data } = useBackend(props); + const { + amount, + current_reagent, + chemicals = [], + possible_amounts = [], + } = data; + return ( +
+ + {possible_amounts.map(possible_amount => ( +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/CodexGigas.js b/tgui-next/packages/tgui/interfaces/CodexGigas.js new file mode 100644 index 0000000000..f96ce9380b --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/CodexGigas.js @@ -0,0 +1,98 @@ +import { useBackend } from '../backend'; +import { Button, LabeledList, Section } from '../components'; + +// TODO: refactor the backend of this it's a trainwreck +export const CodexGigas = props => { + const { act, data } = useBackend(props); + const prefixes = [ + "Dark", + "Hellish", + "Fallen", + "Fiery", + "Sinful", + "Blood", + "Fluffy", + ]; + const titles = [ + "Lord", + "Prelate", + "Count", + "Viscount", + "Vizier", + "Elder", + "Adept", + ]; + const names = [ + "hal", + "ve", + "odr", + "neit", + "ci", + "quon", + "mya", + "folth", + "wren", + "geyr", + "hil", + "niet", + "twou", + "phi", + "coa", + ]; + const suffixes = [ + "the Red", + "the Soulless", + "the Master", + "the Lord of all things", + "Jr.", + ]; + return ( +
+ {data.name} + + + {prefixes.map(prefix => ( +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/ComputerFabricator.js b/tgui-next/packages/tgui/interfaces/ComputerFabricator.js new file mode 100644 index 0000000000..87366f6f73 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ComputerFabricator.js @@ -0,0 +1,403 @@ +import { multiline } from 'common/string'; +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, Grid, Section, Table, Tooltip } from '../components'; + +export const ComputerFabricator = props => { + const { state } = props; + const { act, data } = useBackend(props); + return ( + +
+ Your perfect device, only three steps away... +
+ {data.state !== 0 && ( + + )} /> + + K + + + + + + )} +
+ + {programs.map(program => ( + + +
+
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/NtosNetChat.js b/tgui-next/packages/tgui/interfaces/NtosNetChat.js new file mode 100644 index 0000000000..e6b2ff5f9d --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/NtosNetChat.js @@ -0,0 +1,170 @@ +import { useBackend } from '../backend'; +import { AnimatedNumber, Box, Button, Grid, LabeledList, ProgressBar, Section, Input, Table, Icon, Flex } from '../components'; +import { Fragment } from 'inferno'; +import { createLogger } from '../logging'; + +const logger = createLogger('ntos chat'); + +export const NtosNetChat = props => { + const { act, data } = useBackend(props); + + const { + can_admin, + adminmode, + authed, + username, + active_channel, + is_operator, + all_channels = [], + clients = [], + messages = [], + } = data; + + const in_channel = (active_channel !== null); + const authorized = (authed || adminmode); + + return ( +
+ + + + + act('PRG_newchannel', { + new_channel_name: value, + })} /> + {all_channels.map(channel => ( +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/NtosNetDownloader.js b/tgui-next/packages/tgui/interfaces/NtosNetDownloader.js new file mode 100644 index 0000000000..da3359fb87 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/NtosNetDownloader.js @@ -0,0 +1,123 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, Flex, Icon, LabeledList, NoticeBox, ProgressBar, Section } from '../components'; + +export const NtosNetDownloader = props => { + const { state } = props; + const { act, data } = useBackend(props); + const { + disk_size, + disk_used, + downloadable_programs = [], + error, + hacked_programs = [], + hackedavailable, + } = data; + return ( + + {!!error && ( + + + {error} + + + + + {data.sheets} + {(data.sheets >= 1) && ( + + )} + + + + + + {data.current_heat < 100 ? ( + Nominal + ) : ( + data.current_heat < 200 ? ( + Caution + ) : ( + DANGER + ) + )} + + + +
+ + + {data.power_output} + + + + + + + + {data.connected ? data.power_available : "Unconnected"} + + + +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/PowerMonitor.js b/tgui-next/packages/tgui/interfaces/PowerMonitor.js new file mode 100644 index 0000000000..8998344be5 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/PowerMonitor.js @@ -0,0 +1,222 @@ +import { map, sortBy } from 'common/collections'; +import { flow } from 'common/fp'; +import { toFixed } from 'common/math'; +import { pureComponentHooks } from 'common/react'; +import { Component, Fragment } from 'inferno'; +import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components'; + +const PEAK_DRAW = 500000; + +const powerRank = str => { + const unit = String(str.split(' ')[1]).toLowerCase(); + return ['w', 'kw', 'mw', 'gw'].indexOf(unit); +}; + +export class PowerMonitor extends Component { + constructor() { + super(); + this.state = { + sortByField: null, + }; + } + + render() { + const { state } = this.props; + const { data } = state; + const { history } = data; + const { sortByField } = this.state; + const supply = history.supply[history.supply.length - 1] || 0; + const demand = history.demand[history.demand.length - 1] || 0; + const supplyData = history.supply.map((value, i) => [i, value]); + const demandData = history.demand.map((value, i) => [i, value]); + const maxValue = Math.max( + PEAK_DRAW, + ...history.supply, + ...history.demand); + // Process area data + const areas = flow([ + map((area, i) => ({ + ...area, + // Generate a unique id + id: area.name + i, + })), + sortByField === 'name' && sortBy(area => area.name), + sortByField === 'charge' && sortBy(area => -area.charge), + sortByField === 'draw' && sortBy( + area => -powerRank(area.load), + area => -parseFloat(area.load)), + ])(data.areas); + return ( + + + +
+ + + + + + + + +
+
+ +
+ + +
+
+
+
+ + + Sort by: + + this.setState({ + sortByField: sortByField !== 'name' && 'name', + })} /> + this.setState({ + sortByField: sortByField !== 'charge' && 'charge', + })} /> + this.setState({ + sortByField: sortByField !== 'draw' && 'draw', + })} /> + + + + + Area + + + Charge + + + Draw + + + Eqp + + + Lgt + + + Env + + + {areas.map((area, i) => ( + + + + + + + + + ))} +
+ {area.name} + + + + {area.load} + + + + + + +
+
+
+ ); + } +} + +const AreaCharge = props => { + const { charging, charge } = props; + return ( + + 50 + ? 'battery-half' + : 'battery-quarter' + ) + || charging === 1 && 'bolt' + || charging === 2 && 'battery-full' + )} + color={( + charging === 0 && ( + charge > 50 + ? 'yellow' + : 'red' + ) + || charging === 1 && 'yellow' + || charging === 2 && 'green' + )} /> + + {toFixed(charge) + '%'} + + + ); +}; + +AreaCharge.defaultHooks = pureComponentHooks; + +const AreaStatusColorBox = props => { + const { status } = props; + const power = Boolean(status & 2); + const mode = Boolean(status & 1); + const tooltipText = (power ? 'On' : 'Off') + + ` [${mode ? 'auto' : 'manual'}]`; + return ( + + ); +}; + +AreaStatusColorBox.defaultHooks = pureComponentHooks; diff --git a/tgui-next/packages/tgui/interfaces/Radio.js b/tgui-next/packages/tgui/interfaces/Radio.js new file mode 100644 index 0000000000..e335cf1cac --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Radio.js @@ -0,0 +1,108 @@ +import { map } from 'common/collections'; +import { toFixed } from 'common/math'; +import { useBackend } from '../backend'; +import { Box, Button, LabeledList, NumberInput, Section } from '../components'; +import { RADIO_CHANNELS } from '../constants'; + +export const Radio = props => { + const { act, data } = useBackend(props); + const { + freqlock, + frequency, + minFrequency, + maxFrequency, + listening, + broadcasting, + command, + useCommand, + subspace, + subspaceSwitchable, + } = data; + const tunedChannel = RADIO_CHANNELS + .find(channel => channel.freq === frequency); + const channels = map((value, key) => ({ + name: key, + status: !!value, + }))(data.channels); + return ( +
+ + + {freqlock && ( + + {toFixed(frequency / 10, 1) + ' kHz'} + + ) || ( + toFixed(value, 1)} + onDrag={(e, value) => act('frequency', { + adjust: (value - frequency / 10), + })} /> + )} + {tunedChannel && ( + + [{tunedChannel.name}] + + )} + + +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/RapidPipeDispenser.js b/tgui-next/packages/tgui/interfaces/RapidPipeDispenser.js new file mode 100644 index 0000000000..17e4fd9d15 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/RapidPipeDispenser.js @@ -0,0 +1,188 @@ +import { classes } from 'common/react'; +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, ColorBox, Flex, LabeledList, Section, Tabs } from '../components'; + +const ROOT_CATEGORIES = [ + 'Atmospherics', + 'Disposals', + 'Transit Tubes', +]; + +const ICON_BY_CATEGORY_NAME = { + 'Atmospherics': 'wrench', + 'Disposals': 'trash-alt', + 'Transit Tubes': 'bus', + 'Pipes': 'grip-lines', + 'Disposal Pipes': 'grip-lines', + 'Devices': 'microchip', + 'Heat Exchange': 'thermometer-half', + 'Station Equipment': 'microchip', +}; + +const PAINT_COLORS = { + grey: '#bbbbbb', + amethyst: '#a365ff', + blue: '#4466ff', + brown: '#b26438', + cyan: '#48eae8', + dark: '#808080', + green: '#1edd00', + orange: '#ffa030', + purple: '#b535ea', + red: '#ff3333', + violet: '#6e00f6', + yellow: '#ffce26', +}; + +const TOOLS = [ + { + name: 'Dispense', + bitmask: 1, + }, + { + name: 'Connect', + bitmask: 2, + }, + { + name: 'Destroy', + bitmask: 4, + }, + { + name: 'Paint', + bitmask: 8, + }, +]; + +export const RapidPipeDispenser = props => { + const { act, data } = useBackend(props); + const { + category: rootCategoryIndex, + categories = [], + selected_color, + piping_layer, + mode, + } = data; + const previews = data.preview_rows.flatMap(row => row.previews); + return ( + +
+ + + {ROOT_CATEGORIES.map((categoryName, i) => ( +
+ + +
+ {rootCategoryIndex === 0 && ( + + {[1, 2, 3].map(layer => ( + act('piping_layer', { + piping_layer: layer, + })} /> + ))} + + )} + + {previews.map(preview => ( + + ))} + +
+
+ +
+ + {categories.map(category => ( + + {() => category.recipes.map(recipe => ( + act('pipe_type', { + pipe_type: recipe.pipe_index, + category: category.cat_name, + })} /> + ))} + + ))} + +
+
+
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SatelliteControl.js b/tgui-next/packages/tgui/interfaces/SatelliteControl.js new file mode 100644 index 0000000000..73a7f1ffbb --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SatelliteControl.js @@ -0,0 +1,45 @@ +import { useBackend } from '../backend'; +import { Button, LabeledList, ProgressBar, Section, Table, Box } from '../components'; +import { Fragment } from 'inferno'; +import { LabeledListItem } from '../components/LabeledList'; + +export const SatelliteControl = props => { + const { act, data } = useBackend(props); + const satellites = data.satellites || []; + return ( + + {data.meteor_shield && ( +
+ + + + + +
+ )} +
+ + {satellites.map(satellite => ( + act('toggle', { + id: satellite.id, + })} + /> + ))} + +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/ScannerGate.js b/tgui-next/packages/tgui/interfaces/ScannerGate.js new file mode 100644 index 0000000000..f1e82729bc --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ScannerGate.js @@ -0,0 +1,351 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, LabeledList, NumberInput, Section } from '../components'; +import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; + +const DISEASE_THEASHOLD_LIST = [ + 'Positive', + 'Harmless', + 'Minor', + 'Medium', + 'Harmful', + 'Dangerous', + 'BIOHAZARD', +]; + +const TARGET_SPECIES_LIST = [ + { + name: 'Human', + value: 'human', + }, + { + name: 'Lizardperson', + value: 'lizard', + }, + { + name: 'Flyperson', + value: 'fly', + }, + { + name: 'Felinid', + value: 'felinid', + }, + { + name: 'Plasmaman', + value: 'plasma', + }, + { + name: 'Mothperson', + value: 'moth', + }, + { + name: 'Jellyperson', + value: 'jelly', + }, + { + name: 'Podperson', + value: 'pod', + }, + { + name: 'Golem', + value: 'golem', + }, + { + name: 'Zombie', + value: 'zombie', + }, +]; + +const TARGET_NUTRITION_LIST = [ + { + name: 'Starving', + value: 150, + }, + { + name: 'Obese', + value: 600, + }, +]; + +export const ScannerGate = props => { + const { state } = props; + const { act, data } = useBackend(props); + return ( + + act('toggle_lock')} /> + {!data.locked && ( + + )} + + ); +}; + +const SCANNER_GATE_ROUTES = { + Off: { + title: 'Scanner Mode: Off', + component: () => ScannerGateOff, + }, + Wanted: { + title: 'Scanner Mode: Wanted', + component: () => ScannerGateWanted, + }, + Guns: { + title: 'Scanner Mode: Guns', + component: () => ScannerGateGuns, + }, + Mindshield: { + title: 'Scanner Mode: Mindshield', + component: () => ScannerGateMindshield, + }, + Disease: { + title: 'Scanner Mode: Disease', + component: () => ScannerGateDisease, + }, + Species: { + title: 'Scanner Mode: Species', + component: () => ScannerGateSpecies, + }, + Nutrition: { + title: 'Scanner Mode: Nutrition', + component: () => ScannerGateNutrition, + }, + Nanites: { + title: 'Scanner Mode: Nanites', + component: () => ScannerGateNanites, + }, +}; + +const ScannerGateControl = props => { + const { state } = props; + const { act, data } = useBackend(props); + const { scan_mode } = data; + const route = SCANNER_GATE_ROUTES[scan_mode] + || SCANNER_GATE_ROUTES.off; + const Component = route.component(); + return ( +
act('set_mode', { new_mode: 'Off' })} /> + )}> + +
+ ); +}; + +const ScannerGateOff = props => { + const { act } = useBackend(props); + return ( + + + Select a scanning mode below. + + + + )}> + {data.contents.length === 0 && ( + + Unfortunately, this {data.name} is empty. + + ) || ( + + + + Item + + + + {data.verb ? data.verb : 'Dispense'} + + + {map((value, key) => ( + + + {value.name} + + + {value.amount} + + +
+ )} + + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/Smes.js b/tgui-next/packages/tgui/interfaces/Smes.js new file mode 100644 index 0000000000..7479af5894 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Smes.js @@ -0,0 +1,176 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, NumberInput, LabeledList, ProgressBar, Section } from '../components'; + +export const Smes = props => { + const { act, data } = useBackend(props); + + let inputState; + if (data.capacityPercent >= 100) { + inputState = 'good'; + } + else if (data.inputting) { + inputState = 'average'; + } + else { + inputState = 'bad'; + } + let outputState; + if (data.outputting) { + outputState = 'good'; + } + else if (data.charge > 0) { + outputState = 'average'; + } + else { + outputState = 'bad'; + } + + return ( + +
+ +
+
+ + act('tryinput')}> + {data.inputAttempt ? 'Auto' : 'Off'} + + }> + + {data.capacityPercent >= 100 + ? 'Fully Charged' + : data.inputting + ? 'Charging' + : 'Not Charging'} + + + + + + +
+
+ + act('tryoutput')}> + {data.outputAttempt ? 'On' : 'Off'} + + }> + + {data.outputting + ? 'Sending' + : data.charge > 0 + ? 'Not Sending' + : 'No Charge'} + + + + + + +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SmokeMachine.js b/tgui-next/packages/tgui/interfaces/SmokeMachine.js new file mode 100644 index 0000000000..16ba078910 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SmokeMachine.js @@ -0,0 +1,71 @@ +import { useBackend } from '../backend'; +import { Fragment } from 'inferno'; +import { AnimatedNumber, Box, Button, LabeledList, ProgressBar, NoticeBox, Section } from '../components'; + +export const SmokeMachine = props => { + const { act, data } = useBackend(props); + const { + TankContents, + isTankLoaded, + TankCurrentVolume, + TankMaxVolume, + active, + setting, + screen, + maxSetting = [], + } = data; + return ( + +
act('power')} /> + )}> + + + {' / ' + TankMaxVolume} + + + + + { [1, 2, 3, 4, 5].map(amount => ( +
+
act('purge')} /> + )}> + {TankContents.map(chemical => ( + + + {' '} + units of {chemical.name} + + ))} +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SolarControl.js b/tgui-next/packages/tgui/interfaces/SolarControl.js new file mode 100644 index 0000000000..1cfb4800c0 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SolarControl.js @@ -0,0 +1,118 @@ +import { toFixed } from 'common/math'; +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, Grid, LabeledList, NumberInput, ProgressBar, Section } from '../components'; + +export const SolarControl = props => { + const { act, data } = useBackend(props); + const { + generated, + generated_ratio, + azimuth_current, + azimuth_rate, + max_rotation_rate, + tracking_state, + connected_panels, + connected_tracker, + } = data; + return ( + +
act('refresh')} /> + )}> + + + + + {connected_tracker ? 'OK' : 'N/A'} + + 0 ? 'good' : 'bad'}> + {connected_panels} + + + + + + + + + + + +
+
+ + +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SpaceHeater.js b/tgui-next/packages/tgui/interfaces/SpaceHeater.js new file mode 100644 index 0000000000..c44f3e9c47 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SpaceHeater.js @@ -0,0 +1,104 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, LabeledList, NumberInput, ProgressBar, Section } from '../components'; + +export const SpaceHeater = props => { + const { act, data } = useBackend(props); + return ( + +
+
+
+ + + 50 + ? 'bad' + : Math.abs(data.targetTemp - data.currentTemp) > 20 + ? 'average' + : 'good'}> + {data.currentTemp}°C + + + + {data.open && ( + act('target', { + target: value, + })} /> + ) || ( + data.targetTemp + '°C' + )} + + + {!data.open && 'Auto' || ( + +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SpawnersMenu.js b/tgui-next/packages/tgui/interfaces/SpawnersMenu.js new file mode 100644 index 0000000000..27d8b1f9ff --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SpawnersMenu.js @@ -0,0 +1,51 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, Section } from '../components'; + +export const SpawnersMenu = props => { + const { act, data } = useBackend(props); + const spawners = data.spawners || []; + return ( +
+ {spawners.map(spawner => ( +
+
+ ))} +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/StationAlertConsole.js b/tgui-next/packages/tgui/interfaces/StationAlertConsole.js new file mode 100644 index 0000000000..c372b532e9 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/StationAlertConsole.js @@ -0,0 +1,57 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Section } from '../components'; + +export const StationAlertConsole = props => { + const { data } = useBackend(props); + const categories = data.alarms || []; + const fire = categories['Fire'] || []; + const atmos = categories['Atmosphere'] || []; + const power = categories['Power'] || []; + return ( + +
+
    + {fire.length === 0 && ( +
  • + Systems Nominal +
  • + )} + {fire.map(alert => ( +
  • + {alert} +
  • + ))} +
+
+
+
    + {atmos.length === 0 && ( +
  • + Systems Nominal +
  • + )} + {atmos.map(alert => ( +
  • + {alert} +
  • + ))} +
+
+
+
    + {power.length === 0 && ( +
  • + Systems Nominal +
  • + )} + {power.map(alert => ( +
  • + {alert} +
  • + ))} +
+
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SuitStorageUnit.js b/tgui-next/packages/tgui/interfaces/SuitStorageUnit.js new file mode 100644 index 0000000000..f858505a37 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SuitStorageUnit.js @@ -0,0 +1,111 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, Icon, LabeledList, NoticeBox, Section } from '../components'; + +export const SuitStorageUnit = props => { + const { act, data } = useBackend(props); + const { + locked, + open, + safeties, + uv_active, + occupied, + suit, + helmet, + mask, + storage, + } = data; + return ( + + {!!(occupied && safeties) && ( + + Biological entity detected in suit chamber. Please remove + before continuing with operation. + + )} + {uv_active && ( + + Contents are currently being decontaminated. Please wait. + + ) || ( +
+ {!open && ( +
+ )} +
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/SyndContractor.js b/tgui-next/packages/tgui/interfaces/SyndContractor.js new file mode 100644 index 0000000000..23f152a831 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/SyndContractor.js @@ -0,0 +1,382 @@ +import { Box, Button, Section, Dimmer, Table, Icon, NoticeBox, Tabs, Grid, LabeledList } from "../components"; +import { useBackend } from "../backend"; +import { Fragment, Component } from "inferno"; + +export class FakeTerminal extends Component { + constructor(props) { + super(props); + this.timer = null; + this.state = { + currentIndex: 0, + currentDisplay: [], + }; + } + + tick() { + const { props, state } = this; + if (state.currentIndex <= props.allMessages.length) { + this.setState(prevState => { + return ({ + currentIndex: prevState.currentIndex + 1, + }); + }); + const { currentDisplay } = state; + currentDisplay.push(props.allMessages[state.currentIndex]); + } else { + clearTimeout(this.timer); + setTimeout(props.onFinished, props.finishedTimeout); + } + } + + componentDidMount() { + const { + linesPerSecond = 2.5, + } = this.props; + this.timer = setInterval(() => this.tick(), 1000 / linesPerSecond); + } + + componentWillUnmount() { + clearTimeout(this.timer); + } + + render() { + return ( + + {this.state.currentDisplay.map(value => ( + + {value} +
+
+ ))} +
+ ); + } +} + +export const SyndContractor = props => { + const { data, act } = useBackend(props); + + const terminalMessages = [ + "Recording biometric data...", + "Analyzing embedded syndicate info...", + "STATUS CONFIRMED", + "Contacting syndicate database...", + "Awaiting response...", + "Awaiting response...", + "Awaiting response...", + "Awaiting response...", + "Awaiting response...", + "Awaiting response...", + "Response received, ack 4851234...", + "CONFIRM ACC " + (Math.round(Math.random() * 20000)), + "Setting up private accounts...", + "CONTRACTOR ACCOUNT CREATED", + "Searching for available contracts...", + "Searching for available contracts...", + "Searching for available contracts...", + "Searching for available contracts...", + "CONTRACTS FOUND", + "WELCOME, AGENT", + ]; + + const infoEntries = [ + "SyndTract v2.0", + "", + "We've identified potentional high-value targets that are", + "currently assigned to your mission area. They are believed", + "to hold valuable information which could be of immediate", + "importance to our organisation.", + "", + "Listed below are all of the contracts available to you. You", + "are to bring the specified target to the designated", + "drop-off, and contact us via this uplink. We will send", + "a specialised extraction unit to put the body into.", + "", + "We want targets alive - but we will sometimes pay slight", + "amounts if they're not, you just won't recieve the shown", + "bonus. You can redeem your payment through this uplink in", + "the form of raw telecrystals, which can be put into your", + "regular Syndicate uplink to purchase whatever you may need.", + "We provide you with these crystals the moment you send the", + "target up to us, which can be collected at anytime through", + "this system.", + "", + "Targets extracted will be ransomed back to the station once", + "their use to us is fulfilled, with us providing you a small", + "percentage cut. You may want to be mindful of them", + "identifying you when they come back. We provide you with", + "a standard contractor loadout, which will help cover your", + "identity.", + ]; + + const errorPane = !!data.error && ( + + + + + + + + + + {data.error} + +
+
+
+ ); + + if (!data.logged_in) { + return ( +
+ +
+ ); + } + + if (data.logged_in && data.first_load) { + return ( + + act('PRG_set_first_load_finished')} /> + + ); + } + + if (data.info_screen) { + return ( + + + + +