diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..8874507d61f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,62 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + + + +#### Description of issue + + + +#### Difference between expected and actual behavior + + + +#### Steps to reproduce + + + +#### Specific information for locating + + + + +#### Length of time in which bug has been known to occur + + + + +#### Client version, Server revision & Game ID + + + + +#### Issue bingo + + +- [ ] Issue could be reproduced at least once +- [ ] Issue could be reproduced by different players +- [ ] Issue could be reproduced in multiple rounds +- [ ] Issue happened in a recent (less than 7 days ago) round +- [ ] [Couldn't find an existing issue about this](https://github.com/HearthOfHestia/Nebula/issues) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..7c4bdc9e7de --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,41 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[FEATURE]" +labels: enhancement +assignees: '' + +--- + + +#### Is your feature request related to a problem? Please describe. +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +#### Describe the solution you'd like +A clear and concise description of what you want to happen. + +#### Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +#### Additional context +Add any other context or screenshots about the feature request here. + +#### Feature bingo + + +- [ ] Feature does not already exist +- [ ] Feature has not been rejected in the past 30 days +- [ ] Feature has no maintainer vetos +- [ ] Feature does not break the [Github Acceptable Use Policies on restricted content](https://docs.github.com/en/github/site-policy/github-acceptable-use-policies#2-content-restrictions) +- [ ] [Couldn't find an existing feature request about this](https://github.com/HearthOfHestia/Nebula/labels/enhancement). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 00b0aaf434a..c720132d1b5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,31 +1,26 @@ + - - - + ## Description of changes - ## Why and what will this PR improve - ## Authorship - ## Changelog - + :cl: prefix: /:cl: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bf52f761a5e..cfab69d15d9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,8 +15,8 @@ on: env: BYOND_MAJOR: "514" - BYOND_MINOR: "1566" - SPACEMAN_DMM_VERSION: suite-1.7 + BYOND_MINOR: "1572" + SPACEMAN_DMM_VERSION: suite-1.7.1 jobs: DreamChecker: @@ -80,7 +80,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - map_path: [example, tradeship, nexus, exodus, ministation, away_sites_testing, modpack_testing] + map_path: [example, tradeship, nexus, exodus, ministation, away_sites_testing, modpack_testing, torch] steps: - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f - name: Setup Cache diff --git a/code/__defines/directions.dm b/code/__defines/directions.dm index bb6252cb3e6..b4524560447 100644 --- a/code/__defines/directions.dm +++ b/code/__defines/directions.dm @@ -16,6 +16,8 @@ #define CORNER_EASTWEST CORNER_COUNTERCLOCKWISE #define CORNER_NORTHSOUTH CORNER_CLOCKWISE +#define FIRST_DIR(X) ((X) & -(X)) + /* turn() is weird: turn(icon, angle) turns icon by angle degrees clockwise diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 106bafe44ce..0f3cd9bd04b 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -46,7 +46,7 @@ The latter will result in a linter warning and will not work correctly. #define ATOM_FLAG_ADJACENT_EXCEPTION BITFLAG(9) // Skips adjacent checks for atoms that should always be reachable in window tiles #define ATOM_FLAG_NO_DISSOLVE BITFLAG(10) // Bypasses solvent reactions in the container. #define ATOM_FLAG_NO_PHASE_CHANGE BITFLAG(11) // Bypasses heating and cooling product reactions in the container. -#define ATOM_FLAG_ALLOW_DIAGONAL_FACING BITFLAG(12) // Atom can face non-cardinal directions. +#define ATOM_FLAG_BLOCK_DIAGONAL_FACING BITFLAG(12) // Atom cannot face non-cardinal directions. #define ATOM_IS_OPEN_CONTAINER(A) (A.atom_flags & ATOM_FLAG_OPEN_CONTAINER) diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 1d7dab5188e..e753c7766f8 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -261,11 +261,25 @@ #define Z_ALL_TURFS(Z) block(locate(1, 1, Z), locate(world.maxx, world.maxy, Z)) -#if DM_BUILD < 1540 -#define AS_ANYTHING as() -#else #define AS_ANYTHING as anything -#endif + +// Cooking appliances. +#define APPLIANCE_MIX BITFLAG(0) +#define APPLIANCE_FRYER BITFLAG(1) +#define APPLIANCE_OVEN BITFLAG(2) +#define APPLIANCE_SKILLET BITFLAG(3) +#define APPLIANCE_SAUCEPAN BITFLAG(4) +#define APPLIANCE_POT BITFLAG(5) +#define APPLIANCE_MICROWAVE BITFLAG(6) +// Cooking misc. +// can_insert return values +#define CANNOT_INSERT 0 +#define CAN_INSERT 1 +#define INSERT_GRABBED 2 +// check_contents return values +#define CONTAINER_EMPTY 0 +#define CONTAINER_SINGLE 1 +#define CONTAINER_MANY 2 //NOTE: INTENT_HOTKEY_* defines are not actual intents! //they are here to support hotkeys @@ -286,3 +300,6 @@ #define WRITTEN_SKIP 0 #define WRITTEN_PHYSICAL 1 #define WRITTEN_DIGITAL 2 + +// arbitrary low pressure bound for wind weather effects +#define MIN_WIND_PRESSURE 10 diff --git a/code/__defines/temperature.dm b/code/__defines/temperature.dm index 098cdf3ee3e..a1280715022 100644 --- a/code/__defines/temperature.dm +++ b/code/__defines/temperature.dm @@ -3,11 +3,13 @@ #define ATOM_TEMPERATURE_EQUILIBRIUM_CONSTANT 0.25 #define ADJUST_ATOM_TEMPERATURE(_atom, _temp) \ - _atom.temperature = _temp; \ - if(_atom.reagents) { \ - HANDLE_REACTIONS(_atom.reagents); \ - } \ - QUEUE_TEMPERATURE_ATOMS(_atom); + if(!QDELETED(_atom)) { \ + _atom.temperature = _temp; \ + if(!QDELETED(_atom.reagents)) { \ + HANDLE_REACTIONS(_atom.reagents); \ + } \ + QUEUE_TEMPERATURE_ATOMS(_atom);\ + } #define QUEUE_TEMPERATURE_ATOMS(_atoms) \ if(islist(_atoms)) { \ diff --git a/code/_global_vars/lists/flavor.dm b/code/_global_vars/lists/flavor.dm index 2553ba15545..28bf458706f 100644 --- a/code/_global_vars/lists/flavor.dm +++ b/code/_global_vars/lists/flavor.dm @@ -34,10 +34,10 @@ var/global/list/station_prefixes = list("", "Imperium", "Heretical", "Cuban", var/global/list/station_names = list("", "Stanford", "Dwarf", "Alien", "Aegis", "Death-World", "Rogue", "Safety", "Paranoia", - "Explosive", "North", "West", "East", "South", "Slant-ways", - "Widdershins", "Rimward", "Expensive", "Procreatory", "Imperial", - "Unidentified", "Immoral", "Carp", "Orc", "Pete", "Control", - "Nettle", "Class", "Crab", "Fist", "Corrogated", "Skeleton", + "Explosive", "North", "West", "East", "South", "Slant-ways", + "Widdershins", "Rimward", "Expensive", "Procreatory", "Imperial", + "Unidentified", "Immoral", "Carp", "Orc", "Pete", "Control", + "Nettle", "Class", "Crab", "Fist", "Corrogated", "Skeleton", "Gentleman", "Capitalist", "Communist", "Bear", "Beard", "Space", "Star", "Moon", "System", "Mining", "Research", "Supply", "Military", "Orbital", "Battle", "Science", "Asteroid", "Home", "Production", diff --git a/code/_global_vars/lists/names.dm b/code/_global_vars/lists/names.dm index 5eb78e06c32..d9f4bec71f7 100644 --- a/code/_global_vars/lists/names.dm +++ b/code/_global_vars/lists/names.dm @@ -1,3 +1,5 @@ +// All variables here use double quotes to able load information on every startup. + var/global/list/ai_names = file2list("config/names/ai.txt") var/global/list/wizard_first = file2list("config/names/wizardfirst.txt") var/global/list/wizard_second = file2list("config/names/wizardsecond.txt") @@ -11,5 +13,3 @@ var/global/list/clown_names = file2list("config/names/clown.txt") var/global/list/verbs = file2list("config/names/verbs.txt") var/global/list/adjectives = file2list("config/names/adjectives.txt") -//loaded on startup because of " -//would include in rsc if ' was used diff --git a/code/_helpers/medical_scans.dm b/code/_helpers/medical_scans.dm index 86c7d463727..05bd3cd191e 100644 --- a/code/_helpers/medical_scans.dm +++ b/code/_helpers/medical_scans.dm @@ -265,7 +265,6 @@ if(E["is_stump"]) row += "Missing" else - row += "" var/rowdata = list() if(E["brute_dam"] + E["burn_dam"] == 0) rowdata += "None" @@ -279,7 +278,7 @@ rowdata += "[capitalize(get_wound_severity(E["brute_ratio"], (E["limb_flags"] & ORGAN_FLAG_HEALS_OVERKILL)))] physical trauma" if(E["burn_dam"]) rowdata += "[capitalize(get_wound_severity(E["burn_ratio"], (E["limb_flags"] & ORGAN_FLAG_HEALS_OVERKILL)))] burns" - row += "[jointext(rowdata, "
")]" + row += "[jointext(rowdata, "
")]" if(skill_level >= SKILL_ADEPT) var/list/status = list() diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index dac307ef4ad..3b1a5b1cbd2 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -14,9 +14,9 @@ */ // Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts. -/proc/sanitizeSQL(var/t as text) - var/sqltext = dbcon.Quote(t); - return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that +/proc/sanitize_sql(t) + var/sqltext = dbcon.Quote("[t]") // http://www.byond.com/forum/post/2218538 + return copytext(sqltext, 2, -1) /* * Text sanitization @@ -24,7 +24,7 @@ //Used for preprocessing entered text //Added in an additional check to alert players if input is too long -/proc/sanitize(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1) +/proc/sanitize(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE, ascii_only = FALSE) if(!input) return @@ -33,47 +33,68 @@ if(input_length > max_length) to_chat(usr, SPAN_WARNING("Your message is too long by [input_length - max_length] character\s.")) return - input = copytext_char(input, 1, max_length + 1) + input = copytext_char(input, 1, max_length) if(extra) input = replace_characters(input, list("\n"=" ","\t"=" ")) + if(ascii_only) + // Some procs work differently depending on unicode/ascii string + // You should always consider this with any text processing work + // More: http://www.byond.com/docs/ref/info.html#/{notes}/Unicode + // http://www.byond.com/forum/post/2520672 + input = strip_non_ascii(input) + else + // Strip Unicode control/space-like chars here exept for line endings (\n,\r) and normal space (0x20) + // codes from https://www.compart.com/en/unicode/category/ + // https://en.wikipedia.org/wiki/Whitespace_character#Unicode + var/static/regex/unicode_control_chars = regex(@"[\u0001-\u0009\u000B\u000C\u000E-\u001F\u007F\u0080-\u009F\u00A0\u1680\u180E\u2000-\u200D\u2028\u2029\u202F\u205F\u2060\u3000\uFEFF]", "g") + input = unicode_control_chars.Replace(input, "") + if(encode) - // The below \ escapes have a space inserted to attempt to enable unit testing of span class usage. Please do not remove the space. - //In addition to processing html, html_encode removes byond formatting codes like "\ red", "\ i" and other. - //It is important to avoid double-encode text, it can "break" quotes and some other characters. - //Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.) + // In addition to processing html, html_encode removes byond formatting codes like "\red", "\i" and other. + // It is important to avoid double-encode text, it can "break" quotes and some other characters. + // Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.) input = html_encode(input) else - //If not need encode text, simply remove < and > - //note: we can also remove here byond formatting codes: 0xFF + next byte + // If not need encode text, simply remove < and > + // note: we can also remove here byond formatting codes: 0xFF + next byte input = replace_characters(input, list("<"=" ", ">"=" ")) if(trim) - //Maybe, we need trim text twice? Here and before copytext? input = trim(input) return input -//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places, after html_encode(). +//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places after html_encode(). //Best used for sanitize object names, window titles. //If you have a problem with sanitize() in chat, when quotes and >, < are displayed as html entites - -//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitizeSafe()! -/proc/sanitizeSafe(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1) - return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra) +//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitize_safe()! +/proc/sanitize_safe(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE, ascii_only = FALSE) + return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra, ascii_only) + +/proc/paranoid_sanitize(t) + var/regex/alphanum_only = regex("\[^a-zA-Z0-9# ,.?!:;()]", "g") + return alphanum_only.Replace(t, "#") //Filters out undesirable characters from names -/proc/sanitizeName(var/input, var/max_length = MAX_NAME_LEN, var/allow_numbers = 0, var/force_first_letter_uppercase = TRUE) - if(!input || length(input) > max_length) +/proc/sanitize_name(input, max_length = MAX_NAME_LEN, allow_numbers = 0, force_first_letter_uppercase = TRUE) + if(!input || length_char(input) > max_length) return //Rejects the input if it is null or if it is longer then the max length allowed var/number_of_alphanumeric = 0 var/last_char_group = 0 var/output = "" - for(var/i=1, i<=length(input), i++) - var/ascii_char = text2ascii(input,i) - switch(ascii_char) + var/char = "" + var/bytes_length = length(input) + var/ascii_char + for(var/i = 1, i <= bytes_length, i += length(char)) + char = input[i] + + ascii_char = text2ascii(char) + + switch(ascii_char) //todo: unicode names? // A .. Z if(65 to 90) //Uppercase Letters output += ascii2text(ascii_char) @@ -121,10 +142,7 @@ if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '" if(last_char_group == 1) - output = copytext(output,1,length(output)) //removes the last character (in this case a space) - - for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai","plating")) //prevents these common metagamey names - if(cmptext(output,bad_name)) return //(not case sensitive) + output = copytext(output, 1, -1) //removes the last character (in this case a space) return output @@ -213,11 +231,16 @@ * Text modification */ -/proc/replace_characters(var/t,var/list/repl_chars) +/proc/replace_characters(t, list/repl_chars) for(var/char in repl_chars) t = replacetext(t, char, repl_chars[char]) return t +/proc/random_string(length, list/characters) + . = "" + for (var/i in 1 to length) + . += pick(characters) + //Adds 'u' number of zeros ahead of the text 't' /proc/add_zero(t, u) return pad_left(t, u, "0") @@ -233,13 +256,13 @@ // Adds the required amount of 'character' in front of 'text' to extend the lengh to 'desired_length', if it is shorter // No consideration are made for a multi-character 'character' input /proc/pad_left(text, desired_length, character) - var/padding = generate_padding(length(text), desired_length, character) + var/padding = generate_padding(length_char(text), desired_length, character) return length(padding) ? "[padding][text]" : text // Adds the required amount of 'character' after 'text' to extend the lengh to 'desired_length', if it is shorter // No consideration are made for a multi-character 'character' input /proc/pad_right(text, desired_length, character) - var/padding = generate_padding(length(text), desired_length, character) + var/padding = generate_padding(length_char(text), desired_length, character) return length(padding) ? "[text][padding]" : text /proc/generate_padding(current_length, desired_length, character) @@ -250,32 +273,59 @@ characters += character return JOINTEXT(characters) - -//Returns a string with reserved characters and spaces before the first letter removed +// Returns a string with reserved characters and spaces before the first letter removed +// not work for unicode spaces - you should cleanup them first with sanitize() /proc/trim_left(text) for (var/i = 1 to length(text)) if (text2ascii(text, i) > 32) return copytext(text, i) return "" -//Returns a string with reserved characters and spaces after the last letter removed +// Returns a string with reserved characters and spaces after the last letter removed +// not work for unicode spaces - you should cleanup them first with sanitize() /proc/trim_right(text) for (var/i = length(text), i > 0, i--) if (text2ascii(text, i) > 32) return copytext(text, 1, i + 1) + return "" -//Returns a string with reserved characters and spaces before the first word and after the last word removed. +// Returns a string with reserved characters and spaces before the first word and after the last word removed. +// not work for unicode spaces - you should cleanup them first with sanitize() /proc/trim(text) return trim_left(trim_right(text)) //Returns a string with the first element of the string capitalized. -/proc/capitalize(var/t as text) - return uppertext(copytext_char(t, 1, 2)) + copytext_char(t, 2) +/proc/capitalize(text) + if(text) + text = uppertext(text[1]) + copytext(text, 1 + length(text[1])) + return text + +//Returns a string with the first element of the every word of the string capitalized. +/proc/capitalize_words(text) + var/list/S = splittext(text, " ") + var/list/M = list() + for (var/w in S) + M += capitalize(w) + return jointext(M, " ") + +/proc/strip_non_ascii(text) + var/static/regex/non_ascii_regex = regex(@"[^\x00-\x7F]+", "g") + return non_ascii_regex.Replace(text, "") + +/proc/strip_html_simple(t, limit = MAX_MESSAGE_LEN) + var/list/strip_chars = list("<",">") + t = copytext(t,1,limit) + for(var/char in strip_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + copytext(t, index+1) + index = findtext(t, char) + return t //This proc strips html properly, remove < > and all text between //for complete text sanitizing should be used sanitize() -/proc/strip_html_properly(var/input) +/proc/strip_html_properly(input) if(!input) return var/opentag = 1 //These store the position of < and > respectively. @@ -301,7 +351,7 @@ //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 -/proc/stringmerge(var/text,var/compare,replace = "*") +/proc/stringmerge_ascii(text, compare,replace = "*") var/newtext = text if(length(text) != length(compare)) return 0 @@ -321,7 +371,7 @@ //This proc returns the number of chars of the string that is the character //This is used for detective work to determine fingerprint completion. -/proc/stringpercent(var/text,character = "*") +/proc/stringpercent_ascii(text,character = "*") if(!text || !character) return 0 var/count = 0 @@ -331,10 +381,13 @@ count++ return count -/proc/reverse_text(var/text = "") +/proc/reverse_text(text = "") var/new_text = "" - for(var/i = length(text); i > 0; i--) - new_text += copytext(text, i, i+1) + var/bytes_length = length(text) + var/letter = "" + for(var/i = 1, i <= bytes_length, i += length(letter)) + letter = text[i] + new_text = letter + new_text return new_text //Used in preferences' SetFlavorText and human's set_flavor verb @@ -423,6 +476,7 @@ t = replacetext(t, "\[row\]", "") t = replacetext(t, "\[cell\]", "") t = replacetext(t, "\[editorbr\]", "") + t = replacetext(t, "\[iseologo\]", "") return t //pencode translation to html for tags exclusive to digital files (currently email, nanoword, report editor fields, diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 1a9c5f8eb8a..8f38ebb0a3e 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -303,7 +303,7 @@ Turf and target are seperate in case you want to teleport some distance from a t newname = input(src,"You are \a [role]. Would you like to change your name to something else?", "Name change",oldname) as text if((world.time-time_passed) > 5 MINUTES) return //took too long - newname = sanitizeName(newname, ,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters. + newname = sanitize_name(newname, ,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters. for(var/mob/living/M in global.player_list) if(M == src) continue diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index fc9120c4dfd..8d024420c4e 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -8,4 +8,4 @@ var/list/screen_loc_params = splittext(PM["screen-loc"], ",") var/list/x_data = splittext(screen_loc_params[1], ":") var/list/y_data = splittext(screen_loc_params[2], ":") - screen_loc = "LEFT+[x_data[1]]:[text2num(x_data[2])-16],BOTTOM+[y_data[1]]:[text2num(y_data[2])-16]" + screen_loc = "LEFT+[x_data[1]]:[text2num(x_data[2])-(1.5 * world.icon_size)],BOTTOM+[y_data[1]]:[text2num(y_data[2])-(1.5 * world.icon_size)]" diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index 69493131744..e61cf91fddd 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -32,6 +32,8 @@ var/global/list/radial_menus = list() closeToolTip(usr) /obj/screen/radial/slice/Click(location, control, params) + if(QDELETED(src) || QDELETED(parent)) + return if(parent && usr.client == parent.current_user) if(next_page) parent.next_page() @@ -51,6 +53,8 @@ var/global/list/radial_menus = list() icon_state = "radial_center" /obj/screen/radial/center/Click(location, control, params) + if(QDELETED(src) || QDELETED(parent)) + return if(usr.client == parent.current_user) parent.finished = TRUE @@ -274,6 +278,7 @@ var/global/list/radial_menus = list() /datum/radial_menu/proc/hide() if(current_user) current_user.images -= menu_holder + clear_vis_contents(menu_holder) /datum/radial_menu/proc/wait(atom/user, atom/anchor, require_near = FALSE, list/check_locs) while (current_user && !finished && !selected_choice) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index c653a3d34c7..504ed39436e 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -237,7 +237,7 @@ var/global/obj/screen/robot_inventory else //Modules display is hidden //R.client.screen -= robot_inventory //"store" icon - for(var/atom/A in R.module.equipment) + for(var/atom/A in R.module?.equipment) if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) ) //Module is not currently active R.client.screen -= A diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm index fb5546c5a29..9bd447bf94b 100644 --- a/code/_onclick/hud/skybox.dm +++ b/code/_onclick/hud/skybox.dm @@ -1,5 +1,4 @@ -#define SKYBOX_MAX_BOUND 736 - +var/global/const/SKYBOX_DIMENSION = 736 // Largest measurement for icon sides, used for offsets/scaling /obj/skybox name = "skybox" mouse_opacity = 0 @@ -7,13 +6,14 @@ simulated = FALSE plane = SKYBOX_PLANE blend_mode = BLEND_MULTIPLY - var/base_x_dim = 7 - var/base_y_dim = 7 - var/base_offset_x = -224 // -(world.view x dimension * world.icon_size) - var/base_offset_y = -224 // -(world.view y dimension * world.icon_size) + screen_loc = "CENTER,CENTER" + transform_animate_time = 0 + var/static/max_view_dim + var/static/const/parallax_bleed_percent = 0.2 // 20% parallax offset when going from x=1 to x=max /obj/skybox/Initialize() - screen_loc = "CENTER:[base_offset_x],CENTER:[base_offset_y]" + if(!max_view_dim) + max_view_dim = CEILING(SKYBOX_DIMENSION / world.icon_size) . = ..() /client @@ -21,36 +21,46 @@ /client/proc/set_skybox_offsets(var/x_dim, var/y_dim) if(!skybox) - update_skybox() - if(skybox) - skybox.base_x_dim = x_dim - skybox.base_y_dim = y_dim - skybox.base_offset_x = -((world.icon_size * skybox.base_x_dim)/2) - skybox.base_offset_y = -((world.icon_size * skybox.base_y_dim)/2) - - // Check if the skybox needs to be scaled to fit large displays. - var/new_max_tile_bound = max(skybox.base_x_dim, skybox.base_y_dim) - var/old_max_tile_bound = SKYBOX_MAX_BOUND/world.icon_size - if(new_max_tile_bound > old_max_tile_bound) - var/matrix/M = matrix() - M.Scale(1 + (new_max_tile_bound/old_max_tile_bound)) - skybox.transform = M - else - skybox.transform = null - update_skybox() + update_skybox(TRUE) + return + var/scale_value = 1 + if(isnum(view)) + var/target_icon_size = (view * 2 + 1) * world.icon_size + scale_value = skybox.parallax_bleed_percent + max((target_icon_size / SKYBOX_DIMENSION), 1) + skybox.screen_loc = "CENTER:-[view * world.icon_size],CENTER:-[view * world.icon_size]" + else + var/target_icon_size = max(x_dim, y_dim) * world.icon_size + scale_value = skybox.parallax_bleed_percent + max((target_icon_size / SKYBOX_DIMENSION), 1) + skybox.screen_loc = "CENTER:-[round(SKYBOX_DIMENSION * scale_value / 2)],CENTER:-[round(SKYBOX_DIMENSION * scale_value / 2)]" + skybox.set_scale(scale_value) + update_skybox() /client/proc/update_skybox(rebuild) + + var/turf/T = get_turf(eye) + if(!T) + return + if(!skybox) skybox = new() screen += skybox - rebuild = 1 - var/turf/T = get_turf(eye) - if(T) - if(rebuild) - skybox.overlays.Cut() - skybox.overlays += SSskybox.get_skybox(T.z) - screen |= skybox - skybox.screen_loc = "CENTER:[skybox.base_offset_x - T.x],CENTER:[skybox.base_offset_y - T.y]" + rebuild = TRUE + + if(rebuild) + skybox.overlays.Cut() + var/image/I = SSskybox.get_skybox(T.z) + I.appearance_flags |= PIXEL_SCALE + skybox.overlays += I + screen |= skybox + set_skybox_offsets(last_view_x_dim, last_view_y_dim) + return + + if(skybox.parallax_bleed_percent > 0) + var/matrix/M = skybox.update_transform() || matrix() + var/x_translate = -((T.x/world.maxx)-0.5) * skybox.parallax_bleed_percent * SKYBOX_DIMENSION + var/y_translate = -((T.y/world.maxy)-0.5) * skybox.parallax_bleed_percent * SKYBOX_DIMENSION + M.Translate(x_translate, y_translate) + skybox.transform = M /mob/Move() var/old_z = get_z(src) @@ -63,5 +73,3 @@ . = ..() if(. && client) client.update_skybox(old_z != get_z(src)) - -#undef SKYBOX_MAX_BOUND \ No newline at end of file diff --git a/code/controllers/subsystems/fluids.dm b/code/controllers/subsystems/fluids.dm index 71457a3d1d7..449b67ba476 100644 --- a/code/controllers/subsystems/fluids.dm +++ b/code/controllers/subsystems/fluids.dm @@ -64,6 +64,7 @@ SUBSYSTEM_DEF(fluids) if(!fluid_sources_copied_yet) fluid_sources_copied_yet = TRUE processing_sources = water_sources.Copy() + water_sources.Cut() while(processing_sources.len) @@ -73,10 +74,10 @@ SUBSYSTEM_DEF(fluids) flooded_a_neighbor = FALSE UPDATE_FLUID_BLOCKED_DIRS(current_turf) for(spread_dir in global.cardinal) - if(current_turf.fluid_blocked_dirs & spread_dir) + if(current_turf.fluid_blocked_dirs & spread_dir) continue neighbor = get_step(current_turf, spread_dir) - if(!istype(neighbor) || neighbor.flooded) + if(!istype(neighbor) || QDELETED(neighbor) || neighbor.flooded) continue UPDATE_FLUID_BLOCKED_DIRS(neighbor) if((neighbor.fluid_blocked_dirs & global.reverse_dir[spread_dir]) || !neighbor.CanFluidPass(spread_dir) || checked_targets[neighbor]) @@ -159,7 +160,7 @@ SUBSYSTEM_DEF(fluids) if(current_turf.fluid_blocked_dirs & spread_dir) continue neighbor = get_step(current_turf, spread_dir) - if(!neighbor) + if(QDELETED(neighbor)) continue UPDATE_FLUID_BLOCKED_DIRS(neighbor) coming_from = global.reverse_dir[spread_dir] @@ -192,11 +193,12 @@ SUBSYSTEM_DEF(fluids) current_fluid.last_flow_dir = 0 if (MC_TICK_CHECK) - break + break if(!holders_copied_yet) holders_copied_yet = TRUE processing_holders = holders_to_update.Copy() + holders_to_update.Cut() while(processing_holders.len) reagent_holder = processing_holders[processing_holders.len] diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index f70c8ecfba8..37c98698f50 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -397,7 +397,7 @@ SUBSYSTEM_DEF(garbage) return if(!skip_alert) - if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No") + if(UNLINT(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No")) == "No") running_find_references = null return @@ -410,15 +410,29 @@ SUBSYSTEM_DEF(garbage) testing("Beginning search for references to a [type].") last_find_references = world.time - DoSearchVar(global) //globals - for(var/datum/thing in world) //atoms (don't believe its lies) - DoSearchVar(thing, "World -> [thing]") - - for (var/datum/thing) //datums - DoSearchVar(thing, "World -> [thing]") - - for (var/client/thing) //clients - DoSearchVar(thing, "World -> [thing]") + //Yes we do actually need to do this. The searcher refuses to read weird lists + //And global.vars is a really weird list + var/list/normal_globals = list() + for(var/global_var in global.vars) + normal_globals[global_var] = global.vars[global_var] + DoSearchVar(normal_globals, "(global) -> ") //globals + testing("Finished searching globals") + + for(var/atom/atom_thing) //atoms + DoSearchVar(atom_thing, "World -> [atom_thing]") + testing("Finished searching atoms") + + for (var/datum/datum_thing) //datums + DoSearchVar(datum_thing, "World -> [datum_thing]") + testing("Finished searching datums") + +#ifndef FIND_REF_SKIP_CLIENTS + // DO NOT RUN THIS ON A LIVE SERVER + // IT WILL CRASH!!! + for (var/client/client_thing) //clients + DoSearchVar(client_thing, "World -> [client_thing]") + testing("Finished searching clients") +#endif testing("Completed search for references to a [type].") if(usr && usr.client) @@ -452,12 +466,16 @@ SUBSYSTEM_DEF(garbage) #define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref)-6) ) ) #define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST) -/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64) +/datum/proc/DoSearchVar(X, Xname, recursive_limit = 128) if(usr && usr.client && !usr.client.running_find_references) return if (!recursive_limit) return + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + if(istype(X, /datum)) var/datum/D = X if(D.last_find_references == last_find_references) @@ -467,6 +485,9 @@ SUBSYSTEM_DEF(garbage) var/list/L = D.vars for(var/varname in L) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif if (varname == "vars") continue var/variable = L[varname] @@ -475,22 +496,25 @@ SUBSYSTEM_DEF(garbage) testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") else if(islist(variable)) - DoSearchVar(variable, "[Xname] -> list", recursive_limit-1) + DoSearchVar(variable, "[Xname] -> [varname] (list)", recursive_limit-1) else if(islist(X)) var/normal = IS_NORMAL_LIST(X) for(var/I in X) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif if (I == src) testing("Found [src.type] \ref[src] in list [Xname].") - else if (I && !isnum(I) && normal && X[I] == src) - testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]") + else if (I && !isnum(I) && normal) + if(X[I] == src) + testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]") + else if(islist(X[I])) + DoSearchVar(X[I], "[Xname]\[[I]\]", recursive_limit-1) else if (islist(I)) - DoSearchVar(I, "[Xname] -> list", recursive_limit-1) - -#ifndef FIND_REF_NO_CHECK_TICK - CHECK_TICK -#endif + var/list/Xlist = X + DoSearchVar(I, "[Xname]\[[Xlist.Find(I)]\] -> list", recursive_limit-1) #endif diff --git a/code/controllers/subsystems/statistics.dm b/code/controllers/subsystems/statistics.dm index 263e9f8d7ac..c6931d5ba1e 100644 --- a/code/controllers/subsystems/statistics.dm +++ b/code/controllers/subsystems/statistics.dm @@ -146,14 +146,14 @@ SUBSYSTEM_DEF(statistics) var/datum/death/death = new var/area/placeofdeath = get_area(dead) death.place_of_death = placeofdeath ? placeofdeath.name : "Unknown area" - death.place_of_death = sanitizeSQL(death.place_of_death) - death.name = sanitizeSQL(dead.real_name) - death.key = sanitizeSQL(dead.key) - death.special_role = sanitizeSQL(dead.mind.get_special_role_name()) - death.job = sanitizeSQL(dead.mind.assigned_role) + death.place_of_death = sanitize_sql(death.place_of_death) + death.name = sanitize_sql(dead.real_name) + death.key = sanitize_sql(dead.key) + death.special_role = sanitize_sql(dead.mind.get_special_role_name()) + death.job = sanitize_sql(dead.mind.assigned_role) if(dead.last_attacker_) - death.last_attacker_name = sanitizeSQL(dead.last_attacker_.name) - death.last_attacker_key = sanitizeSQL(dead.last_attacker_.client.key) + death.last_attacker_name = sanitize_sql(dead.last_attacker_.name) + death.last_attacker_key = sanitize_sql(dead.last_attacker_.client.key) death.gender = dead.gender death.time_of_death = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") death.coords = "[dead.x], [dead.y], [dead.z]" diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm index 21adc0015f4..d4519eac6ad 100644 --- a/code/controllers/subsystems/throwing.dm +++ b/code/controllers/subsystems/throwing.dm @@ -26,8 +26,16 @@ SUBSYSTEM_DEF(throwing) var/atom/movable/AM = currentrun[currentrun.len] var/datum/thrownthing/TT = currentrun[AM] currentrun.len-- - if (QDELETED(AM) || QDELETED(TT)) - processing -= AM + if (QDELETED(AM)) + if(!QDELETED(TT)) + qdel(TT) // handles removing from processing list + if (MC_TICK_CHECK) + return + continue + if (QDELETED(TT)) + if(!QDELETED(AM)) + AM.throwing = null + processing -= AM if (MC_TICK_CHECK) return continue @@ -168,10 +176,10 @@ SUBSYSTEM_DEF(throwing) hit = TRUE thrownthing.throw_impact(A, src) break - + if(QDELETED(thrownthing)) return - + if(!hit) thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground. thrownthing.space_drift(init_dir) diff --git a/code/controllers/subsystems/timer.dm b/code/controllers/subsystems/timer.dm index c329651a5bc..d62ad0af676 100644 --- a/code/controllers/subsystems/timer.dm +++ b/code/controllers/subsystems/timer.dm @@ -259,6 +259,12 @@ SUBSYSTEM_DEF(timer) // Add all timed events from the secondary queue as well alltimers += second_queue + for (var/datum/timedevent/t as anything in alltimers) + t.bucket_joined = FALSE + t.bucket_pos = -1 + t.prev = null + t.next = null + // If there are no timers being tracked by the subsystem, // there is no need to do any further rebuilding if (!length(alltimers)) @@ -302,6 +308,7 @@ SUBSYSTEM_DEF(timer) new_bucket_count++ var/bucket_pos = BUCKET_POS(timer) timer.bucket_pos = bucket_pos + timer.bucket_joined = TRUE var/datum/timedevent/bucket_head = bucket_list[bucket_pos] if (!bucket_head) diff --git a/code/datums/composite_sounds/_composite_sound.dm b/code/datums/composite_sounds/_composite_sound.dm index bdf1301bc71..419d45e01b9 100644 --- a/code/datums/composite_sounds/_composite_sound.dm +++ b/code/datums/composite_sounds/_composite_sound.dm @@ -67,9 +67,8 @@ timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_LOOP) /datum/composite_sound/proc/play(soundfile) - var/sound/S = sound(soundfile) - for(var/atom/thing AS_ANYTHING in output_atoms) - playsound(thing, S, volume) + for(var/atom/thing as anything in output_atoms) + playsound(thing, soundfile, volume) /datum/composite_sound/proc/get_sound(starttime, _mid_sounds) . = _mid_sounds || mid_sounds diff --git a/code/datums/composite_sounds/machinery_sounds.dm b/code/datums/composite_sounds/machinery_sounds.dm index d8a261cac34..18a290e1e06 100644 --- a/code/datums/composite_sounds/machinery_sounds.dm +++ b/code/datums/composite_sounds/machinery_sounds.dm @@ -1,7 +1,15 @@ +/datum/composite_sound/deep_fryer + start_sound = 'sound/machines/fryer/deep_fryer_immerse.ogg' //my immersions + start_length = 10 + mid_sounds = list('sound/machines/fryer/deep_fryer_1.ogg' = 1, 'sound/machines/fryer/deep_fryer_2.ogg' = 1) + mid_length = 2 + end_sound = 'sound/machines/fryer/deep_fryer_emerge.ogg' + volume = 10 + /datum/composite_sound/microwave start_sound = 'sound/machines/microwave/microwave-start.ogg' start_length = 10 mid_sounds = list('sound/machines/microwave/microwave-mid1.ogg'=10, 'sound/machines/microwave/microwave-mid2.ogg'=1) mid_length = 10 end_sound = 'sound/machines/microwave/microwave-end.ogg' - volume = 1 \ No newline at end of file + volume = 10 diff --git a/code/datums/extensions/assembly/assembly.dm b/code/datums/extensions/assembly/assembly.dm index e7db4747142..9a532c435d4 100644 --- a/code/datums/extensions/assembly/assembly.dm +++ b/code/datums/extensions/assembly/assembly.dm @@ -52,7 +52,7 @@ else var/atom/movable/H = holder P.dropInto(H.loc) - if(P.type in critical_parts) + if(enabled && (P.type in critical_parts)) critical_shutdown() /datum/extension/assembly/proc/add_replace_component(var/mob/living/user, var/part_type, var/obj/item/stock_parts/P) @@ -106,6 +106,11 @@ handle_power() +/datum/extension/assembly/proc/is_critical_part(var/obj/item/stock_parts/P) + if(is_type_in_list(P, critical_parts)) + return TRUE + return FALSE + /datum/extension/assembly/proc/has_critical_parts() for(var/crit_type in critical_parts) var/found_part = FALSE diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 45bb23c33a5..a8fadf4018c 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -29,7 +29,7 @@ if(sector) var/list/neighbors_to_add = list() - for(var/obj/effect/overmap/visitable/neighbor in sector.loc) + for(var/obj/effect/overmap/visitable/neighbor in /*HEARTH EDIT START*/ range(sector.loc, 2) /*HEARTH EDIT END*/) neighbors_to_add |= neighbor var/list/neighboring_sectors = list() @@ -45,7 +45,7 @@ accessible_z_levels |= neighbor.map_z return (tz in accessible_z_levels) - + /decl/teleport/proc/can_teleport(var/atom/movable/target, var/atom/destination) if(!destination || !target?.loc) return FALSE diff --git a/code/datums/mind/mind.dm b/code/datums/mind/mind.dm index e7c9134cf0f..62f88197fb8 100644 --- a/code/datums/mind/mind.dm +++ b/code/datums/mind/mind.dm @@ -36,7 +36,6 @@ var/mob/living/original //TODO: remove.not used in any meaningful way ~Carn. First I'll need to tweak the way silicon-mobs handle minds. var/active = 0 - var/list/known_connections //list of known (RNG) relations between people var/gen_relations_info var/assigned_role @@ -47,7 +46,6 @@ var/datum/job/assigned_job var/list/datum/objective/objectives = list() - var/list/datum/objective/special_verbs = list() var/has_been_rev = 0//Tracks if this mind has been a rev or not @@ -70,9 +68,19 @@ /datum/mind/Destroy() QDEL_NULL_LIST(memories) + QDEL_NULL_LIST(objectives) + QDEL_NULL(changeling) SSticker.minds -= src . = ..() +/datum/mind/proc/handle_mob_deletion(mob/living/deleted_mob) + if (current == deleted_mob) + current.spellremove() + current = null + + if (original == deleted_mob) + original = null + /datum/mind/proc/transfer_to(mob/living/new_character) if(!istype(new_character)) to_world_log("## DEBUG: transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob. Please inform Carn") @@ -493,7 +501,6 @@ changeling = null initial_account = null objectives = list() - special_verbs = list() has_been_rev = 0 rev_cooldown = 0 brigged_since = -1 diff --git a/code/datums/movement/mob.dm b/code/datums/movement/mob.dm index 3bd328bdcb3..d31a94d6e22 100644 --- a/code/datums/movement/mob.dm +++ b/code/datums/movement/mob.dm @@ -13,12 +13,15 @@ control_object.set_dir(direction) // Death handling -/datum/movement_handler/mob/death/DoMove() - if(mob.stat != DEAD) +/datum/movement_handler/mob/death/DoMove(var/direction, var/mob/mover) + if(mob != mover || mob.stat != DEAD) return + . = MOVEMENT_HANDLED + if(!mob.client) return + mob.ghostize() // Incorporeal/Ghost movement diff --git a/code/datums/observation/dir_set.dm b/code/datums/observation/dir_set.dm index 9245e15dd1c..b4456ff0ffd 100644 --- a/code/datums/observation/dir_set.dm +++ b/code/datums/observation/dir_set.dm @@ -27,7 +27,7 @@ /atom/set_dir(ndir) var/old_dir = dir // This attempts to mimic BYOND's handling of diagonal directions and cardinal icon states. - if(!(atom_flags & ATOM_FLAG_ALLOW_DIAGONAL_FACING) && !IsPowerOfTwo(ndir)) + if((atom_flags & ATOM_FLAG_BLOCK_DIAGONAL_FACING) && !IsPowerOfTwo(ndir)) if(old_dir & ndir) ndir = old_dir else diff --git a/code/datums/observation/~cleanup.dm b/code/datums/observation/~cleanup.dm index 3c40d700aad..3610367a7cd 100644 --- a/code/datums/observation/~cleanup.dm +++ b/code/datums/observation/~cleanup.dm @@ -44,7 +44,7 @@ var/global/list/event_listen_count = list() for(var/entry in global.all_observable_events) var/decl/observ/event = entry if(event.unregister_global(listener)) - log_debug("[event] - [listener] was deleted while still registered to global events.") + log_debug("[event] ([event.type]) - [log_info_line(listener)] was deleted while still registered to global events.") if(!(--listen_count)) return @@ -56,7 +56,7 @@ var/global/list/event_listen_count = list() if(proc_owners) for(var/proc_owner in proc_owners) if(event.unregister(event_source, proc_owner)) - log_debug("[event] - [event_source] was deleted while still being listened to by [proc_owner].") + log_debug("[event] ([event.type]) - [log_info_line(event_source)] was deleted while still being listened to by [log_info_line(proc_owner)].") if(!(--source_listener_count)) return @@ -66,6 +66,6 @@ var/global/list/event_listen_count = list() var/decl/observ/event = entry for(var/event_source in event.event_sources) if(event.unregister(event_source, listener)) - log_debug("[event] - [listener] was deleted while still listening to [event_source].") + log_debug("[event] ([event.type]) - [log_info_line(listener)] was deleted while still listening to [log_info_line(event_source)].") if(!(--listener_count)) return diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index db0b321f57d..09a78eb3948 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -13,6 +13,22 @@ var/result // example: = /obj/item/chems/food/donut/normal var/time = 100 // Cooking time in deciseconds. var/result_quantity = 1 // How many items to create. Where possible, just use fewer ingredients instead. + var/coating = null // Required coating on all items in the recipe. The default value of null explitly requires no coating + // A value of -1 is permissive and cares not for any coatings + // Any typepath indicates a specific coating that should be present + // Coatings are used for batter, breadcrumbs, beer-batter, colonel's secret coating, etc + var/appliance = APPLIANCE_MIX // Which appliances this recipe can be made in. + // List of defines is in _defines/misc.dm. But for reference they are: + /* + MIX + FRYER + OVEN + SKILLET + SAUCEPAN + POT + MICROWAVE + */ + // This is a bitfield, more than one type can be used. var/const/REAGENT_REPLACE = 0 //Reagents in the ingredients are discarded (only the reagents present in the result at compiletime are used) var/const/REAGENT_MAX = 1 //The result will contain the maximum of each reagent present between the two pools. Compiletime result, and sum of ingredients @@ -32,12 +48,49 @@ /decl/recipe/Initialize() . = ..() complexity = length(reagents) + length(fruit) - var/value for(var/i in items) // add the number of items total - value = items[i] - complexity += isnum(value) ? value : 1 + if(!items[i]) + items[i] = 1 + complexity += items[i] complexity += length(uniquelist(items)) // add how many unique items there are; will prioritise burgers over 2 bunbuns and 1 wasted meat, for example +/decl/recipe/proc/get_appliances_string() + var/list/appliance_names + if(appliance & APPLIANCE_MIX) + LAZYADD(appliance_names, "a mixing bowl or plate") + if(appliance & APPLIANCE_FRYER) + LAZYADD(appliance_names, "a fryer") + if(appliance & APPLIANCE_OVEN) + LAZYADD(appliance_names, "an oven") + if(appliance & APPLIANCE_SKILLET) + LAZYADD(appliance_names, "a skillet") + if(appliance & APPLIANCE_SAUCEPAN) + LAZYADD(appliance_names, "a saucepan") + if(appliance & APPLIANCE_POT) + LAZYADD(appliance_names, "a pot") + if(appliance & APPLIANCE_MICROWAVE) + LAZYADD(appliance_names, "a microwave") + return english_list(appliance_names, and_text = " or ") + +/decl/recipe/proc/get_appliance_names() + var/list/appliance_names + if(appliance & APPLIANCE_MIX) + LAZYADD(appliance_names, "mixing bowl") + LAZYADD(appliance_names, "plate") + if(appliance & APPLIANCE_FRYER) + LAZYADD(appliance_names, "fryer") + if(appliance & APPLIANCE_OVEN) + LAZYADD(appliance_names, "oven") + if(appliance & APPLIANCE_SKILLET) + LAZYADD(appliance_names, "skillet") + if(appliance & APPLIANCE_SAUCEPAN) + LAZYADD(appliance_names, "saucepan") + if(appliance & APPLIANCE_POT) + LAZYADD(appliance_names, "pot") + if(appliance & APPLIANCE_MICROWAVE) + LAZYADD(appliance_names, "microwave") + return appliance_names + /decl/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) SHOULD_BE_PURE(TRUE) if(length(avail_reagents?.reagent_volumes) < length(reagents)) @@ -51,37 +104,43 @@ SHOULD_BE_PURE(TRUE) if(!length(fruit)) return TRUE - var/container_contents = container?.get_contained_external_atoms() + var/list/container_contents = container?.get_contained_external_atoms() if(length(container_contents) < length(fruit)) return FALSE var/list/needed_fruits = fruit.Copy() for(var/obj/item/chems/food/S in container_contents) - var/use_tag - if(istype(S, /obj/item/chems/food/grown)) - var/obj/item/chems/food/grown/G = S - if(!G.seed || !G.seed.kitchen_tag) - continue - use_tag = G.dry ? "dried [G.seed.kitchen_tag]" : G.seed.kitchen_tag - else if(istype(S, /obj/item/chems/food/fruit_slice)) - var/obj/item/chems/food/fruit_slice/FS = S - if(!FS.seed || !FS.seed.kitchen_tag) - continue - use_tag = "[FS.seed.kitchen_tag] slice" - use_tag = "[S.dry ? "dried " : ""][use_tag]" + var/list/tags = S.get_kitchen_tags() + if(!LAZYLEN(tags)) + continue + var/use_tag = tags.Join(" ") if(isnull(needed_fruits[use_tag])) continue - needed_fruits[use_tag]-- + if(check_coating(S)) + needed_fruits[use_tag]-- for(var/ktag in needed_fruits) if(needed_fruits[ktag] > 0) return FALSE return TRUE +//This is called on individual items within the container. +/decl/recipe/proc/check_coating(var/obj/item/chems/food/S) + if(!istype(S)) + return TRUE//Only snacks can be battered + + if (coating == -1) + return TRUE //-1 value doesnt care + + return S.batter_coating == coating + /decl/recipe/proc/check_items(var/obj/container) SHOULD_BE_PURE(TRUE) if(!length(items)) return TRUE var/list/container_contents = container?.get_contained_external_atoms() - if(length(container_contents) < length(items)) + var/sum = 0 + for(var/i in items) + sum += items[i] + if(length(container_contents) < sum) return FALSE var/list/needed_items = items.Copy() for(var/itype in needed_items) @@ -89,16 +148,18 @@ if(!istype(thing, itype)) continue container_contents -= thing - if(isnum(needed_items[itype])) - --needed_items[itype] - if(needed_items[itype] <= 0) - needed_items -= itype - else + if(!check_coating(thing)) + continue + needed_items[itype]-- + if(needed_items[itype] <= 0) needed_items -= itype - break + break if(!length(container_contents)) break - return !length(needed_items) + sum = 0 + for(var/i in needed_items) + sum += needed_items[i] + return !sum //general version /decl/recipe/proc/make(var/obj/container) @@ -123,14 +184,15 @@ to decide what to do. They may be used again to make another recipe or discarded, or merged into the results, thats no longer the concern of this proc */ - var/datum/reagents/buffer = new /datum/reagents(1e12, global.temp_reagents_holder)// + var/datum/reagents/buffer = new /datum/reagents(INFINITY, global.temp_reagents_holder)// var/list/container_contents = container.get_contained_external_atoms() //Find items we need - if (LAZYLEN(items)) - for (var/i in items) + for (var/i in items) + for(var/_ in 1 to items[i]) var/obj/item/I = locate(i) in container_contents if (I && I.reagents) I.reagents.trans_to_holder(buffer,I.reagents.total_volume) + container_contents -= I qdel(I) //Find fruits @@ -214,6 +276,21 @@ //If we're here, then holder is a buffer containing the total reagents for all the results. //So now we redistribute it among them var/total = holder.total_volume - for(var/atom/a AS_ANYTHING in results) - holder.trans_to(a, total / length(results)) - return results \ No newline at end of file + for (var/atom/a as anything in results) + holder.trans_to_obj(a, total / length(results)) + return results + +/proc/select_recipe(var/obj/container, var/appliance) + if(!appliance) + CRASH("Null appliance flag passed to select_recipe!") + var/highest_complexity = 0 + var/available_recipes = decls_repository.get_decls_of_subtype(/decl/recipe) + for (var/rtype in available_recipes) + var/decl/recipe/recipe = available_recipes[rtype] + if(!(appliance & recipe.appliance)) + continue + if(!recipe.check_reagents(container.reagents) || !recipe.check_items(container) || !recipe.check_fruit(container)) + continue + if(recipe.complexity >= highest_complexity) + highest_complexity = recipe.complexity + . = recipe diff --git a/code/datums/security_state.dm b/code/datums/security_state.dm index abd8e0da125..f1bbdb3ea1a 100644 --- a/code/datums/security_state.dm +++ b/code/datums/security_state.dm @@ -62,10 +62,11 @@ comm_console_security_levels = list() // Setup the list of selectable security levels available in the comm. console - for(var/security_level in all_security_levels) + for(var/decl/security_level/security_level in all_security_levels) if(security_level == highest_standard_security_level) break - comm_console_security_levels += security_level + if(security_level.selectable) + comm_console_security_levels += security_level // Now we ensure the high security level is not above the severe one (but we allow them to be equal) var/severe_index = all_security_levels.Find(severe_security_level) @@ -149,6 +150,8 @@ var/up_description var/down_description + var/selectable = TRUE + var/datum/alarm_appearance/alarm_appearance /decl/security_level/Initialize() @@ -181,8 +184,8 @@ /decl/security_level/default icon = 'icons/misc/security_state.dmi' - var/static/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg')) - var/static/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg')) + var/static/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('maps/torch/sounds/minor_alert.ogg')) + var/static/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1, new_sound = sound('maps/torch/sounds/minor_alert.ogg')) /decl/security_level/default/switching_up_to() if(up_description) @@ -293,6 +296,21 @@ alarm_icon = "alarm_normal" alarm_icon_color = PIPE_COLOR_GREEN +/decl/security_level/default/code_yellow + name = "code yellow" + icon = 'icons/misc/security_state.dmi' + + light_color_alarm = COLOR_YELLOW_GRAY + light_color_status_display = COLOR_YELLOW_GRAY + overlay_alarm = "alarm_orange" + overlay_status_display = "status_display_orange" + alarm_appearance = /datum/alarm_appearance/yellow + + up_description = "Subsector FTL Procedures are now in effect; observe modified Code Orange protocols, secure all stations for superluminal transition. EVA Ban in effect." + down_description = "Subsector FTL Procedures are now in effect; observe modified Code Orange protocols, secure all stations for superluminal transition. EVA Ban in effect." + + selectable = FALSE + /datum/alarm_appearance/blue display_icon = "status_display_lines" display_icon_color = COLOR_BLUE @@ -327,4 +345,14 @@ alarm_icon_color = COLOR_RED alarm_icon_twotone = "alarm_blinking_twotone2" - alarm_icon_twotone_color = PIPE_COLOR_YELLOW \ No newline at end of file + alarm_icon_twotone_color = PIPE_COLOR_YELLOW + +/datum/alarm_appearance/yellow + display_icon = "status_display_lines" + display_icon_color = COLOR_YELLOW_GRAY + + display_emblem = "status_display_ftl" + display_emblem_color = COLOR_WHITE + + alarm_icon = "alarm_normal" + alarm_icon_color = COLOR_YELLOW_GRAY \ No newline at end of file diff --git a/code/datums/sound_player.dm b/code/datums/sound_player.dm index ab4f31d4a6b..47b92d9fd45 100644 --- a/code/datums/sound_player.dm +++ b/code/datums/sound_player.dm @@ -80,7 +80,7 @@ */ /datum/sound_token var/atom/source // Where the sound originates from - var/list/listeners // Assoc: Atoms hearing this sound, and their sound datum + var/list/listeners // Atoms hearing this sound var/range // How many turfs away the sound will stop playing completely var/prefer_mute // If sound should be muted instead of stopped when mob moves out of range. In the general case this should be avoided because listeners will remain tracked. var/sound/sound // Sound datum, holds most sound relevant data @@ -204,7 +204,7 @@ PrivUpdateListeners() /datum/sound_token/proc/PrivAddListener(var/atom/listener) - if(!check_preference(listener)) + if(QDELETED(listener) || !check_preference(listener)) return if(isvirtualmob(listener)) @@ -259,8 +259,8 @@ for(var/listener in listeners) PrivUpdateListener(listener) -/datum/sound_token/proc/PrivUpdateListener(var/listener, var/update_sound = TRUE) - if(!check_preference(listener)) +/datum/sound_token/proc/PrivUpdateListener(var/atom/listener, var/update_sound = TRUE) + if(QDELETED(listener) || !check_preference(listener)) PrivRemoveListener(listener) return @@ -271,7 +271,7 @@ sound.status |= SOUND_UPDATE sound_to(listener, sound) -/datum/sound_token/proc/PrivGetEnvironment(var/listener) +/datum/sound_token/proc/PrivGetEnvironment(var/atom/listener) var/area/A = get_area(listener) return A && PrivIsValidEnvironment(A.sound_env) ? A.sound_env : sound.environment diff --git a/code/datums/supplypacks/dispcarts.dm b/code/datums/supplypacks/dispcarts.dm index dcaddd40fcb..10c091494c2 100644 --- a/code/datums/supplypacks/dispcarts.dm +++ b/code/datums/supplypacks/dispcarts.dm @@ -86,6 +86,3 @@ PACK(syrup_chocolate, /obj/item/chems/chem_disp_cartridge/syrup_chocolate, "Reag PACK(syrup_caramel, /obj/item/chems/chem_disp_cartridge/syrup_caramel, "Reagent refill - Caramel Syrup", "caramel syrup reagent cartridge crate") PACK(syrup_vanilla, /obj/item/chems/chem_disp_cartridge/syrup_vanilla, "Reagent refill - Vanilla Syrup", "vanilla syrup reagent cartridge crate") PACK(syrup_pumpkin, /obj/item/chems/chem_disp_cartridge/syrup_pumpkin, "Reagent refill - Pumpkin Spice Syrup", "pumpkin spice syrup reagent cartridge crate") - -#undef SEC_PACK -#undef PACK diff --git a/code/datums/supplypacks/operations.dm b/code/datums/supplypacks/operations.dm index 59e82647bbc..cb594f257ea 100644 --- a/code/datums/supplypacks/operations.dm +++ b/code/datums/supplypacks/operations.dm @@ -90,7 +90,7 @@ /obj/item/folder/red, /obj/item/folder/yellow, /obj/item/hand_labeler, - /obj/item/tape_roll, + /obj/item/ducttape, /obj/structure/filingcabinet/chestdrawer, /obj/item/paper_bin) name = "Office supplies" diff --git a/code/datums/supplypacks/supply.dm b/code/datums/supplypacks/supply.dm index 757bd1eda08..a4e8f9849b0 100644 --- a/code/datums/supplypacks/supply.dm +++ b/code/datums/supplypacks/supply.dm @@ -57,6 +57,12 @@ contains = list (/obj/item/storage/box/water = 2) containername = "bottled water crate" +/decl/hierarchy/supply_pack/supply/hand_truck + name = "Hand Truck" + contains = list(/obj/structure/hand_cart) + containertype = /obj/structure/largecrate + containername = "Hand Truck crate" + /decl/hierarchy/supply_pack/supply/sodas num_contained = 2 contains = list(/obj/item/storage/box/cola, diff --git a/code/datums/uplink/devices and tools.dm b/code/datums/uplink/devices and tools.dm index eb05d6d9a28..788163c0a5c 100644 --- a/code/datums/uplink/devices and tools.dm +++ b/code/datums/uplink/devices and tools.dm @@ -15,7 +15,7 @@ name = "Duct Tape" desc = "A roll of duct tape. changes \"HELP\" into sexy \"mmm\"." item_cost = 2 - path = /obj/item/tape_roll + path = /obj/item/ducttape /datum/uplink_item/item/tools/money name = "Operations Funding" diff --git a/code/datums/vote/custom.dm b/code/datums/vote/custom.dm index b783c749dea..ba32ded269e 100644 --- a/code/datums/vote/custom.dm +++ b/code/datums/vote/custom.dm @@ -12,7 +12,7 @@ return ..() /datum/vote/custom/setup_vote(mob/creator, automatic) - question = sanitizeSafe(input(creator,"What is the vote for?") as text|null) + question = sanitize_safe(input(creator,"What is the vote for?") as text|null) if(!question) abort = 1 return diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 3d517675a7e..db45e4380a3 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -1,12 +1,11 @@ /decl/special_role abstract_type = /decl/special_role - // Text shown when becoming this antagonist. var/list/restricted_jobs = list() // Jobs that cannot be this antagonist at roundstart (depending on config) var/list/protected_jobs = list() // As above. var/list/blocked_job_event_categories // Job event categories that blacklist a job from being this antagonist. // Jobs that can NEVER be this antagonist - var/list/blacklisted_jobs = (/datum/job/submap) + var/list/blacklisted_jobs = (/datum/job/submap) // Strings. var/welcome_text = "Cry havoc and let slip the dogs of war!" @@ -85,7 +84,7 @@ and before taking extreme actions, please try to also contact the administration! \ Think through your actions and make the roleplay immersive! Please remember all \ rules aside from those without explicit exceptions apply to antagonists." - + // Map template that antag needs to load before spawning. Nulled after it's loaded. var/datum/map_template/base_to_load @@ -104,9 +103,9 @@ if(antaghud_indicator) if(!global.hud_icon_reference) global.hud_icon_reference = list() - if(name) + if(name) global.hud_icon_reference[name] = antaghud_indicator - if(faction_name) + if(faction_name) global.hud_icon_reference[faction_name] = antaghud_indicator /decl/special_role/proc/get_antag_text(mob/recipient) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c9c7f3a672e..8542a650d98 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -580,7 +580,11 @@ its easier to just keep the beam vertical. var/matrix/M = matrix() M.Scale(icon_scale_x, icon_scale_y) M.Turn(icon_rotation) - animate(src, transform = M, transform_animate_time) + if(transform_animate_time) + animate(src, transform = M, transform_animate_time) + else + transform = M + return transform // Walks up the loc tree until it finds a loc of the given loc_type /atom/get_recursive_loc_of_type(var/loc_type) diff --git a/code/game/atoms_init.dm b/code/game/atoms_init.dm index a11aba7fa38..48db58219d9 100644 --- a/code/game/atoms_init.dm +++ b/code/game/atoms_init.dm @@ -71,6 +71,8 @@ LAZYCLEARLIST(our_overlays) LAZYCLEARLIST(priority_overlays) + LAZYCLEARLIST(climbers) + QDEL_NULL(light) if(opacity) @@ -93,7 +95,17 @@ loc.Entered(src, null) /atom/movable/Destroy() - . = ..() + // These must be done before event cleanup in the parent call + if(LAZYLEN(movement_handlers) && !ispath(movement_handlers[1])) + QDEL_NULL_LIST(movement_handlers) + + if (bound_overlay) + QDEL_NULL(bound_overlay) + + if(virtual_mob && !ispath(virtual_mob)) + qdel(virtual_mob) + virtual_mob = null + #ifdef DISABLE_DEBUG_CRASH // meh do nothing. we know what we're doing. pro engineers. #else @@ -106,12 +118,7 @@ forceMove(null) - if(LAZYLEN(movement_handlers) && !ispath(movement_handlers[1])) - QDEL_NULL_LIST(movement_handlers) - - if (bound_overlay) - QDEL_NULL(bound_overlay) + vis_locs = null //clears this atom out of all vis_contents + vis_contents.Cut() - if(virtual_mob && !ispath(virtual_mob)) - qdel(virtual_mob) - virtual_mob = null + . = ..() // called last so that events are unregistered before the parent call diff --git a/code/game/gamemodes/objectives/_objective.dm b/code/game/gamemodes/objectives/_objective.dm index c02bc4be338..ccfaea16d32 100644 --- a/code/game/gamemodes/objectives/_objective.dm +++ b/code/game/gamemodes/objectives/_objective.dm @@ -14,6 +14,8 @@ var/global/list/all_objectives = list() /datum/objective/Destroy() global.all_objectives -= src + owner = null + target = null . = ..() /datum/objective/proc/find_target() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index ec7b2849251..5fca1d98f41 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -35,7 +35,7 @@ /obj/machinery/sleeper/standard/Initialize(mapload, d, populate_parts) . = ..() - add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/stabilizer()) + add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/stabilizer()) add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/sedatives()) add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/painkillers()) add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/antitoxins()) @@ -263,7 +263,7 @@ to_chat(user, SPAN_WARNING("Unbuckle the subject before attempting to move them.")) else if(panel_open) to_chat(user, SPAN_WARNING("Close the maintenance panel before attempting to place the subject in the sleeper.")) - else + else go_in(target, user) return TRUE @@ -318,6 +318,11 @@ if(close_sound) playsound(src, close_sound, 40) +/obj/machinery/sleeper/get_contained_external_atoms() + . = ..() + LAZYREMOVE(., loaded_canisters) + LAZYREMOVE(., beaker) + /obj/machinery/sleeper/proc/go_out() if(!occupant) return @@ -329,9 +334,6 @@ if(open_sound) playsound(src, open_sound, 40) - for(var/obj/O in (contents - (component_parts + loaded_canisters))) // In case an object was dropped inside or something. Excludes the beaker and component parts. - if(O != beaker) - O.dropInto(loc) toggle_filter() /obj/machinery/sleeper/proc/set_occupant(var/mob/living/carbon/occupant) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 23f8ce81acb..2ed558621a9 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -128,7 +128,7 @@ . = ..() /obj/machinery/alarm/Destroy() - events_repository.unregister(/decl/observ/name_set, src, get_area(src), .proc/change_area_name) + events_repository.unregister(/decl/observ/name_set, get_area(src), src, .proc/change_area_name) unregister_radio(src, frequency) return ..() diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 93fe942d7a0..235be870e8a 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -222,32 +222,32 @@ return TOPIC_REFRESH if(href_list["set_input_tag"]) - var/t = sanitizeSafe(input(usr, "Enter the input ID tag.", src.name, src.input_tag), MAX_NAME_LEN) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the input ID tag.", src.name, src.input_tag), MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) src.input_tag = t set_frequency(frequency) return TOPIC_REFRESH if(href_list["set_output_tag"]) - var/t = sanitizeSafe(input(usr, "Enter the output ID tag.", src.name, src.output_tag), MAX_NAME_LEN) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the output ID tag.", src.name, src.output_tag), MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) src.output_tag = t set_frequency(frequency) return TOPIC_REFRESH if(href_list["set_sensor_tag"]) - var/t = sanitizeSafe(input(usr, "Enter the sensor ID tag.", src.name, src.sensor_tag)) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the sensor ID tag.", src.name, src.sensor_tag)) + t = sanitize_safe(t, MAX_NAME_LEN) if(t) src.sensor_tag = t set_frequency(frequency) return TOPIC_REFRESH if(href_list["set_sensor_name"]) - var/t = sanitizeSafe(input(usr, "Enter the sensor name.", src.name, src.sensor_name)) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the sensor name.", src.name, src.sensor_name)) + t = sanitize_safe(t, MAX_NAME_LEN) if(t) src.sensor_name = t return TOPIC_REFRESH diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 23a989f7785..04ab8cc6737 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -20,6 +20,7 @@ var/list/scrubbing_gas + /obj/machinery/portable_atmospherics/powered/scrubber/Initialize() . = ..() if(!scrubbing_gas) diff --git a/code/game/machinery/bodyscanner.dm b/code/game/machinery/bodyscanner.dm index 603b0571e37..1bbb5e45066 100644 --- a/code/game/machinery/bodyscanner.dm +++ b/code/game/machinery/bodyscanner.dm @@ -45,7 +45,7 @@ usr.client.eye = src /obj/machinery/bodyscanner/proc/drop_contents() - for(var/obj/O in (contents - component_parts)) + for(var/obj/O in get_contained_external_atoms()) O.dropInto(loc) /obj/machinery/bodyscanner/proc/go_out() diff --git a/code/game/machinery/bodyscanner_console.dm b/code/game/machinery/bodyscanner_console.dm index 1bd8108b490..60f5b92206e 100644 --- a/code/game/machinery/bodyscanner_console.dm +++ b/code/game/machinery/bodyscanner_console.dm @@ -1,5 +1,5 @@ /obj/machinery/body_scanconsole - var/obj/machinery/bodyscanner/connected + var/obj/machinery/bodyscanner/connected var/stored_scan_subject name = "Body Scanner Console" icon = 'icons/obj/Cryogenic2.dmi' @@ -20,7 +20,7 @@ /obj/machinery/body_scanconsole/on_update_icon() if(stat & (BROKEN | NOPOWER)) - icon_state = "body_scannerconsole-p" + icon_state = "body_scannerconsole-p" else icon_state = initial(icon_state) @@ -31,13 +31,14 @@ break events_repository.register(/decl/observ/destroyed, connected, src, .proc/unlink_scanner) -/obj/machinery/body_scanconsole/proc/unlink_scanner(var/obj/machinery/bodyscanner/scanner) +/obj/machinery/body_scanconsole/proc/unlink_scanner(var/obj/machinery/bodyscanner/scanner) events_repository.unregister(/decl/observ/destroyed, scanner, src, .proc/unlink_scanner) connected = null /obj/machinery/body_scanconsole/proc/FindDisplays() for(var/obj/machinery/body_scan_display/D in SSmachines.machinery) - if(D.tag in display_tags) + // TODO: Convert to use networking + if(D.id_tag in display_tags) connected_displays += D events_repository.register(/decl/observ/destroyed, D, src, .proc/remove_display) return !!connected_displays.len @@ -97,7 +98,7 @@ data["html_scan_header"] = display_medical_data_header(data["scan"], user.get_skill_value(SKILL_MEDICAL)) data["html_scan_health"] = display_medical_data_health(data["scan"], user.get_skill_value(SKILL_MEDICAL)) data["html_scan_body"] = display_medical_data_body(data["scan"], user.get_skill_value(SKILL_MEDICAL)) - + stored_scan_subject = connected.occupant user.visible_message("\The [user] performs a scan of \the [connected.occupant] using \the [connected].") playsound(connected.loc, 'sound/machines/medbayscanner.ogg', 50) @@ -111,7 +112,7 @@ new /obj/item/paper/bodyscan(loc, "Printout error.", "Body scan report - [stored_scan_subject]", scan.Copy()) return TOPIC_REFRESH - if(href_list["push"]) + if(href_list["push"]) if(!connected_displays.len && !FindDisplays()) to_chat(user, "[html_icon(src)]Error: No configured displays detected.") return TOPIC_REFRESH diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index cd40f066a19..f153ddc892a 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -156,7 +156,6 @@ var/mob/occupant = null // Person waiting to be despawned. var/time_till_despawn = 9000 // Down to 15 minutes //30 minutes-ish is too long var/time_entered = 0 // Used to keep track of the safe period. - var/obj/item/radio/intercom/announce // var/obj/machinery/computer/cryopod/control_computer var/last_no_computer_message = 0 @@ -185,6 +184,10 @@ var/open_sound = 'sound/machines/podopen.ogg' var/close_sound = 'sound/machines/podclose.ogg' +/obj/machinery/cryopod/get_contained_external_atoms() + . = ..() + LAZYREMOVE(., occupant) + /obj/machinery/cryopod/robot name = "robotic storage unit" desc = "A storage unit for robots." @@ -262,7 +265,6 @@ /obj/machinery/cryopod/Initialize() . = ..() - announce = new /obj/item/radio/intercom(src) find_control_computer() /obj/machinery/cryopod/proc/find_control_computer() @@ -324,7 +326,7 @@ qdel(R.mmi) for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc - for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags + for(var/obj/item/O in I.get_contained_external_atoms()) // the things inside the tools, if anything; mainly for janiborg trash bags O.forceMove(R) qdel(I) qdel(R.module) @@ -335,23 +337,18 @@ // Also make sure there is a valid control computer /obj/machinery/cryopod/proc/despawn_occupant() //Drop all items into the pod. - for(var/obj/item/W in occupant) + for(var/obj/item/W in occupant.get_equipped_items(include_carried = TRUE)) occupant.drop_from_inventory(W) W.forceMove(src) - if(W.contents.len) //Make sure we catch anything not handled by qdel() on the items. - for(var/obj/item/O in W.contents) - if(istype(O,/obj/item/storage/internal)) //Stop eating pockets, you fuck! - continue - O.forceMove(src) + //Make sure we catch anything not handled by qdel() on the items. + for(var/obj/item/O in W.get_contained_external_atoms()) + if(istype(O,/obj/item/storage/internal)) //Stop eating pockets, you fuck! + continue + O.forceMove(src) //Delete all items not on the preservation list. - var/list/items = src.contents.Copy() - items -= occupant // Don't delete the occupant - items -= announce // or the autosay radio. - items -= component_parts - - for(var/obj/item/W in items) + for(var/obj/item/W in get_contained_external_atoms()) var/preserve = null // Snowflaaaake. @@ -374,7 +371,7 @@ control_computer.frozen_items += W W.forceMove(null) else - W.forceMove(src.loc) + W.forceMove(get_turf(src)) //Update any existing objectives involving this mob. for(var/datum/objective/O in global.all_objectives) @@ -417,7 +414,8 @@ control_computer._admin_logs += "[key_name(occupant)] ([role_alt_title]) at [stationtime2text()]" log_and_message_admins("[key_name(occupant)] ([role_alt_title]) entered cryostorage.") - announce.autosay("[occupant.real_name], [role_alt_title], [on_store_message]", "[on_store_name]") + var/obj/item/radio/announcer = get_global_announcer() + announcer.autosay("[occupant.real_name], [role_alt_title], [on_store_message]", "[on_store_name]") visible_message("\The [initial(name)] hums and hisses as it moves [occupant.real_name] into storage.", range = 3) //This should guarantee that ghosts don't spawn. @@ -486,9 +484,7 @@ icon_state = base_icon_state //Eject any items that aren't meant to be in the pod. - var/list/items = contents - component_parts - if(occupant) items -= occupant - if(announce) items -= announce + var/list/items = get_contained_external_atoms() for(var/obj/item/W in items) W.dropInto(loc) diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker.dm b/code/game/machinery/kitchen/cooking_machines/_cooker.dm deleted file mode 100644 index a6fb75d8efd..00000000000 --- a/code/game/machinery/kitchen/cooking_machines/_cooker.dm +++ /dev/null @@ -1,236 +0,0 @@ -// This folder contains code that was originally ported from Apollo Station and then refactored/optimized/changed. - -// Tracks precooked food to stop deep fried baked grilled grilled grilled monkey cereal. -/obj/item/chems/food/var/list/cooked - -// Root type for cooking machines. See following files for specific implementations. -/obj/machinery/cooker - name = "cooker" - desc = "You shouldn't be seeing this!" - icon = 'icons/obj/cooking_machines.dmi' - density = 1 - anchored = 1 - idle_power_usage = 5 - construct_state = /decl/machine_construction/default/panel_closed - uncreated_component_parts = null - stat_immune = 0 - - var/on_icon // Icon state used when cooking. - var/off_icon // Icon state used when not cooking. - var/cooking // Whether or not the machine is currently operating. - var/cook_type // A string value used to track what kind of food this machine makes. - var/cook_time = 200 // How many ticks the cooking will take. - var/can_cook_mobs // Whether or not this machine accepts grabbed mobs. - var/food_color // Colour of resulting food item. - var/cooked_sound // Sound played when cooking completes. - var/can_burn_food // Can the object burn food that is left inside? - var/burn_chance = 10 // How likely is the food to burn? - var/obj/item/cooking_obj // Holder for the currently cooking object. - - // If the machine has multiple output modes, define them here. - var/selected_option - var/list/output_options = list() - -/obj/machinery/cooker/Destroy() - if(cooking_obj) - qdel(cooking_obj) - cooking_obj = null - return ..() - -/obj/machinery/cooker/examine(mob/user) - . = ..() - if(cooking_obj) - to_chat(user, "You can see \a [cooking_obj] inside.") - if(panel_open) - to_chat(user, "The panel is open.") - -/obj/machinery/cooker/components_are_accessible(path) - return !cooking && ..() - -/obj/machinery/cooker/cannot_transition_to(state_path, mob/user) - if(cooking) - return SPAN_NOTICE("Wait for \the [src] to finish first!") - return ..() - -/obj/machinery/cooker/attackby(var/obj/item/I, var/mob/user) - set waitfor = 0 //So that any remaining parts of calling proc don't have to wait for the long cooking time ahead. - - if(cooking) - to_chat(user, "\The [src] is running!") - return - - if((. = component_attackby(I, user))) - return - - if(!cook_type || (stat & (NOPOWER|BROKEN))) - to_chat(user, "\The [src] is not working.") - return - - // We are trying to cook a grabbed mob. - var/obj/item/grab/G = I - if(istype(G)) - - if(!can_cook_mobs) - to_chat(user, "That's not going to fit.") - return - - if(!isliving(G.affecting)) - to_chat(user, "You can't cook that.") - return - - cook_mob(G.affecting, user) - return - - // We're trying to cook something else. Check if it's valid. - var/obj/item/chems/food/check = I - if(istype(check) && islist(check.cooked) && (cook_type in check.cooked)) - to_chat(user, "\The [check] has already been [cook_type].") - return 0 - else if(istype(check, /obj/item/chems/glass)) - to_chat(user, "That would probably break [src].") - return 0 - else if(istype(check, /obj/item/disk/nuclear)) - to_chat(user, "Central Command would kill you if you [cook_type] that.") - return 0 - else if(!istype(check) && !istype(check, /obj/item/holder)) - to_chat(user, "That's not edible.") - return 0 - - // Gotta hurt. - if(istype(cooking_obj, /obj/item/holder)) - for(var/mob/living/M in cooking_obj.contents) - M.apply_damage(rand(30,40), BURN, BP_CHEST) - - // Not sure why a food item that passed the previous checks would fail to drop, but safety first. - if(!user.unEquip(I)) - return - - // We can actually start cooking now. - user.visible_message("\The [user] puts \the [I] into \the [src].") - cooking_obj = I - cooking_obj.forceMove(src) - cooking = 1 - icon_state = on_icon - - // Doop de doo. Jeopardy theme goes here. - sleep(cook_time) - - // Sanity checks. - if(check_cooking_obj()) - return // Cooking failed/was terminated. - - // RIP slow-moving held mobs. - if(istype(cooking_obj, /obj/item/holder)) - for(var/mob/living/M in cooking_obj.contents) - M.death() - qdel(M) - - // Cook the food. - var/cook_path - if(selected_option && output_options.len) - cook_path = output_options[selected_option] - if(!cook_path) - cook_path = /obj/item/chems/food/variable - var/obj/item/chems/food/result = new cook_path(src) //Holy typepaths, Batman. - - if(cooking_obj.reagents && cooking_obj.reagents.total_volume) - cooking_obj.reagents.trans_to(result, cooking_obj.reagents.total_volume) - - // Set icon and appearance. - change_product_appearance(result) - - // Update strings. - change_product_strings(result) - - // Set cooked data. - var/obj/item/chems/food/food_item = cooking_obj - if(istype(food_item) && islist(food_item.cooked)) - result.cooked = food_item.cooked.Copy() - else - result.cooked = list() - result.cooked |= cook_type - - // Reset relevant variables. - qdel(cooking_obj) - src.visible_message("\The [src] pings!") - if(cooked_sound) - playsound(get_turf(src), cooked_sound, 50, 1) - - if(!can_burn_food) - icon_state = off_icon - cooking = 0 - result.dropInto(loc) - cooking_obj = null - else - var/failed - var/overcook_period = max(FLOOR(cook_time/5),1) - cooking_obj = result - while(1) - sleep(overcook_period) - if(!cooking || !result || result.loc != src) - failed = 1 - else if(prob(burn_chance)) - // You dun goofed. - qdel(cooking_obj) - cooking_obj = new /obj/item/chems/food/badrecipe(src) - // Produce nasty smoke. - visible_message("\The [src] vomits a gout of rancid smoke!") - var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() - smoke.attach(src) - smoke.set_up(10, 0, usr.loc) - smoke.start() - failed = 1 - - if(failed) - cooking = 0 - icon_state = off_icon - break - -/obj/machinery/cooker/proc/check_cooking_obj() - if(!cooking_obj || cooking_obj.loc != src) - cooking_obj = null - icon_state = off_icon - cooking = 0 - return TRUE - -/obj/machinery/cooker/physical_attack_hand(var/mob/user) - if(cooking_obj) - to_chat(user, "You grab \the [cooking_obj] from \the [src].") - user.put_in_hands(cooking_obj) - cooking = 0 - cooking_obj = null - icon_state = off_icon - return TRUE - - if(output_options.len) - if(cooking) - to_chat(user, "\The [src] is in use!") - return TRUE - - var/choice = input("What specific food do you wish to make with \the [src]?") as null|anything in output_options+"Default" - if(!choice) - return TRUE - if(choice == "Default") - selected_option = null - to_chat(user, "You decide not to make anything specific with \the [src].") - else - selected_option = choice - to_chat(user, "You prepare \the [src] to make \a [selected_option].") - return TRUE - -/obj/machinery/cooker/proc/cook_mob(var/mob/living/victim, var/mob/user) - return - -/obj/machinery/cooker/proc/change_product_strings(var/obj/item/chems/food/product) - if(product.type == /obj/item/chems/food/variable) // Base type, generic. - product.SetName("[cook_type] [cooking_obj.name]") - product.desc = "[cooking_obj.desc] It has been [cook_type]." - else - product.SetName("[cooking_obj.name] [product.name]") - -/obj/machinery/cooker/proc/change_product_appearance(var/obj/item/chems/food/product) - if(istype(product)) - if(istype(cooking_obj, /obj/item/chems/food)) - var/obj/item/chems/food/S = cooking_obj - food_color = S.filling_color - product.update_food_appearance_from(cooking_obj, food_color) diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm b/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm deleted file mode 100644 index 7f279bd0561..00000000000 --- a/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm +++ /dev/null @@ -1,93 +0,0 @@ -// Wrapper obj for cooked food. Appearance is set in the cooking code, not on spawn. -/obj/item/chems/food/variable - name = "cooked food" - icon = 'icons/obj/food_custom.dmi' - desc = "If you can see this description then something is wrong. Please report the bug on the tracker." - nutriment_amt = 5 - bitesize = 2 - filling_color = COLOR_BROWN - -/obj/item/chems/food/variable/Initialize() - . = ..() - update_icon() - -/obj/item/chems/food/variable/update_food_appearance_from(var/obj/item/donor, var/food_color, var/copy_donor_appearance = TRUE) - ..(donor, food_color, (type == /obj/item/chems/food/variable)) // variable is used for generic foods (deep fried X), subtypes are used for specific foods - -/obj/item/chems/food/variable/pizza - name = "personal pizza" - desc = "A personalized pan pizza meant for only one person." - icon_state = "personal_pizza" - -/obj/item/chems/food/variable/bread - name = "bread" - desc = "Tasty bread." - icon_state = "breadcustom" - -/obj/item/chems/food/variable/pie - name = "pie" - desc = "Tasty pie." - icon_state = "piecustom" - -/obj/item/chems/food/variable/cake - name = "cake" - desc = "A popular band." - icon_state = "cakecustom" - -/obj/item/chems/food/variable/pocket - name = "hot pocket" - desc = "You wanna put a bangin- oh, nevermind." - icon_state = "donk" - filling_color = COLOR_BROWN - -/obj/item/chems/food/variable/kebab - name = "kebab" - desc = "Food is just tastier on a stick!" - icon_state = "kabob" - filling_color = COLOR_DARK_RED - -/obj/item/chems/food/variable/waffles - name = "waffles" - desc = "Made with love." - icon_state = "waffles" - gender = PLURAL - -/obj/item/chems/food/variable/pancakes - name = "pancakes" - desc = "How does an oven make pancakes?" - icon_state = "pancakescustom" - gender = PLURAL - -/obj/item/chems/food/variable/cookie - name = "cookie" - desc = "Sugar snap!" - icon_state = "cookie" - -/obj/item/chems/food/variable/donut - name = "filled donut" - desc = "Donut eat this!" // kill me - icon_state = "donut" - -/obj/item/chems/food/variable/jawbreaker - name = "flavored jawbreaker" - desc = "It's like cracking a molar on a rainbow." - icon_state = "jawbreaker" - filling_color = COLOR_RED - -/obj/item/chems/food/variable/candybar - name = "flavored chocolate bar" - desc = "Made in a factory downtown." - icon_state = "bar" - filling_color = COLOR_DARK_BROWN - -/obj/item/chems/food/variable/sucker - name = "flavored sucker" - desc = "Suck, suck, suck." - icon_state = "sucker" - filling_color = COLOR_RED - -/obj/item/chems/food/variable/jelly - name = "jelly" - desc = "All your friends will be jelly." - icon_state = "jellycustom" - filling_color = COLOR_RED diff --git a/code/game/machinery/kitchen/cooking_machines/cereal.dm b/code/game/machinery/kitchen/cooking_machines/cereal.dm deleted file mode 100644 index b5a3783ff56..00000000000 --- a/code/game/machinery/kitchen/cooking_machines/cereal.dm +++ /dev/null @@ -1,25 +0,0 @@ -/obj/machinery/cooker/cereal - name = "cereal maker" - desc = "Now with Dann O's available!" - icon = 'icons/obj/cooking_machines.dmi' - icon_state = "cereal_off" - cook_type = "cerealized" - on_icon = "cereal_on" - off_icon = "cereal_off" - -/obj/machinery/cooker/cereal/change_product_strings(var/obj/item/chems/food/product) - . = ..() - product.SetName("box of [cooking_obj.name] cereal") - -/obj/machinery/cooker/cereal/change_product_appearance(var/obj/item/chems/food/product) - product.icon = 'icons/obj/food.dmi' - product.icon_state = "cereal_box" - product.filling_color = cooking_obj.color - - var/image/food_image = image(cooking_obj.icon, cooking_obj.icon_state) - food_image.color = cooking_obj.color - food_image.overlays += cooking_obj.overlays - food_image.transform *= 0.7 - - product.overlays += food_image - diff --git a/code/game/machinery/kitchen/cooking_machines/fryer.dm b/code/game/machinery/kitchen/cooking_machines/fryer.dm deleted file mode 100644 index 0b084658b0d..00000000000 --- a/code/game/machinery/kitchen/cooking_machines/fryer.dm +++ /dev/null @@ -1,50 +0,0 @@ -/obj/machinery/cooker/fryer - name = "deep fryer" - desc = "Deep fried everything." - icon_state = "fryer_off" - can_cook_mobs = 1 - cook_type = "deep fried" - on_icon = "fryer_on" - off_icon = "fryer_off" - food_color = "#ffad33" - cooked_sound = 'sound/machines/ding.ogg' - -/obj/machinery/cooker/fryer/cook_mob(var/mob/living/victim, var/mob/user) - - if(!istype(victim)) - return - - user.visible_message("\The [user] starts pushing \the [victim] into \the [src]!") - icon_state = on_icon - cooking = 1 - - if(!do_mob(user, victim, 20)) - cooking = 0 - icon_state = off_icon - return - - if(!victim || !victim.Adjacent(user)) - to_chat(user, "Your victim slipped free!") - cooking = 0 - icon_state = off_icon - return - - var/target_zone = user.zone_sel.selecting - if(ishuman(victim) && !(target_zone in list(BP_GROIN, BP_CHEST))) - var/mob/living/carbon/human/H = victim - var/obj/item/organ/external/E = H.get_organ(target_zone) - if(!E) - to_chat(user, "They are missing that body part!") - else - visible_message("\The [user] shoves \the [victim][E ? "'s [E.name]" : ""] into \the [src]!") - H.apply_damage(rand(20,30), BURN, target_zone) - - else - victim.apply_damage(rand(30,40), BURN) - - if(victim) - admin_attack_log(user, victim, "Has [cook_type] their victim in \a [src]", "Has been [cook_type] in \a [src] by the attacker.", "[cook_type], in \a [src], ") - - icon_state = off_icon - cooking = 0 - return diff --git a/code/game/machinery/kitchen/cooking_machines/grill.dm b/code/game/machinery/kitchen/cooking_machines/grill.dm deleted file mode 100644 index b4f83c56adb..00000000000 --- a/code/game/machinery/kitchen/cooking_machines/grill.dm +++ /dev/null @@ -1,10 +0,0 @@ -/obj/machinery/cooker/grill - name = "griddle" - desc = "A flat, wide, and smooth cooking surface." - icon_state = "grill_off" - cook_type = "grilled" - cook_time = 100 - food_color = "#a34719" - on_icon = "grill_on" - off_icon = "grill_off" - can_burn_food = 1 \ No newline at end of file diff --git a/code/game/machinery/kitchen/cooking_machines/oven.dm b/code/game/machinery/kitchen/cooking_machines/oven.dm deleted file mode 100644 index 5eb89e361d6..00000000000 --- a/code/game/machinery/kitchen/cooking_machines/oven.dm +++ /dev/null @@ -1,24 +0,0 @@ -/obj/machinery/cooker/oven - name = "oven" - desc = "Cookies are ready, dear." - icon = 'icons/obj/cooking_machines.dmi' - icon_state = "oven_off" - on_icon = "oven_on" - off_icon = "oven_off" - cook_type = "baked" - cook_time = 300 - food_color = "#a34719" - can_burn_food = 1 - - output_options = list( - "Personal Pizza" = /obj/item/chems/food/variable/pizza, - "Bread" = /obj/item/chems/food/variable/bread, - "Pie" = /obj/item/chems/food/variable/pie, - "Small Cake" = /obj/item/chems/food/variable/cake, - "Hot Pocket" = /obj/item/chems/food/variable/pocket, - "Kebab" = /obj/item/chems/food/variable/kebab, - "Waffles" = /obj/item/chems/food/variable/waffles, - "Pancakes" = /obj/item/chems/food/variable/pancakes, - "Cookie" = /obj/item/chems/food/variable/cookie, - "Donut" = /obj/item/chems/food/variable/donut, - ) \ No newline at end of file diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index a3250bc212f..41c17e1f14d 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -143,7 +143,7 @@ /obj/machinery/gibber/proc/go_out() if(operating || !src.occupant) return - for(var/obj/O in (contents - component_parts)) + for(var/obj/O in get_contained_external_atoms()) O.dropInto(loc) if (src.occupant.client) src.occupant.client.eye = src.occupant.client.mob @@ -211,7 +211,7 @@ qdel(occupant) playsound(loc, 'sound/effects/splat.ogg', 50, 1) - for (var/obj/thing in (contents - component_parts)) + for (var/obj/thing in get_contained_external_atoms()) // There's a chance that the gibber will fail to destroy some evidence. if(istype(thing,/obj/item/organ) && prob(80)) qdel(thing) diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index 7cc2c4100c3..d1d05e87fac 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -202,17 +202,6 @@ /*********************************** * Microwave Menu Handling/Cooking ************************************/ -/obj/machinery/microwave/proc/select_recipe() - var/list/all_recipes = decls_repository.get_decls_of_subtype(/decl/recipe) - var/highest_count = 0 - for(var/rtype in all_recipes) - var/decl/recipe/recipe = all_recipes[rtype] - if(!istype(recipe) || !recipe.check_reagents(reagents) || !recipe.check_items(src) || !recipe.check_fruit(src)) - continue - //okay, let's select the most complicated recipe - if(recipe.complexity >= highest_count) - highest_count = recipe.complexity - . = recipe /obj/machinery/microwave/proc/cook() cook_break = FALSE @@ -228,7 +217,7 @@ if (reagents.total_volume && prob(50)) // 50% chance a liquid recipe gets messy dirty += CEILING(reagents.total_volume / 10) - var/decl/recipe/recipe = select_recipe() + var/decl/recipe/recipe = select_recipe(src, APPLIANCE_MICROWAVE) if (!recipe) failed = TRUE cook_time = update_cook_time() @@ -249,21 +238,21 @@ return (ct / cooking_power) /obj/machinery/microwave/proc/finish_cooking() - var/decl/recipe/recipe = select_recipe() + var/decl/recipe/recipe = select_recipe(src, APPLIANCE_MICROWAVE) if(!recipe) return - var/result = recipe.result + var/decl/recipe/oldrecipe = recipe var/list/cooked_items = list() while(recipe) cooked_items += recipe.make_food(src) - recipe = select_recipe() - if (!recipe || (recipe.result != result)) + recipe = select_recipe(src, APPLIANCE_MICROWAVE) + if (!recipe || recipe != oldrecipe) break //Any leftover reagents are divided amongst the foods var/total = reagents.total_volume for (var/obj/item/I in cooked_items) - reagents.trans_to_holder(I.reagents, total/cooked_items.len) + reagents.trans_to_obj(I, total/cooked_items.len) I.dropInto(loc) // since eject only ejects ingredients! dispose(message = FALSE) //clear out anything left diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 30fb38ec304..ab0a95dfe61 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -457,7 +457,7 @@ var/global/list/allCasters = list() //Global list that will contain reference to if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(src.loc))) || (istype(usr, /mob/living/silicon))) usr.set_machine(src) if(href_list["set_channel_name"]) - src.channel_name = sanitizeSafe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""), MAX_LNAME_LEN) + src.channel_name = sanitize_safe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""), MAX_LNAME_LEN) src.updateUsrDialog() //src.update_icon() @@ -560,7 +560,7 @@ var/global/list/allCasters = list() //Global list that will contain reference to src.updateUsrDialog() else if(href_list["set_wanted_name"]) - src.channel_name = sanitizeSafe(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""), MAX_LNAME_LEN) + src.channel_name = sanitize_safe(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""), MAX_LNAME_LEN) src.updateUsrDialog() else if(href_list["set_wanted_desc"]) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 45655481ebb..0bdec2de426 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -798,7 +798,7 @@ var/global/list/turret_icons return if(istype(I, /obj/item/pen)) //you can rename turrets like bots! - var/t = sanitizeSafe(input(user, "Enter new turret name", name, finish_name) as text, MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter new turret name", name, finish_name) as text, MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && loc != usr) diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 5e872f38fa0..ba008a04f7d 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -50,11 +50,6 @@ return return MCS_BLOCK -/obj/machinery/telecomms/dismantle() - for(var/obj/x in (contents - component_parts)) - x.dropInto(loc) - . = ..() - // This should all be a multitool extension, but outside the scope of current rework. /obj/machinery/telecomms/CanUseTopic(mob/user) // You need a multitool to use this, or be silicon @@ -135,7 +130,7 @@ dat += "" temp = "" - + var/datum/browser/written_digital/popup = new(user, "tcommmachine", "Telecommunications Machine Configuration Panel", 520, 600) popup.set_content(JOINTEXT(dat)) popup.open() diff --git a/code/game/machinery/vending/engineering.dm b/code/game/machinery/vending/engineering.dm index 18d7cd188a9..d09812099b9 100644 --- a/code/game/machinery/vending/engineering.dm +++ b/code/game/machinery/vending/engineering.dm @@ -18,7 +18,7 @@ /obj/item/screwdriver = 5, /obj/item/flashlight/flare/glowstick = 3, /obj/item/flashlight/flare/glowstick/red = 3, - /obj/item/tape_roll = 8, + /obj/item/ducttape = 8, /obj/item/clothing/gloves/insulated/cheap = 2 ) contraband = list( diff --git a/code/game/machinery/vending/medical.dm b/code/game/machinery/vending/medical.dm index 7a8453e181a..7b278bad927 100644 --- a/code/game/machinery/vending/medical.dm +++ b/code/game/machinery/vending/medical.dm @@ -41,6 +41,7 @@ icon_deny = "wallmed-deny" icon_vend = "wallmed-vend" base_type = /obj/machinery/vending/wallmed1 + markup = 0 density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude products = list( /obj/item/stack/medical/bruise_pack = 3, @@ -60,6 +61,7 @@ icon_state = "wallmed" icon_deny = "wallmed-deny" icon_vend = "wallmed-vend" + markup = 0 density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude base_type = /obj/machinery/vending/wallmed2 products = list( diff --git a/code/game/machinery/vending/misc.dm b/code/game/machinery/vending/misc.dm index c3cef8d3b58..2294deedf10 100644 --- a/code/game/machinery/vending/misc.dm +++ b/code/game/machinery/vending/misc.dm @@ -26,7 +26,16 @@ markup = 0 base_type = /obj/machinery/vending/dinnerware products = list( - /obj/item/chems/glass/beaker/bowl =2, + /obj/item/chems/cooking_container/plate/bowl = 4, + /obj/item/chems/cooking_container/plate = 4, + /obj/item/chems/cooking_container/fryer = 4, + /obj/item/chems/cooking_container/oven = 4, + /obj/item/chems/cooking_container/pot = 4, + /obj/item/chems/cooking_container/saucepan = 4, + /obj/item/chems/cooking_container/skillet = 4, + /obj/item/kitchen/utensil/fork = 4, + /obj/item/kitchen/utensil/spoon = 4, + /obj/item/chems/glass/beaker/measuringcup = 4, /obj/item/storage/tray/metal/aluminium = 8, /obj/item/knife/kitchen = 3, /obj/item/kitchen/rollingpin = 2, diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 07c1a3c3ccf..ac233842fca 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -67,7 +67,7 @@ addtimer(CALLBACK(src, /obj/machinery/washing_machine/proc/wash), 20 SECONDS) /obj/machinery/washing_machine/proc/wash() - for(var/atom/A in (contents - component_parts)) + for(var/atom/A in get_contained_external_atoms()) if(detergent) A.clean_blood() if(isitem(A)) @@ -200,7 +200,7 @@ var/mob/M = locate(/mob/living) in src if(M) M.gib() - for(var/atom/movable/O in (contents - component_parts)) + for(var/atom/movable/O in get_contained_external_atoms()) O.dropInto(loc) state &= ~WASHER_STATE_FULL update_icon() diff --git a/code/game/movietitles.dm b/code/game/movietitles.dm index a603643b1dc..9f37d5e716c 100644 --- a/code/game/movietitles.dm +++ b/code/game/movietitles.dm @@ -88,7 +88,7 @@ var/global/list/end_titles var/client/P = parent if(parent) P.screen -= src - LAZYREMOVE(P.credits, src) + LAZYREMOVE(P?.credits, src) parent = null return ..() diff --git a/code/game/objects/effects/fluids.dm b/code/game/objects/effects/fluids.dm index 7a61d705e33..8341a5ed934 100644 --- a/code/game/objects/effects/fluids.dm +++ b/code/game/objects/effects/fluids.dm @@ -37,7 +37,7 @@ ADD_ACTIVE_FLUID(src) for(var/checkdir in global.cardinal) var/obj/effect/fluid/F = locate() in get_step(loc, checkdir) - if(F) + if(!QDELETED(F)) ADD_ACTIVE_FLUID(F) update_lighting = TRUE update_icon() @@ -46,7 +46,7 @@ var/turf/simulated/T = get_turf(src) for(var/checkdir in global.cardinal) var/obj/effect/fluid/F = locate() in get_step(T, checkdir) - if(F) + if(!QDELETED(F)) ADD_ACTIVE_FLUID(F) REMOVE_ACTIVE_FLUID(src) SSfluids.pending_flows -= src diff --git a/code/game/objects/item.dm b/code/game/objects/item.dm index 289cf8a73f0..10ee1a26476 100644 --- a/code/game/objects/item.dm +++ b/code/game/objects/item.dm @@ -131,6 +131,8 @@ STOP_PROCESSING(SSobj, src) QDEL_NULL(hidden_uplink) + QDEL_NULL(coating) + if(ismob(loc)) var/mob/M = loc @@ -140,10 +142,11 @@ LAZYREMOVE(organ.implants, src) M.drop_from_inventory(src) + // TODO: CONVERT TO USE OBSERVATIONS var/obj/item/storage/storage = loc if(istype(storage)) // some ui cleanup needs to be done - storage.on_item_pre_deletion(src) // must be done before deletion + storage.on_item_pre_deletion(src) // must be done before deletion // TODO: ADD PRE_DELETION OBSERVATION . = ..() storage.on_item_post_deletion(src) // must be done after deletion else diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index b01b245ded0..cb99a477dd2 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -49,7 +49,7 @@ return if (!in_range(src, user) && src.loc != user) return - t = sanitizeSafe(t, MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) src.SetName("body bag - ") src.name += t diff --git a/code/game/objects/items/books/_book.dm b/code/game/objects/items/books/_book.dm index dd0c5921c13..4652e19a142 100644 --- a/code/game/objects/items/books/_book.dm +++ b/code/game/objects/items/books/_book.dm @@ -75,7 +75,7 @@ var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel") switch(choice) if("Title") - var/newtitle = reject_bad_text(sanitizeSafe(input("Write a new title:"))) + var/newtitle = reject_bad_text(sanitize_safe(input("Write a new title:"))) if(!newtitle) to_chat(usr, "The title is invalid.") return diff --git a/code/game/objects/items/books/skill_book.dm b/code/game/objects/items/books/skill_book.dm index c49dc07331b..c9b67b52726 100644 --- a/code/game/objects/items/books/skill_book.dm +++ b/code/game/objects/items/books/skill_book.dm @@ -734,7 +734,7 @@ MEDICAL return FALSE /obj/item/book/skill/custom/proc/edit_title(var/obj/item/pen, var/mob/user) - var/newtitle = reject_bad_text(sanitizeSafe(input(user, "Write a new title:"))) + var/newtitle = reject_bad_text(sanitize_safe(input(user, "Write a new title:"))) if(!can_write(pen,user)) return if(!newtitle) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 96039634a2a..e0cdb252330 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -229,6 +229,9 @@ if(.) SSnano.update_uis(src) +/mob/announcer // used only for autosay + simulated = FALSE + /obj/item/radio/proc/autosay(var/message, var/from, var/channel, var/sayverb = "states") //BS12 EDIT var/datum/radio_frequency/connection = null if(channel && channels && channels.len > 0) @@ -240,7 +243,7 @@ channel = null if (!istype(connection)) return - var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(src, null, null, 1) + var/mob/announcer/A = new() A.fully_replace_character_name(from) talk_into(A, message, channel, sayverb) qdel(A) @@ -344,7 +347,7 @@ jobname = "No id" // --- AI --- - else if (isAI(M)) + else if (isAI(M) || istype(M, /mob/announcer)) jobname = ASSIGNMENT_COMPUTER // --- Cyborg --- @@ -818,7 +821,7 @@ /obj/item/radio/phone/medbay frequency = MED_I_FREQ - + /obj/item/radio/phone/medbay/Initialize() . = ..() internal_channels = global.default_medbay_channels.Copy() diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 18d0b84c917..0487e0c630e 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -454,7 +454,7 @@ if(loc == user) var/new_name = input(user, "What would you like to label the tape?", "Tape labeling") as null|text if(isnull(new_name)) return - new_name = sanitizeSafe(new_name) + new_name = sanitize_safe(new_name) if(new_name) SetName("tape - '[new_name]'") to_chat(user, "You label the tape '[new_name]'.") diff --git a/code/game/objects/items/robot/robot_frame.dm b/code/game/objects/items/robot/robot_frame.dm index 0ca8db0428c..34cd2723f1c 100644 --- a/code/game/objects/items/robot/robot_frame.dm +++ b/code/game/objects/items/robot/robot_frame.dm @@ -138,7 +138,7 @@ qdel(src) else if(istype(W, /obj/item/pen)) - var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN) if(t && (in_range(src, user) || loc == user)) created_name = t else diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index c264c004195..6220bb4f6e5 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -71,7 +71,7 @@ var/heldname = "default name" /obj/item/borg/upgrade/rename/attack_self(mob/user) - heldname = sanitizeSafe(input(user, "Enter new robot name", "Robot Reclassification", heldname), MAX_NAME_LEN) + heldname = sanitize_safe(input(user, "Enter new robot name", "Robot Reclassification", heldname), MAX_NAME_LEN) /obj/item/borg/upgrade/rename/action(var/mob/living/silicon/robot/R) if(..()) return 0 diff --git a/code/game/objects/items/spirit_board.dm b/code/game/objects/items/spirit_board.dm index 229435b0bcb..b55b5731e94 100644 --- a/code/game/objects/items/spirit_board.dm +++ b/code/game/objects/items/spirit_board.dm @@ -9,7 +9,7 @@ var/lastuser = null /obj/item/spirit_board/examine(mob/user) - ..() + . = ..() to_chat(user, "The planchette is sitting at \"[planchette]\".") /obj/item/spirit_board/attack_hand(mob/user) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 4108969fc3c..e4a7e7d4612 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -70,7 +70,7 @@ use(2) return - if (istype(W, /obj/item/tape_roll)) + if (istype(W, /obj/item/ducttape)) var/obj/item/stack/medical/splint/ghetto/new_splint = new(user.loc) new_splint.dropInto(loc) new_splint.add_fingerprint(user) diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 1a18081f94f..1617f2e0543 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -39,7 +39,7 @@ if(signed_by) to_chat(user, SPAN_WARNING("\The [src] has already been signed.")) else - var/signature = sanitizeSafe(input("What do you want to sign the card as?", "Union Card") as text, MAX_NAME_LEN) + var/signature = sanitize_safe(input("What do you want to sign the card as?", "Union Card") as text, MAX_NAME_LEN) if(signature && !signed_by && !user.incapacitated() && Adjacent(user)) signed_by = signature user.visible_message(SPAN_NOTICE("\The [user] signs \the [src] with a flourish.")) diff --git a/code/game/objects/items/weapons/cards_ids_syndicate.dm b/code/game/objects/items/weapons/cards_ids_syndicate.dm index 351db1c3965..3b1bd79d618 100644 --- a/code/game/objects/items/weapons/cards_ids_syndicate.dm +++ b/code/game/objects/items/weapons/cards_ids_syndicate.dm @@ -110,13 +110,13 @@ to_chat(user, "Age has been set to '[age]'.") . = 1 if("Prefix") - var/new_prefix = sanitizeSafe(input(user,"What title prefix would you like to put on this card?","Agent Card Prefix", age) as text, MAX_NAME_LEN) + var/new_prefix = sanitize_safe(input(user,"What title prefix would you like to put on this card?","Agent Card Prefix", age) as text, MAX_NAME_LEN) if(!isnull(new_prefix) && CanUseTopic(user, state)) formal_name_prefix = new_prefix to_chat(user, "Title prefix has been set to '[formal_name_prefix]'.") . = 1 if("Suffix") - var/new_suffix = sanitizeSafe(input(user,"What title suffix would you like to put on this card?","Agent Card Suffix", age) as text, MAX_NAME_LEN) + var/new_suffix = sanitize_safe(input(user,"What title suffix would you like to put on this card?","Agent Card Suffix", age) as text, MAX_NAME_LEN) if(!isnull(new_suffix) && CanUseTopic(user, state)) formal_name_suffix = new_suffix to_chat(user, "Title suffix has been set to '[formal_name_suffix]'.") @@ -172,7 +172,7 @@ to_chat(user, "Fingerprint hash changed to '[new_fingerprint_hash]'.") . = 1 if("Name") - var/new_name = sanitizeName(input(user,"What name would you like to put on this card?","Agent Card Name", registered_name) as null|text, allow_numbers=TRUE) + var/new_name = sanitize_name(input(user,"What name would you like to put on this card?","Agent Card Name", registered_name) as null|text, allow_numbers=TRUE) if(!isnull(new_name) && CanUseTopic(user, state)) src.registered_name = new_name to_chat(user, "Name changed to '[new_name]'.") diff --git a/code/game/objects/items/weapons/circuitboards/machinery/household.dm b/code/game/objects/items/weapons/circuitboards/machinery/household.dm index 3762cb31248..1796c4007f5 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/household.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/household.dm @@ -27,15 +27,17 @@ /obj/item/stock_parts/power/apc/buildable = 1 ) -/obj/item/stock_parts/circuitboard/cooker - name = "circuitboard (candy machine)" - build_path = /obj/machinery/cooker/candy +// HEARTH OF HESTIA EDIT +/obj/item/stock_parts/circuitboard/appliance + name = "circuitboard (kitchen appliance)" + build_path = /obj/machinery/appliance/mixer/candy board_type = "machine" origin_tech = "{'biotech':1,'materials':1}" buildtype_select = TRUE req_components = list( - /obj/item/stock_parts/manipulator = 2, - /obj/item/stock_parts/matter_bin = 1, + /obj/item/stock_parts/capacitor = 3, + /obj/item/stock_parts/scanning_module = 1, + /obj/item/stock_parts/matter_bin = 2, /obj/item/stack/cable_coil = 10) additional_spawn_components = list( /obj/item/stock_parts/console_screen = 1, @@ -43,8 +45,10 @@ /obj/item/stock_parts/power/apc/buildable = 1 ) -/obj/item/stock_parts/circuitboard/cooker/get_buildable_types() - return subtypesof(/obj/machinery/cooker) +/obj/item/stock_parts/circuitboard/appliance/get_buildable_types() + return subtypesof(/obj/machinery/appliance/cooker) + subtypesof(/obj/machinery/appliance/mixer) + +// END HEARTH OF HESTIA EDIT /obj/item/stock_parts/circuitboard/honey name = "circuitboard (honey extractor)" diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 281e00e9ecc..b3dda7746fb 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -14,6 +14,11 @@ var/list/allowed_containers = list(/obj/item/chems/glass/beaker, /obj/item/chems/glass/bottle) var/affected_area = 3 +/obj/item/grenade/chem_grenade/Destroy() + QDEL_NULL(detonator) + QDEL_NULL_LIST(beakers) + . = ..() + /obj/item/grenade/chem_grenade/Initialize() . = ..() create_reagents(1000) @@ -112,7 +117,7 @@ update_icon() /obj/item/grenade/chem_grenade/activate(mob/user) - if(active) + if(active) return if(detonator) if(!isigniter(detonator.a_left)) @@ -127,12 +132,12 @@ /obj/item/grenade/chem_grenade/detonate() set waitfor = 0 - if(!stage || stage < 2) + if(!stage || stage < 2) return var/has_reagents = 0 for(var/obj/item/chems/glass/G in beakers) - if(G.reagents.total_volume) + if(G.reagents.total_volume) has_reagents = TRUE break @@ -162,7 +167,7 @@ set_invisibility(INVISIBILITY_MAXIMUM) // Visual effect to show the grenade going off. - if(reagents.total_volume) + if(reagents.total_volume) var/datum/effect/effect/system/steam_spread/steam = new steam.set_up(10, 0, get_turf(src)) steam.attach(src) diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index bda5fb96f1d..964674d2738 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -46,7 +46,7 @@ return if((!in_range(src, usr) && loc != user)) return - t = sanitizeSafe(t, MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if(t) SetName("glass case - '[t]'") desc = "A case containing \a [t] implant." diff --git a/code/game/objects/items/weapons/material/swiss.dm b/code/game/objects/items/weapons/material/swiss.dm index f1605a45e62..0ee0bedabbe 100644 --- a/code/game/objects/items/weapons/material/swiss.dm +++ b/code/game/objects/items/weapons/material/swiss.dm @@ -49,9 +49,9 @@ /obj/item/knife/folding/swiss/get_tool_quality(archetype) . = (archetype == get_tool_archetype()) ? ..() : 0 - + /obj/item/knife/folding/swiss/attack_self(mob/user) - var/choice + var/choice if(user.a_intent != I_HELP && ((SWISSKNF_LBLADE in tools) || (SWISSKNF_SBLADE in tools)) && active_tool == SWISSKNF_CLOSED) open = TRUE if(SWISSKNF_LBLADE in tools) @@ -64,7 +64,7 @@ else choice = SWISSKNF_CLOSED open = FALSE - + if(!choice || !CanPhysicallyInteract(user)) return if(choice == SWISSKNF_CLOSED) @@ -77,7 +77,7 @@ playsound(user, 'sound/weapons/flipblade.ogg', 15, 1) else user.visible_message("\The [user] opens the [lowertext(choice)].") - + active_tool = choice update_force() update_icon() @@ -108,7 +108,7 @@ /obj/item/knife/folding/swiss/on_update_icon() ..() if(active_tool != null) - overlays += overlay_image(icon, active_tool) + add_overlay(overlay_image(icon, active_tool)) /obj/item/knife/folding/swiss/get_mob_overlay(mob/user_mob, slot, bodypart) . = (active_tool == SWISSKNF_LBLADE || active_tool == SWISSKNF_SBLADE) ? ..() : new /image diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index cca5951971e..eeab7c82918 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -266,9 +266,9 @@ /obj/item/radio/headset, /obj/item/megaphone, /obj/item/taperoll, + /obj/item/magnetic_tape, /obj/item/holowarrant, /obj/item/radio, - /obj/item/tape, /obj/item/pen, /obj/item/stamp, /obj/item/stack/package_wrap, @@ -311,6 +311,8 @@ /obj/item/flash, /obj/item/telebaton, /obj/item/taperecorder, + /obj/item/magnetic_tape, + /obj/item/taperoll, /obj/item/folder, /obj/item/paper, /obj/item/clipboard, @@ -320,10 +322,8 @@ /obj/item/modular_computer/pda, /obj/item/radio/headset, /obj/item/megaphone, - /obj/item/taperoll, /obj/item/holowarrant, /obj/item/radio, - /obj/item/tape, /obj/item/pen, /obj/item/stamp, /obj/item/stack/package_wrap, @@ -352,16 +352,14 @@ /obj/item/forensics/sample/print, /obj/item/forensics/sample/fibers, /obj/item/taperecorder, - /obj/item/tape, + /obj/item/magnetic_tape, /obj/item/clothing/gloves/latex, /obj/item/clothing/gloves/forensic, /obj/item/folder, /obj/item/paper, /obj/item/forensics/sample_kit, - /obj/item/camera, - /obj/item/taperecorder, - /obj/item/tape - ) + /obj/item/camera + ) /obj/item/storage/belt/holster/machete name = "machete belt" @@ -387,9 +385,9 @@ /obj/item/radio/beacon, /obj/item/pinpointer/radio, /obj/item/taperecorder, - /obj/item/tape, + /obj/item/magnetic_tape, /obj/item/scanner/gas - ) + ) can_holster = list(/obj/item/hatchet/machete) sound_in = 'sound/effects/holster/sheathin.ogg' sound_out = 'sound/effects/holster/sheathout.ogg' diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 741361d5696..4a0dda00b01 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -108,7 +108,7 @@ set desc = "Click to rename your bible." if(!renamed) - var/input = sanitizeSafe(input("What do you want to rename your bible to? You can only do this once.", ,""), MAX_NAME_LEN) + var/input = sanitize_safe(input("What do you want to rename your bible to? You can only do this once.", ,""), MAX_NAME_LEN) var/mob/M = usr if(src && input && !M.stat && in_range(M,src)) diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index dfd5709968c..dfc32c4a9b5 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -1,18 +1,18 @@ -/obj/item/tape_roll +/obj/item/ducttape name = "duct tape" desc = "A roll of sticky tape. Possibly for taping ducks... or was that ducts?" icon = 'icons/obj/bureaucracy.dmi' icon_state = "taperoll" w_class = ITEM_SIZE_SMALL -/obj/item/tape_roll/Initialize() +/obj/item/ducttape/Initialize() . = ..() set_extension(src, /datum/extension/tool, list( TOOL_BONE_GEL = TOOL_QUALITY_MEDIOCRE, TOOL_SUTURES = TOOL_QUALITY_BAD )) -/obj/item/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user) +/obj/item/ducttape/attack(var/mob/living/carbon/human/H, var/mob/user) if(istype(H)) if(user.zone_sel.selecting == BP_EYES) @@ -83,7 +83,7 @@ return ..() return 1 -/obj/item/tape_roll/proc/stick(var/obj/item/W, mob/user) +/obj/item/ducttape/proc/stick(var/obj/item/W, mob/user) if(!istype(W, /obj/item/paper) || istype(W, /obj/item/paper/sticky) || !user.unEquip(W)) return var/obj/item/ducttape/tape = new(get_turf(src)) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index d219d4506d4..4e483267f42 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -131,7 +131,7 @@ /obj/item/storage/belt/utility = 2, /obj/item/storage/belt/utility/atmostech = 1, /obj/random/tool = 5, - /obj/item/tape_roll = 2) + /obj/item/ducttape = 2) /obj/random/medical name = "Random Medical equipment" diff --git a/code/game/objects/structures/bookcase.dm b/code/game/objects/structures/bookcase.dm index 6a465b62d40..311ec958699 100644 --- a/code/game/objects/structures/bookcase.dm +++ b/code/game/objects/structures/bookcase.dm @@ -34,7 +34,7 @@ var/global/list/station_bookcases = list() if(istype(O, /obj/item/book) && user.unEquip(O, src)) update_icon() else if(istype(O, /obj/item/pen)) - var/newname = sanitizeSafe(input("What would you like to title this bookshelf?"), MAX_NAME_LEN) + var/newname = sanitize_safe(input("What would you like to title this bookshelf?"), MAX_NAME_LEN) if(!newname) return else diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index a0e6e655ab8..daaceef5817 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -186,9 +186,9 @@ C.plated_tile += GET_DECL(plating_type) C.name = "plated catwalk" C.update_icon() - activated = 1 + activated = TRUE for(var/turf/T in orange(src, 1)) - for(var/obj/effect/wallframe_spawn/other in T) + for(var/obj/effect/catwalk_plated/other in T) if(!other.activated) other.activate() /obj/effect/catwalk_plated/dark diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index 8387fba6890..8a44ed80ff0 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -20,15 +20,17 @@ closet_appearance = /decl/closet_appearance/oxygen /obj/structure/closet/emcloset/WillContain() - //Guaranteed kit - two tanks and masks - . = list(/obj/item/tank/emergency/oxygen = 2, - /obj/item/clothing/mask/breath = 2) + //Guaranteed kit - two tanks, two masks, two O2 pouches, and a softsuit + . = list(/obj/item/tank/emergency/oxygen/engi = 2, + /obj/item/clothing/mask/breath = 2, + /obj/item/storage/med_pouch/oxyloss = 2, + /obj/item/clothing/suit/space/emergency, + /obj/item/clothing/head/helmet/space/emergency) . += new/datum/atom_creator/simple(list(/obj/item/storage/toolbox/emergency, /obj/item/inflatable/wall = 2), 75) - . += new/datum/atom_creator/simple(list(/obj/item/tank/emergency/oxygen/engi, /obj/item/clothing/mask/gas/half), 10) - . += new/datum/atom_creator/simple(/obj/item/oxycandle, 15) - . += new/datum/atom_creator/simple(/obj/item/storage/firstaid/o2, 25) - . += new/datum/atom_creator/simple(list(/obj/item/clothing/suit/space/emergency,/obj/item/clothing/head/helmet/space/emergency), 25) + . += new/datum/atom_creator/simple(list(/obj/item/clothing/mask/gas/half, /obj/item/tank/oxygen), 10) + . += new/datum/atom_creator/simple(/obj/item/oxycandle, 75) + . += new/datum/atom_creator/simple(/obj/item/storage/firstaid/regular, 25) /* * Fire Closet diff --git a/code/game/objects/structures/crematorium.dm b/code/game/objects/structures/crematorium.dm index 3b41a43dcc7..1ea52f85486 100644 --- a/code/game/objects/structures/crematorium.dm +++ b/code/game/objects/structures/crematorium.dm @@ -92,7 +92,7 @@ /obj/structure/crematorium/attackby(P, mob/user) if(istype(P, /obj/item/pen)) - var/new_label = sanitizeSafe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) + var/new_label = sanitize_safe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) if((!Adjacent(user) || loc == user)) return diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 583b8ed67ca..8c9d6830f27 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -103,7 +103,7 @@ /obj/structure/door_assembly/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/pen)) - var/t = sanitizeSafe(input(user, "Enter the name for the door.", src.name, src.created_name), MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter the name for the door.", src.name, src.created_name), MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && src.loc != usr) return created_name = t diff --git a/code/game/objects/structures/doors/_door.dm b/code/game/objects/structures/doors/_door.dm index 219260cb900..ffdaa951296 100644 --- a/code/game/objects/structures/doors/_door.dm +++ b/code/game/objects/structures/doors/_door.dm @@ -1,19 +1,20 @@ -#define MATERIAL_DOOR_SOUND_VOLUME 25 /obj/structure/door name = "door" icon = 'icons/obj/doors/material_doors.dmi' icon_state = "metal" hitsound = 'sound/weapons/genhit.ogg' - material_alteration = MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_COLOR | MAT_FLAG_ALTERATION_COLOR + material_alteration = MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_DESC | MAT_FLAG_ALTERATION_COLOR maxhealth = 50 density = TRUE anchored = TRUE opacity = TRUE + var/datum/lock/lock + var/has_window = FALSE var/changing_state = FALSE var/icon_base - var/datum/lock/lock + var/door_sound_volume = 25 /obj/structure/door/Initialize() . = ..() @@ -23,15 +24,11 @@ lock = new /datum/lock(src, lock) if(!icon_base) icon_base = material.door_icon_base - changing_state = FALSE - update_nearby_tiles(need_rebuild=TRUE) - - if(material.luminescence) + update_icon() + update_nearby_tiles(need_rebuild = TRUE) + if(material?.luminescence) set_light(material.luminescence, 0.5, material.color) - if(material.opacity < 0.5) - alpha = 180 - /obj/structure/door/Destroy() update_nearby_tiles() QDEL_NULL(lock) @@ -42,25 +39,22 @@ /obj/structure/door/on_update_icon() ..() - if(density) - icon_state = "[icon_base]" - else - icon_state = "[icon_base]open" + icon_state = "[icon_base][!density ? "open" : ""]" /obj/structure/door/proc/post_change_state() update_nearby_tiles() update_icon() changing_state = FALSE -/obj/structure/door/attack_hand(var/mob/user) +/obj/structure/door/attack_hand(mob/user) return density ? open() : close() /obj/structure/door/proc/close() set waitfor = 0 if(!can_close()) return FALSE - flick("[icon_base]closing", src) - playsound(src.loc, material.dooropen_noise, MATERIAL_DOOR_SOUND_VOLUME, 1) + flick("[icon_base]_closing", src) + playsound(src, material.dooropen_noise, door_sound_volume, 1) changing_state = TRUE sleep(1 SECOND) @@ -73,8 +67,8 @@ set waitfor = 0 if(!can_open()) return FALSE - flick("[icon_base]opening", src) - playsound(src.loc, material.dooropen_noise, MATERIAL_DOOR_SOUND_VOLUME, 1) + flick("[icon_base]_opening", src) + playsound(src, material.dooropen_noise, door_sound_volume, 1) changing_state = TRUE sleep(1 SECOND) @@ -112,7 +106,6 @@ return FALSE /obj/structure/door/attackby(obj/item/I, mob/user) - add_fingerprint(user, 0, I) if((user.a_intent == I_HURT && I.force) || istype(I, /obj/item/stack/material)) @@ -149,7 +142,7 @@ return !opacity return !density -/obj/structure/door/CanFluidPass(var/coming_from) +/obj/structure/door/CanFluidPass(coming_from) return !density /obj/structure/door/Bumped(atom/AM) @@ -212,4 +205,3 @@ /obj/structure/door/shuttle material = /decl/material/solid/metal/steel -#undef MATERIAL_DOOR_SOUND_VOLUME \ No newline at end of file diff --git a/code/game/objects/structures/fountain.dm b/code/game/objects/structures/fountain.dm index 4972ba89463..91a143a920f 100644 --- a/code/game/objects/structures/fountain.dm +++ b/code/game/objects/structures/fountain.dm @@ -49,12 +49,11 @@ to_chat(user, "You touch the fountain. All the memories of your life seem to fade into the distant past as seconds drag like years. You feel the inexplicable sensation of your skin tightening and thinning across your entire body as your muscles degrade and your joints weaken. Time returns to its 'normal' pace. You can only just barely remember touching the fountain.") user.became_older = TRUE user.change_hair_color(80, 80, 80) - var/age_holder = round(rand(15,20)) - user.set_age(age_holder) + user.set_age(user.get_age() + round(rand(15,20))) else //become younger to_chat(user, "You touch the fountain. Everything stops - then reverses. You relive in an instant the events of your life. The fountain, yesterday's lunch, your first love, your first kiss. It all feels as though it just happened moments ago. Then it feels like it never happened at all. Time reverses back into normality and continues its advance. You feel great, but why are you here?") user.became_younger = TRUE - user.set_age(rand(15,17)) + user.set_age(rand(18, max(round(user.get_age() / 2), 18))) //anywhere from 18 to half your age used = TRUE desc = "The water flows beautifully from the spout, but the water in the pool does not ripple." @@ -64,5 +63,8 @@ icon_state = "fountain_g" used = TRUE -/obj/structure/fountain/mundane/attack_hand() +/obj/structure/fountain/mundane/attack_hand(var/mob/user) + return + +/obj/structure/fountain/mundane/time_dilation(var/mob/living/carbon/human/user) return \ No newline at end of file diff --git a/code/game/objects/structures/hand_cart.dm b/code/game/objects/structures/hand_cart.dm index f5e9ea3cfe1..c1ac8d6b39d 100644 --- a/code/game/objects/structures/hand_cart.dm +++ b/code/game/objects/structures/hand_cart.dm @@ -37,6 +37,12 @@ /obj/structure/hand_cart/grab_attack(var/obj/item/grab/G) if(G.affecting && istype(G.affecting, /obj/)) + if(G.affecting == src) + to_chat(G.assailant, SPAN_NOTICE("You can't make \the [src] carry itself!")) + return TRUE + if(carrying) + to_chat(G.assailant, SPAN_NOTICE("[src] already has \the [carrying] on it, it can't fit anything else!")) + return TRUE to_chat(G.assailant, SPAN_NOTICE("You start loading \the [G.affecting] onto \the [src].")) if(load_item(G.affecting, G.assailant)) qdel(G) diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 53786b0fa9b..7612d769a05 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -120,7 +120,7 @@ add_fingerprint(user) /obj/structure/inflatable/can_repair_with(obj/item/tool) - . = istype(tool, /obj/item/tape_roll) && (health < maxhealth) + . = istype(tool, /obj/item/ducttape) && (health < maxhealth) /obj/structure/inflatable/handle_repair(mob/user, obj/item/tool) if(taped) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index e025bcef129..32954e5304d 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -82,7 +82,7 @@ /obj/structure/morgue/attackby(P, mob/user) if(istype(P, /obj/item/pen)) - var/new_label = sanitizeSafe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) + var/new_label = sanitize_safe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) if((!Adjacent(user) || loc == user)) return diff --git a/code/game/objects/structures/racks.dm b/code/game/objects/structures/racks.dm index 138f4111329..76259ff6b06 100644 --- a/code/game/objects/structures/racks.dm +++ b/code/game/objects/structures/racks.dm @@ -12,6 +12,7 @@ parts_amount = 2 parts_type = /obj/item/stack/material/strut density = TRUE + anchored = TRUE /obj/structure/rack/Initialize() ..() @@ -33,6 +34,14 @@ auto_align(O, click_params) return TRUE +/obj/structure/rack/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || height==0) + return TRUE + if(istype(mover) && mover.checkpass(PASS_FLAG_TABLE)) + return TRUE + var/obj/structure/rack/R = (locate() in get_turf(mover)) + return R + /obj/structure/rack/holorack/dismantle() material = null reinf_material = null diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index b581bd99b64..972ddb3732b 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -255,7 +255,7 @@ var/response = input(user, "New Window ID:", name, id) as null | text if (isnull(response) || user.incapacitated() || !user.Adjacent(src) || user.get_active_hand() != W) return - id = sanitizeSafe(response, MAX_NAME_LEN) + id = sanitize_safe(response, MAX_NAME_LEN) to_chat(user, SPAN_NOTICE("The new ID of \the [src] is [id].")) return else if(istype(W, /obj/item/gun/energy/plasmacutter) && anchored) @@ -568,10 +568,10 @@ /obj/machinery/button/windowtint/attackby(obj/item/W, mob/user) if(isMultitool(W)) - var/t = sanitizeSafe(input(user, "Enter the ID for the button.", name, id_tag), MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter the ID for the button.", name, id_tag), MAX_NAME_LEN) if(!CanPhysicallyInteract(user)) return TRUE - t = sanitizeSafe(t, MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) id_tag = t to_chat(user, SPAN_NOTICE("The new ID of the button is '[id_tag]'.")) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index a2cf8496a1e..e5b8825fc0d 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -130,7 +130,7 @@ /turf/proc/get_movement_delay(var/travel_dir) . = get_base_movement_delay() if(weather) - . += weather.get_movement_delay(travel_dir) + . += weather.get_movement_delay(return_air(), travel_dir) /turf/attack_hand(mob/user) user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index e12bd213650..c995ab4a492 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -1,5 +1,6 @@ /turf/proc/ReplaceWithLattice(var/material) var/base_turf = get_base_turf_by_area(src) + . = src if(base_turf && type != base_turf) . = ChangeTurf(base_turf) if(!(locate(/obj/structure/lattice) in .)) @@ -124,14 +125,14 @@ /turf/simulated/floor/transport_properties_from(turf/simulated/floor/other) if(!..()) return FALSE - + broken = other.broken burnt = other.burnt if(broken || burnt) queue_icon_update() set_flooring(other.flooring) return TRUE - + //I would name this copy_from() but we remove the other turf from their air zone for some reason /turf/simulated/transport_properties_from(turf/simulated/other) if(!..()) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 5b92362faf2..d81555bd166 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -94,6 +94,7 @@ var/global/list/admin_verbs_admin = list( /datum/admins/proc/show_aspects ) var/global/list/admin_verbs_ban = list( + /client/proc/DB_ban_panel, /client/proc/unban_panel, /client/proc/jobbans ) @@ -661,7 +662,7 @@ var/global/list/admin_verbs_mod = list( var/mob/living/silicon/S = input("Select silicon.", "Rename Silicon.") as null|anything in global.silicon_mob_list if(!S) return - var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name)) + var/new_name = sanitize_safe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name)) if(new_name && new_name != S.real_name) log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'") S.fully_replace_character_name(new_name) @@ -924,7 +925,7 @@ var/global/list/admin_verbs_mod = list( if("Upload custom") var/file = input(usr) as icon|null - if(!file) + if(!file) return global.using_map.update_titlescreen(file) diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/dbban/functions.dm similarity index 99% rename from code/modules/admin/DB ban/functions.dm rename to code/modules/admin/dbban/functions.dm index 5cde2396817..ee761246959 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/dbban/functions.dm @@ -294,7 +294,7 @@ /client/proc/DB_ban_panel() set category = "Admin" set name = "Banning Panel" - set desc = "Edit admin permissions" + set desc = "Allow edit existing bans or create new ones." if(!holder) return diff --git a/code/modules/admin/ticket.dm b/code/modules/admin/ticket.dm index 7bf115e2a6c..fa3df76106d 100644 --- a/code/modules/admin/ticket.dm +++ b/code/modules/admin/ticket.dm @@ -19,7 +19,7 @@ var/global/list/ticket_panels = list() id = tickets.len opened_time = world.time if(establish_db_connection()) - var/sql_ckey = sanitizeSQL(owner.ckey) + var/sql_ckey = sanitize_sql(owner.ckey) var/DBQuery/ticket_query = dbcon.NewQuery("INSERT INTO `erro_admin_tickets`(`ckey`, `round`, `inround_id`, `status`, `open_date`) VALUES ('[sql_ckey]', '[game_id]', [src.id], 'OPEN', NOW());") ticket_query.Execute() addtimer(CALLBACK(src, .proc/timeoutcheck), 5 MINUTES) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index bbbbbbcd74b..1d517ffd923 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1293,7 +1293,7 @@ src.access_news_network() else if(href_list["ac_set_channel_name"]) - src.admincaster_feed_channel.channel_name = sanitizeSafe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) + src.admincaster_feed_channel.channel_name = sanitize_safe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) src.access_news_network() else if(href_list["ac_set_channel_lock"]) @@ -1321,7 +1321,7 @@ var/list/available_channels = list() for(var/datum/feed_channel/F in news_network.network_channels) available_channels += F.channel_name - src.admincaster_feed_channel.channel_name = sanitizeSafe(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) + src.admincaster_feed_channel.channel_name = sanitize_safe(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) src.access_news_network() else if(href_list["ac_set_new_message"]) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 311001f84fc..981cae52c3c 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -111,7 +111,7 @@ var/global/list/adminhelp_ignored_words = list("unknown","the","a","an","of","mo update_ticket_panels() if(establish_db_connection()) - var/sql_text = "HELP [src.ckey]: [sanitizeSQL(original_msg)]\n" + var/sql_text = "HELP [src.ckey]: [sanitize_sql(original_msg)]\n" var/DBQuery/ticket_text = dbcon.NewQuery("UPDATE `erro_admin_tickets` SET `text` = '[sql_text]' WHERE `round` = '[game_id]' AND `inround_id` = '[ticket.id]';") ticket_text.Execute() diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index cc865fd9490..da9195800ca 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -153,7 +153,7 @@ update_ticket_panels() if(establish_db_connection()) - var/sql_text = "[src.ckey] -> [C.ckey]: [sanitizeSQL(msg)]\n" + var/sql_text = "[src.ckey] -> [C.ckey]: [sanitize_sql(msg)]\n" var/DBQuery/ticket_text = dbcon.NewQuery("UPDATE `erro_admin_tickets` SET `text` = CONCAT(COALESCE(text,''), '[sql_text]') WHERE `round` = '[game_id]' AND `inround_id` = '[ticket.id]';") ticket_text.Execute() diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index cc89531a4e8..25127ad555e 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -92,7 +92,7 @@ return 0 var/obj/item/paicard/card = new(T) var/mob/living/silicon/pai/pai = new(card) - pai.SetName(sanitizeSafe(input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text)) + pai.SetName(sanitize_safe(input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text)) pai.real_name = pai.name pai.key = choice.key card.setPersonality(pai) @@ -483,7 +483,7 @@ trap = GET_DECL(trap) trap.forced(mob) -/client/proc/spawn_exoplanet(exoplanet_type as anything in subtypesof(/obj/effect/overmap/visitable/sector/exoplanet)) +/client/proc/spawn_exoplanet(exoplanet_type AS_ANYTHING in subtypesof(/obj/effect/overmap/visitable/sector/exoplanet)) set category = "Debug" set name = "Create Exoplanet" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 992d4840c11..747cea4c332 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -467,7 +467,6 @@ Traitors and the like can also be revived with the previous role mostly intact. if(G_found.mind && !G_found.mind.active) G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use - new_character.mind.special_verbs = list() else new_character.mind_initialize() if(!new_character.mind.assigned_role) @@ -561,7 +560,7 @@ Traitors and the like can also be revived with the previous role mostly intact. to_chat(src, "Only administrators may use this command.") return var/input = sanitize(input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null, extra = 0) - var/customname = sanitizeSafe(input(usr, "Pick a title for the report.", "Title") as text|null) + var/customname = sanitize_safe(input(usr, "Pick a title for the report.", "Title") as text|null) if(!input) return if(!customname) diff --git a/code/modules/aspects/aspects.dm b/code/modules/aspects/aspects.dm index 18fd39df96a..5adbd11af2a 100644 --- a/code/modules/aspects/aspects.dm +++ b/code/modules/aspects/aspects.dm @@ -32,7 +32,7 @@ var/global/list/aspect_categories = list() // Containers for ease of printing da /decl/aspect/Initialize() . = ..() - + // This is here until there are positive traits to balance out the negative ones; // currently the cost calc serves no purpose and looks really silly sitting at -14/5. aspect_cost = 0 @@ -143,7 +143,7 @@ var/global/list/aspect_categories = list() // Containers for ease of printing da /datum/admins/proc/show_aspects() set category = "Admin" set name = "Show Aspects" - if(!check_rights(R_INVESTIGATE)) + if(!check_rights(R_INVESTIGATE)) return var/mob/M = input("Select mob.", "Select mob.") as null|anything in global.living_mob_list_ if(M) diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index b7df526e118..4e30fdbec65 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -15,6 +15,17 @@ var/obj/item/assembly/a_right = null var/obj/special_assembly = null +/obj/item/assembly_holder/Initialize() + . = ..() + global.listening_objects += src + +/obj/item/assembly_holder/Destroy() + global.listening_objects -= src + a_left = null + a_right = null + special_assembly = null + return ..() + /obj/item/assembly_holder/proc/attach(var/obj/item/D, var/obj/item/D2, var/mob/user) return @@ -182,16 +193,6 @@ // special_assembly.dothings() return 1 - -/obj/item/assembly_holder/Initialize() - . = ..() - global.listening_objects += src - -/obj/item/assembly_holder/Destroy() - global.listening_objects -= src - return ..() - - /obj/item/assembly_holder/hear_talk(mob/living/M, msg, verb, decl/language/speaking) if(a_right) a_right.hear_talk(M,msg,verb,speaking) diff --git a/code/modules/atmospherics/pipes.dm b/code/modules/atmospherics/pipes.dm index 621d797fd71..ccf082dfd3e 100644 --- a/code/modules/atmospherics/pipes.dm +++ b/code/modules/atmospherics/pipes.dm @@ -120,6 +120,8 @@ if(liquid_temporary) liquid_temporary.trans_to(loc, liquid_temporary.total_volume) liquid_temporary = null + if(leaking) + STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF) . = ..() /obj/machinery/atmospherics/pipe/deconstruction_pressure_check() diff --git a/code/modules/augment/active/cyberbrain.dm b/code/modules/augment/active/cyberbrain.dm index a0b49e9224d..cd00f0e1e6c 100644 --- a/code/modules/augment/active/cyberbrain.dm +++ b/code/modules/augment/active/cyberbrain.dm @@ -27,9 +27,15 @@ set_extension(src, /datum/extension/assembly/modular_computer/cyberbrain) update_icon() - + install_default_hardware() +/obj/item/organ/internal/augment/active/cyberbrain/get_contained_external_atoms() + . = ..() + var/datum/extension/assembly/assembly = get_extension(src, /datum/extension/assembly) + if(assembly) + LAZYREMOVE(., assembly.parts) + // Used to perform preset-specific hardware changes. /obj/item/organ/internal/augment/active/cyberbrain/proc/install_default_hardware() var/datum/extension/assembly/assembly = get_extension(src, /datum/extension/assembly) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 493796a8675..d3af3dc0e1c 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -406,7 +406,8 @@ var/global/list/localhost_addresses = list( 'html/panels.css', 'html/spacemag.css', 'html/images/loading.gif', - 'html/images/talisman.png' + 'html/images/talisman.png', + 'html/images/iseo.png' ) var/decl/asset_cache/asset_cache = GET_DECL(/decl/asset_cache) @@ -653,7 +654,7 @@ var/global/const/MAX_VIEW = 41 if("South") movement_keys[key] = SOUTH if("Say") - winset(src, "default-\ref[key]", "parent=default;name=[key];command=say") + winset(src, "default-\ref[key]", "parent=default;name=[key];command=.say") communication_hotkeys += key if("OOC") winset(src, "default-\ref[key]", "parent=default;name=[key];command=ooc") diff --git a/code/modules/client/preference_setup/background/01_species.dm b/code/modules/client/preference_setup/background/01_species.dm index a237921a5c6..85165834975 100644 --- a/code/modules/client/preference_setup/background/01_species.dm +++ b/code/modules/client/preference_setup/background/01_species.dm @@ -7,7 +7,7 @@ W.write("species", pref.species) /datum/category_item/player_setup_item/background/species/load_character(datum/pref_record_reader/R) - pref.species = R.read("species") + pref.species = R.read("species") /datum/category_item/player_setup_item/background/species/sanitize_character() . = ..() @@ -35,7 +35,7 @@ var/decl/species/current_species = get_species_by_key(pref.species) var/list/prefilter = get_playable_species() var/list/playables = list() - + for(var/s in prefilter) if(!check_rights(R_ADMIN, 0) && config.usealienwhitelist) var/decl/species/checking_species = get_species_by_key(s) @@ -61,11 +61,11 @@ var/icon/use_preview_icon = current_species.get_preview_icon() if(use_preview_icon) - send_rsc(user, use_preview_icon, current_species.preview_icon_path) + send_rsc(user, use_preview_icon, current_species.preview_icon_path) . += "" else . += "No preview available." - + var/desc = current_species.description || "No additional details." if(hide_species && length(desc) > 200) desc = "[copytext(desc, 1, 194)] \[...\]" diff --git a/code/modules/client/preference_setup/background/02_culture.dm b/code/modules/client/preference_setup/background/02_culture.dm index c40f9dff1be..852a634db24 100644 --- a/code/modules/client/preference_setup/background/02_culture.dm +++ b/code/modules/client/preference_setup/background/02_culture.dm @@ -62,7 +62,7 @@ if(pref.cultural_info[TAG_CULTURE]) var/decl/cultural_info/check = GET_DECL(pref.cultural_info[TAG_CULTURE]) if(check) - pref.real_name = check.sanitize_name(pref.real_name, pref.species) + pref.real_name = check.sanitize_cultural_name(pref.real_name, pref.species) if(!pref.real_name) pref.real_name = check.get_random_name(preference_mob(), pref.gender) diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 5aeea735ff5..eb256a0d4bf 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -95,7 +95,7 @@ if (!isnull(raw_name) && CanUseTopic(user)) var/decl/cultural_info/check = GET_DECL(pref.cultural_info[TAG_CULTURE]) - var/new_name = check.sanitize_name(raw_name, pref.species) + var/new_name = check.sanitize_cultural_name(raw_name, pref.species) if(filter_block_message(user, new_name)) return TOPIC_NOACTION diff --git a/code/modules/client/preference_setup/global/03_pai.dm b/code/modules/client/preference_setup/global/03_pai.dm index 9c2541558a4..86bccf57f94 100644 --- a/code/modules/client/preference_setup/global/03_pai.dm +++ b/code/modules/client/preference_setup/global/03_pai.dm @@ -52,7 +52,7 @@ . = TOPIC_REFRESH switch(href_list["option"]) if("name") - t = sanitizeName(input(user, "Enter a name for your pAI", "Global Preference", candidate.name) as text|null, MAX_NAME_LEN, 1) + t = sanitize_name(input(user, "Enter a name for your pAI", "Global Preference", candidate.name) as text|null, MAX_NAME_LEN, 1) if(t && CanUseTopic(user)) candidate.name = t if("desc") diff --git a/code/modules/client/preference_setup/global/05_settings.dm b/code/modules/client/preference_setup/global/05_settings.dm index d96ac73e0e9..d49f628cd7d 100644 --- a/code/modules/client/preference_setup/global/05_settings.dm +++ b/code/modules/client/preference_setup/global/05_settings.dm @@ -83,7 +83,7 @@ /client/proc/get_preference_value(var/preference) if(prefs) var/datum/client_preference/cp = get_client_preference(preference) - if(cp) + if(cp && LAZYLEN(prefs.preference_values)) return prefs.preference_values[cp.key] else return null @@ -93,7 +93,7 @@ /client/proc/set_preference(var/preference, var/set_preference) var/datum/client_preference/cp = get_client_preference(preference) - if(!cp) + if(!cp || !LAZYLEN(prefs.preference_values)) return FALSE if((prefs.preference_values[cp.key] != set_preference) && (set_preference in cp.options)) @@ -106,7 +106,7 @@ /client/proc/cycle_preference(var/preference) var/datum/client_preference/cp = get_client_preference(preference) - if(!cp) + if(!cp || !LAZYLEN(prefs.preference_values)) return FALSE var/next_option = next_in_list(prefs.preference_values[cp.key], cp.options) diff --git a/code/modules/client/preference_setup/loadout/lists/augmentations.dm b/code/modules/client/preference_setup/loadout/lists/augmentations.dm index 4dd270fe541..e19a17c1301 100644 --- a/code/modules/client/preference_setup/loadout/lists/augmentations.dm +++ b/code/modules/client/preference_setup/loadout/lists/augmentations.dm @@ -12,7 +12,7 @@ qdel(src) /obj/item/implant/AttemptAugmentation(mob/user, target_zone) - if(can_implant(user, user, target_zone) && implant_in_mob(user, user, target_zone)) + if(can_implant(user, user, target_zone) && user.get_organ(target_zone) && implant_in_mob(user, user, target_zone)) var/obj/item/organ/organ = user.get_organ(target_zone) to_chat(user, SPAN_NOTICE("You have \a [src] implanted in your [organ.name].")) else diff --git a/code/modules/client/preference_setup/loadout/lists/eyegear.dm b/code/modules/client/preference_setup/loadout/lists/eyegear.dm index 8a8dd7b83b2..b958b12d0c2 100644 --- a/code/modules/client/preference_setup/loadout/lists/eyegear.dm +++ b/code/modules/client/preference_setup/loadout/lists/eyegear.dm @@ -1,6 +1,6 @@ /decl/loadout_category/eyes name = "Eyewear" - + /decl/loadout_option/eyes category = /decl/loadout_category/eyes slot = slot_glasses_str @@ -40,3 +40,67 @@ name = "blindfold" path = /obj/item/clothing/glasses/blindfold flags = GEAR_HAS_COLOR_SELECTION + +/decl/loadout_option/eyes/medical + name = "medical eyewear selection" + path = /obj/item/clothing/glasses + +/decl/loadout_option/eyes/medical/get_gear_tweak_options() + . = ..() + LAZYINITLIST(.[/datum/gear_tweak/path/specified_types_list]) + .[/datum/gear_tweak/path/specified_types_list] |= list( + /obj/item/clothing/glasses/hud/health, + /obj/item/clothing/glasses/hud/health/prescription, + /obj/item/clothing/glasses/hud/health/visor, + /obj/item/clothing/glasses/eyepatch/hud/medical + ) + +/decl/loadout_option/eyes/security + name = "security eyewear selection" + path = /obj/item/clothing/glasses + +/decl/loadout_option/eyes/security/get_gear_tweak_options() + . = ..() + LAZYINITLIST(.[/datum/gear_tweak/path/specified_types_list]) + .[/datum/gear_tweak/path/specified_types_list] |= list( + /obj/item/clothing/glasses/hud/security, + /obj/item/clothing/glasses/hud/security/prescription, + /obj/item/clothing/glasses/sunglasses/sechud, + /obj/item/clothing/glasses/sunglasses/sechud/toggle, + /obj/item/clothing/glasses/eyepatch/hud/security + ) + +/decl/loadout_option/eyes/meson + name = "meson eyewear selection" + path = /obj/item/clothing/glasses + + +/decl/loadout_option/eyes/meson/get_gear_tweak_options() + . = ..() + LAZYINITLIST(.[/datum/gear_tweak/path/specified_types_list]) + .[/datum/gear_tweak/path/specified_types_list] |= list( + /obj/item/clothing/glasses/meson, + /obj/item/clothing/glasses/meson/prescription, + /obj/item/clothing/glasses/eyepatch/hud/meson + ) + +/decl/loadout_option/eyes/sciencegoggles + name = "scientific eyewear selection" + path = /obj/item/clothing/glasses + +/decl/loadout_option/eyes/sciencegoggles/get_gear_tweak_options() + . = ..() + LAZYINITLIST(.[/datum/gear_tweak/path/specified_types_list]) + .[/datum/gear_tweak/path/specified_types_list] |= list( + /obj/item/clothing/glasses/science, + /obj/item/clothing/glasses/science/prescription, + /obj/item/clothing/glasses/eyepatch/hud/science + ) + +/decl/loadout_option/eyes/welding + name = "welding goggles" + path = /obj/item/clothing/glasses/welding + +/decl/loadout_option/eyes/material + name = "optical material scanner" + path = /obj/item/clothing/glasses/material \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/lists/utility.dm b/code/modules/client/preference_setup/loadout/lists/utility.dm index 28894d43167..81eb76f18c6 100644 --- a/code/modules/client/preference_setup/loadout/lists/utility.dm +++ b/code/modules/client/preference_setup/loadout/lists/utility.dm @@ -73,3 +73,23 @@ "utility knife" = /obj/item/knife/utility, "lightweight utility knife" = /obj/item/knife/utility/lightweight ) + +/decl/loadout_option/utility/cheaptablet + name = "tablet computer, cheap" + path = /obj/item/modular_computer/tablet/preset/custom_loadout/cheap + cost = 3 + +/decl/loadout_option/utility/normaltablet + name = "tablet computer, advanced" + path = /obj/item/modular_computer/tablet/preset/custom_loadout/advanced + cost = 4 + +/decl/loadout_option/utility/cheaplaptop + name = "laptop computer, cheap" + path = /obj/item/modular_computer/laptop/preset/custom_loadout/cheap + cost = 3 + +/decl/loadout_option/utility/normallaptop + name = "laptop computer, advanced" + path = /obj/item/modular_computer/laptop/preset/custom_loadout/advanced + cost = 4 \ No newline at end of file diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c48b90b8814..d771fef81f2 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -75,6 +75,8 @@ var/global/list/time_prefs_fixed = list() /datum/preferences/Destroy() . = ..() + QDEL_NULL(player_setup) + QDEL_NULL(panel) QDEL_LIST_ASSOC_VAL(char_render_holders) /datum/preferences/proc/setup() diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm index 292bc8ffe73..9dfa71691f7 100644 --- a/code/modules/clothing/spacesuits/breaches.dm +++ b/code/modules/clothing/spacesuits/breaches.dm @@ -228,7 +228,7 @@ repair_breaches(BRUTE, 3, user) return - else if(istype(W, /obj/item/tape_roll)) + else if(istype(W, /obj/item/ducttape)) var/datum/breach/target_breach //Target the largest unpatched breach. for(var/datum/breach/B in breaches) if(B.patched) diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm index 7cb2acf9d08..d328b7af5d6 100644 --- a/code/modules/clothing/spacesuits/rig/suits/light.dm +++ b/code/modules/clothing/spacesuits/rig/suits/light.dm @@ -130,7 +130,7 @@ var/mob/M = usr if(!M.mind) return 0 if(M.incapacitated()) return 0 - var/input = sanitizeSafe(input("What do you want to name your suit?", "Rename suit"), MAX_NAME_LEN) + var/input = sanitize_safe(input("What do you want to name your suit?", "Rename suit"), MAX_NAME_LEN) if(src && input && !M.incapacitated() && in_range(M,src)) if(!findtext(input, "the", 1, 4)) input = "\improper [input]" @@ -147,7 +147,7 @@ var/mob/M = usr if(!M.mind) return 0 if(M.incapacitated()) return 0 - var/input = sanitizeSafe(input("Please describe your voidsuit in 128 letters or less.", "write description"), MAX_DESC_LEN) + var/input = sanitize_safe(input("Please describe your voidsuit in 128 letters or less.", "write description"), MAX_DESC_LEN) if(src && input && !M.incapacitated() && in_range(M,src)) desc = input to_chat(M, "Suit description succesful!") diff --git a/code/modules/clothing/under/accessories/ranks.dm b/code/modules/clothing/under/accessories/ranks.dm new file mode 100644 index 00000000000..e9dd4e672eb --- /dev/null +++ b/code/modules/clothing/under/accessories/ranks.dm @@ -0,0 +1,14 @@ +//Rank accessory base item +/obj/item/clothing/accessory/rank + name = "rank tabs" + desc = "A set of grey rank tabs." + slot = ACCESSORY_SLOT_RANK + hide_on_uniform_rolldown = TRUE + hide_on_uniform_rollsleeves = TRUE + var/ranking //Shorthand for the rank + var/ranking_full //Full name of the rank. + +/obj/item/clothing/accessory/rank/Initialize() + . = ..() + name = "[initial(name)] ([ranking_full])" + desc = "[initial(desc)] This set denotes a rank of [ranking_full] ([ranking])." \ No newline at end of file diff --git a/code/modules/codex/categories/category_recipes.dm b/code/modules/codex/categories/category_recipes.dm index 741c99adacb..f575ffec50b 100644 --- a/code/modules/codex/categories/category_recipes.dm +++ b/code/modules/codex/categories/category_recipes.dm @@ -85,7 +85,7 @@ var/mechanics_text = "" if(recipe.mechanics_text) mechanics_text = "[recipe.mechanics_text]

" - mechanics_text += "This recipe requires the following ingredients:
" + mechanics_text += "This recipe requires the following ingredients: