diff --git a/citadel.dme b/citadel.dme index 7c7f9707d0ac..a0160f3e7a30 100644 --- a/citadel.dme +++ b/citadel.dme @@ -1783,6 +1783,7 @@ #include "code\game\objects\items\storage\wallets.dm" #include "code\game\objects\items\storage\medical\firstaid.dm" #include "code\game\objects\items\storage\medical\hypokit.dm" +#include "code\game\objects\items\storage\misc\survival.dm" #include "code\game\objects\items\storage\misc_legacy\bible.dm" #include "code\game\objects\items\storage\misc_legacy\fancy.dm" #include "code\game\objects\items\storage\misc_legacy\laundry_basket.dm" @@ -2026,6 +2027,10 @@ #include "code\game\objects\structures\tables\update_triggers.dm" #include "code\game\objects\systems\_system.dm" #include "code\game\objects\systems\cell_slot.dm" +#include "code\game\objects\systems\storage\storage-filters.dm" +#include "code\game\objects\systems\storage\storage-indirection.dm" +#include "code\game\objects\systems\storage\storage-indirection_holder.dm" +#include "code\game\objects\systems\storage\storage-limits.dm" #include "code\game\objects\systems\storage\storage-screen_object.dm" #include "code\game\objects\systems\storage\storage-ui.dm" #include "code\game\objects\systems\storage\storage.dm" @@ -2259,6 +2264,7 @@ #include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" #include "code\modules\admin\verbs\SDQL2\wrappers\map.dm" +#include "code\modules\admin\verbs\SDQL2\wrappers\math.dm" #include "code\modules\admin\verbs\server\admin_reboot.dm" #include "code\modules\admin\view_variables\admin_delete.dm" #include "code\modules\admin\view_variables\color_matrix_editor.dm" diff --git a/code/__DEFINES/materials/helpers.dm b/code/__DEFINES/materials/helpers.dm index 70eafe784e50..793a43a26c31 100644 --- a/code/__DEFINES/materials/helpers.dm +++ b/code/__DEFINES/materials/helpers.dm @@ -1,14 +1,45 @@ //* This file is explicitly licensed under the MIT license. *// //* Copyright (c) 2023 Citadel Station developers. *// -//* object checks +//* /datum/prototype/material declaration helpers *// + +#define DECLARE_MATERIAL(PATH_FRAGMENT) \ +/datum/prototype/material##PATH_FRAGMENT + +/** + * Generates material stacks for a material. + * + * The material must have: + * + * * a defined `display_name` + * * a defined `sheet_singular_name` + * * a defined `sheet_plural_name` + * * a defined `icon` + * * a defined `icon_stack_count` + */ +#define GENERATE_MATERIAL_STACKS(PATH_FRAGMENT) \ +/obj/item/stack/material##PATH_FRAGMENT { \ + name = /datum/prototype/material##PATH_FRAGMENT::name + " " + /datum/prototype/material##PATH_FRAGMENT::sheet_singular_name; \ + icon = /datum/prototype/material##PATH_FRAGMENT::icon; \ + icon_state = "stack-1"; \ + material = /datum/prototype/material##PATH_FRAGMENT; \ + no_variants = TRUE; \ + amount = 1; \ +} \ +/obj/item/stack/material##PATH_FRAGMENT/full_stack { \ + name = /datum/prototype/material##PATH_FRAGMENT::name + " " + /datum/prototype/material##PATH_FRAGMENT::sheet_plural_name; \ + icon_state = "stack"; \ + amount = 50; \ +} + +//* Material Traits - Checks *// /// We are ticking materials. #define IS_TICKING_MATERIALS(A) (A.atom_flags & ATOM_MATERIALS_TICKING) #define START_TICKING_MATERIALS(A) SSmaterials.add_ticked_object(src) #define STOP_TICKING_MATERIALS(A) SSmaterials.remove_ticked_object(src) -//* /atom level invocation of traits +//* Material Traits - /atom invocation *// /// Invocation of material traits /// A - the atom diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 33e4e1156c9b..f098686ca566 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -135,9 +135,34 @@ SUBSYSTEM_DEF(atoms) * * ... - rest of args are passed to new() / Initialize(). */ /datum/controller/subsystem/atoms/proc/instance_atom_immediate(path, mapload, atom/where, ...) + SHOULD_NOT_SLEEP(TRUE) var/old_init_status = atom_init_status atom_init_status = mapload? ATOM_INIT_IN_NEW_MAPLOAD : ATOM_INIT_IN_NEW_REGULAR - var/atom/created = new path(arglist(args.Copy())) + var/atom/created = new path(arglist(args.Copy(3))) + atom_init_status = old_init_status + return created + +/** + * immediately creates and inits an atom with a preloader callback. + * + * @params + * * path - typepath + * * mapload - treat as mapload? + * * preload_call - callback to invoke with (created) for the created atom. This is not allowed to sleep. + * * where - location to init at + * * ... - rest of args are passed to new() / Initialize(). + */ +/datum/controller/subsystem/atoms/proc/instance_atom_immediate_with_preloader(path, mapload, datum/callback/preload_call, atom/where, ...) + SHOULD_NOT_SLEEP(TRUE) + var/old_init_status = atom_init_status + atom_init_status = ATOM_INIT_IN_SUBSYSTEM + var/atom/created = new path(arglist(args.Copy(4))) + preload_call.invoke_no_sleep(created) + atom_init_status = mapload? ATOM_INIT_IN_NEW_MAPLOAD : ATOM_INIT_IN_NEW_REGULAR + // this sets 'where' to if we should be mapload. + // this is acceptable because args[4] ('where') is not used again. + args[4] = mapload + InitAtom(created, FALSE, args) atom_init_status = old_init_status return created diff --git a/code/datums/callback.dm b/code/datums/callback.dm index 2087fd6ef448..3918cf039a44 100644 --- a/code/datums/callback.dm +++ b/code/datums/callback.dm @@ -101,24 +101,39 @@ else calling_arguments = args if(datum_flags & DF_VAR_EDITED) - return WrapAdminProcCall(object, delegate, calling_arguments) - if(object == GLOBAL_PROC) - return call(delegate)(arglist(calling_arguments)) - return call(object, delegate)(arglist(calling_arguments)) + . = WrapAdminProcCall(object, delegate, calling_arguments) + else if(object == GLOBAL_PROC) + . = call(delegate)(arglist(calling_arguments)) + else + . = call(object, delegate)(arglist(calling_arguments)) + pass() /** * Invoke this callback and crash if it sleeps. * * * Use when a callback should never sleep, as call() cannot be verified by static analysis. + * * Do not use in performance critical code. This wraps calls more aggressively than InvokeAsync(). + * * `null` is returned if the call sleeps. + * + * The specific use case here is an async call where: + * + * * It's always invalid behavior for a callback to sleep. + * * The caller should be protected (caller shouldn't be interrupted by the sleep). + * + * This allows enforcement of the above invariants by loudly runtiming and bringing attention to the issue, + * as opposed to the usual way of compile checking it (which we can't because this is a reflection-based call to an arbitrary proc). */ /datum/callback/proc/invoke_no_sleep(...) . = CALLBACK_SLEEP_SENTINEL - ASYNC - . = Invoke(arglist(args)) + . = invoke_no_sleep_call(arglist(args)) if(. == CALLBACK_SLEEP_SENTINEL) . = null CRASH("Callback [src] slept on a no-sleeping invoke.") +/datum/callback/proc/invoke_no_sleep_call(...) + set waitfor = FALSE + . = Invoke(arglist(args)) + /** * Invoke this callback async (waitfor=false) * diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 85823242f516..c377c1e9964e 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -141,8 +141,59 @@ for(var/i=0,i max_items) + return FALSE + if(!isnull(max_combined_volume) && (cached_combined_volume + candidate.get_weight_volume() > max_combined_volume)) + return FALSE + var/their_weight_class = candidate.get_weight_class() + if(!isnull(max_single_weight_class) && (their_weight_class > max_single_weight_class)) + return FALSE + if(!isnull(max_combined_weight_class) && (cached_combined_weight_class + their_weight_class > max_combined_weight_class)) + return FALSE + if(candidate.obj_storage && (candidate.w_class >= parent.w_class) && disallow_equal_weight_class_storage_nesting) + return FALSE + return TRUE + +/datum/object_system/storage/proc/why_failed_insertion_limits(obj/item/candidate) + var/atom/movable/indirection = real_contents_loc() + if(!isnull(max_items) && length(indirection.contents) > max_items) + return "too many items" + if(!isnull(max_combined_volume) && (cached_combined_volume + candidate.get_weight_volume() > max_combined_volume)) + return "insufficient volume" + var/their_weight_class = candidate.get_weight_class() + if(!isnull(max_single_weight_class) && (their_weight_class > max_single_weight_class)) + return "too large" + if(!isnull(max_combined_weight_class) && (cached_combined_weight_class + their_weight_class > max_combined_weight_class)) + return "insufficient space" + if(candidate.obj_storage && (candidate.w_class >= parent.w_class) && disallow_equal_weight_class_storage_nesting) + return "can't nest storage" + return null diff --git a/code/game/objects/systems/storage/storage-ui.dm b/code/game/objects/systems/storage/storage-ui.dm index 76d987239ff9..a06a3a0dd64e 100644 --- a/code/game/objects/systems/storage/storage-ui.dm +++ b/code/game/objects/systems/storage/storage-ui.dm @@ -1,6 +1,13 @@ //* This file is explicitly licensed under the MIT license. *// //* Copyright (c) 2024 Citadel Station Developers *// +//* Helper Datums *// + +/** + * Holds an object to render along with the amount. + * + * * This does hard-ref the rendered object for ease of use. Since UI is re-rendered on removals, this should be fine. + */ /datum/storage_numerical_display var/obj/item/rendered_object var/amount @@ -11,3 +18,251 @@ /proc/cmp_storage_numerical_displays_name_asc(datum/storage_numerical_display/A, datum/storage_numerical_display/B) return sorttext(B.rendered_object.name, A.rendered_object.name) || sorttext(B.rendered_object.type, A.rendered_object.type) + +//* UI Render Filters *// + +/** + * Do not modify the returned appearances; they might be real instances! + * + * @return list(/datum/storage_numerical_display instance, ...) + */ +/datum/object_system/storage/proc/render_numerical_display(list/obj/item/for_items) + RETURN_TYPE(/list) + . = list() + var/list/types = list() + for(var/obj/item/iterating in (for_items || real_contents_loc())) + var/datum/storage_numerical_display/collation + if(isnull(types[iterating.type])) + collation = new + collation.rendered_object = iterating + collation.amount = 0 + . += collation + types[iterating.type] = collation + collation = types[iterating.type] + ++collation.amount + tim_sort(., /proc/cmp_storage_numerical_displays_name_asc) + +//* UI Rendering *// + +// todo: refactor a bit? this is a little messy + +/datum/object_system/storage/proc/ui_queue_refresh() + if(ui_refresh_queued) + return + ui_refresh_queued = TRUE + addtimer(CALLBACK(src, PROC_REF(refresh)), 0) + +/datum/object_system/storage/proc/cleanup_ui(mob/user) + var/list/objects = ui_by_mob[user] + user.client?.screen -= objects + QDEL_LIST(objects) + ui_by_mob -= user + +/** + * we assume that the display style didn't change. + */ +/datum/object_system/storage/proc/refresh_ui(mob/user) + // for now, we just do a full redraw. + cleanup_ui(user) + create_ui(user) + +/datum/object_system/storage/proc/create_ui(mob/user) + var/uses_volumetric_ui = uses_volumetric_ui() + var/list/atom/movable/screen/storage/objects + if(uses_volumetric_ui) + objects += create_ui_volumetric_mode(user) + else + objects += create_ui_slot_mode(user) + LAZYINITLIST(ui_by_mob) + ui_by_mob[user] = objects + user.client?.screen += objects + +/** + * this should not rely on uses_numerical_ui() + */ +/datum/object_system/storage/proc/uses_volumetric_ui() + return max_combined_volume && !ui_numerical_mode && !ui_force_slot_mode + +/** + * this should not rely on uses_volumetric_ui() + */ +/datum/object_system/storage/proc/uses_numerical_ui() + return ui_numerical_mode + +/datum/object_system/storage/proc/create_ui_slot_mode(mob/user) + . = list() + var/atom/movable/screen/storage/closer/closer = new + . += closer + var/atom/movable/screen/storage/panel/slot/boxes/boxes = new + . += boxes + // todo: clientless support is awful here + var/list/decoded_view = decode_view_size(user.client?.view || world.view) + var/view_x = decoded_view[1] + // clamp to max items if needed + var/rendering_width = STORAGE_UI_TILES_FOR_SCREEN_VIEW_X(view_x) + if(max_items) + rendering_width = min(max_items, rendering_width) + // see if we need to process numerical display + var/list/datum/storage_numerical_display/numerical_rendered = uses_numerical_ui()? render_numerical_display() : null + // process indirection + var/atom/indirection = real_contents_loc() + // if we have expand when needed, only show 1 more than the actual amount. + if(ui_expand_when_needed) + rendering_width = min(rendering_width, (isnull(numerical_rendered)? length(indirection.contents) : length(numerical_rendered)) + 1) + // compute count and rows + var/item_count = isnull(numerical_rendered)? length(indirection.contents) : length(numerical_rendered) + var/rows_needed = ROUND_UP(item_count / rendering_width) || 1 + // prepare iteration + var/current_row = 1 + var/current_column = 1 + // render boxes + boxes.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \ + LEFT+[STORAGE_UI_START_TILE_X + rendering_width - 1]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y + rows_needed - 1]:[STORAGE_UI_START_PIXEL_Y]" + // render closer + closer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + rendering_width]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y]" + // render items + if(islist(numerical_rendered)) + for(var/datum/storage_numerical_display/display as anything in numerical_rendered) + var/atom/movable/screen/storage/item/slot/renderer = new(null, display.rendered_object) + . += renderer + // render amount + display.rendered_object.maptext = MAPTEXT("[display.amount]") + // position + renderer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + current_column - 1]:[STORAGE_UI_START_PIXEL_X],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" + // advance + ++current_column + if(current_column > rendering_width) + current_column = 1 + ++current_row + if(current_row > STORAGE_UI_MAX_ROWS) + break + else + for(var/obj/item/item in indirection) + var/atom/movable/screen/storage/item/slot/renderer = new(null, item) + . += renderer + // position + renderer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + current_column - 1]:[STORAGE_UI_START_PIXEL_X],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" + // advance + ++current_column + if(current_column > rendering_width) + current_column = 1 + ++current_row + if(current_row > STORAGE_UI_MAX_ROWS) + break + +/datum/object_system/storage/proc/create_ui_volumetric_mode(mob/user) + // guard against divide-by-0's + if(!max_combined_volume) + return create_ui_slot_mode(user) + . = list() + + //? resolve view and rendering + // todo: clientless support is awful here + + // resolve view + var/list/decoded_view = decode_view_size(user.client?.view || world.view) + var/view_x = decoded_view[1] + // setup initial width + var/rendering_width = STORAGE_UI_TILES_FOR_SCREEN_VIEW_X(view_x) + var/rendering_width_in_pixels = rendering_width * 32 + // effective max scales up if we're overrunning + var/effective_max_volume = max(max_combined_volume, cached_combined_volume) + // scale down width to volume + rendering_width_in_pixels = min(rendering_width_in_pixels, effective_max_volume * VOLUMETRIC_STORAGE_STANDARD_PIXEL_RATIO) + + //? resolve items + + // resolve indirection + var/atom/indirection = real_contents_loc() + + //? prepare iteration + + // max x used in all rows, including padding. + var/maximum_used_width = 0 + // current consumed x of row + var/iteration_used_width = 0 + // current consumed item padding of row + var/iteration_used_padding = 0 + // current row + var/current_row = 1 + // safety + var/safety = VOLUMETRIC_STORAGE_MAX_ITEMS + // iterate and render + for(var/obj/item/item in indirection) + // check safety + safety-- + if(safety <= 0) + to_chat(user, SPAN_WARNING("Some items in this storage have been truncated for performance reasons.")) + break + + // check row + if(iteration_used_width >= rendering_width_in_pixels) + // check if we're out of rows + if(current_row >= STORAGE_UI_MAX_ROWS) + to_chat(user, SPAN_WARNING("Some items in this storage have been truncated for performance reasons.")) + break + // make another row + current_row++ + // register to maximum used width + // we add the edge padding for both edges, but remove the last item's padding. + maximum_used_width = max(maximum_used_width, iteration_used_width + iteration_used_padding + VOLUMETRIC_STORAGE_EDGE_PADDING * 2 - VOLUMETRIC_STORAGE_ITEM_PADDING) + // reset vars + iteration_used_padding = 0 + iteration_used_width = 0 + + // render the item + var/atom/movable/screen/storage/item/volumetric/renderer = new(null, item) + // scale it as necessary, to nearest multiple of 2 + var/used_pixels = max(VOLUMETRIC_STORAGE_MINIMUM_PIXELS_PER_ITEM, CEILING(rendering_width_in_pixels * (item.get_weight_volume() / effective_max_volume), 2)) + // emit to renderer + renderer.set_pixel_width(used_pixels) + // set screen loc + renderer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + (iteration_used_width + iteration_used_padding + VOLUMETRIC_STORAGE_EDGE_PADDING) + (used_pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" + // add to emitted screen list + . += renderer + // add to iteration tracking + iteration_used_width += used_pixels + iteration_used_padding += VOLUMETRIC_STORAGE_ITEM_PADDING + // register to maximum used width + // we add the edge padding for both edges, but remove the last item's padding. + maximum_used_width = max(maximum_used_width, iteration_used_width + iteration_used_padding + VOLUMETRIC_STORAGE_EDGE_PADDING * 2 - VOLUMETRIC_STORAGE_ITEM_PADDING) + + // now that everything's set up, we can render everything based on the solved sizes. + // middle size; we also keep in account padding so there's a smooth expansion instead of a sudden expansion at the end. + var/middle_width = max(maximum_used_width, rendering_width_in_pixels + iteration_used_padding) + // i hate byond i hate byond i hate byond i hate byond; this is because things break if we don't extend by 2 pixels + // at a time for left/right as we use a dumb transform matrix and screen loc to shift, instead of a scale and shift matrix + middle_width = CEILING(middle_width, 2) + // todo: instead of this crap we should instead have the translation matrix do the shift + var/middle_shift = round(middle_width * 0.5 - VOLUMETRIC_STORAGE_BOX_ICON_SIZE * 0.5) + // render left + var/atom/movable/screen/storage/panel/volumetric/left/p_left = new + . += p_left + p_left.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ + BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \ + LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" + // render middle + var/atom/movable/screen/storage/panel/volumetric/middle/p_box = new + . += p_box + p_box.set_pixel_width(middle_width) + p_box.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_shift],\ + BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \ + LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_shift],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" + // render closer on bottom + var/atom/movable/screen/storage/closer/closer = new + . += closer + closer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_width],\ + BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y]" + // render right sides above closer + if(current_row > 1) + var/atom/movable/screen/storage/panel/volumetric/right/p_right = new + . += p_right + p_right.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_width - WORLD_ICON_SIZE + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + 1]:[STORAGE_UI_START_PIXEL_Y] to \ + LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_width - WORLD_ICON_SIZE + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ + BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" diff --git a/code/game/objects/systems/storage/storage.dm b/code/game/objects/systems/storage/storage.dm index b921ced493b1..32f9799907d3 100644 --- a/code/game/objects/systems/storage/storage.dm +++ b/code/game/objects/systems/storage/storage.dm @@ -8,7 +8,7 @@ */ /datum/object_system/storage - //* Access + //* Access *// /// if set, limit allowable random access to first n items var/limited_random_access_stack_amount @@ -16,7 +16,7 @@ /// * top down is from end of contents list, bottom up is from start of contents list var/limited_random_access_stack_bottom_first = FALSE - //* Actions + //* Actions *// /// the action we have for mode switching gathering var/datum/action/storage_gather_mode/action_mode_switch @@ -362,6 +362,12 @@ //* Hooks *// +/** + * Hooked into obj/Moved(). + */ +/datum/object_system/storage/proc/on_parent_moved(atom/old_loc, forced) + reconsider_mob_viewable() + /datum/object_system/storage/proc/on_pickup(mob/user) grant_buttons(user) @@ -404,35 +410,6 @@ physically_insert_item(item, no_move = TRUE) ui_queue_refresh() -//* Filters *// - -/datum/object_system/storage/proc/check_insertion_filters(obj/item/candidate) - if(insertion_allow_typecache?[candidate.type]) - return TRUE - if(!isnull(insertion_whitelist_typecache) && !insertion_whitelist_typecache?[candidate.type]) - return FALSE - if(insertion_blacklist_typecache?[candidate.type]) - return FALSE - return TRUE - -/datum/object_system/storage/proc/set_insertion_whitelist(list/types) - if(!length(types)) - src.insertion_whitelist_typecache = null - return - src.insertion_whitelist_typecache = cached_typecacheof(types) - -/datum/object_system/storage/proc/set_insertion_blacklist(list/types) - if(!length(types)) - src.insertion_blacklist_typecache = null - return - src.insertion_blacklist_typecache = cached_typecacheof(types) - -/datum/object_system/storage/proc/set_insertion_allow(list/types) - if(!length(types)) - src.insertion_allow_typecache = null - return - src.insertion_allow_typecache = cached_typecacheof(types) - //* Interaction *// /** @@ -447,6 +424,8 @@ //* Insertion & Removal *// /** + * todo: refactor? + * * @return TRUE / FALSE; if true, caller should stop clickchain. */ /datum/object_system/storage/proc/auto_handle_interacted_insertion(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed) @@ -477,6 +456,38 @@ ) return TRUE +/** + * Called by inventory procs; skips some checks of interacted insertion. + * + * todo: refactor? + * + * @return TRUE on success, FALSE on failure. + */ +/datum/object_system/storage/proc/auto_handle_inventory_insertion(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed) + if(is_locked(actor.performer)) + actor.chat_feedback( + msg = SPAN_WARNING("[parent] is locked."), + target = parent, + ) + return TRUE + if(!actor.performer.Reachability(indirection || parent)) + return TRUE + if(!try_insert(inserting, actor, silent, suppressed)) + return TRUE + // sound + // todo: put this in interacted_insert()..? + if(!suppressed && !isnull(actor)) + if(sfx_insert) + // todo: variable sound + playsound(actor.performer, sfx_insert, 50, 1, -5) + actor.visible_feedback( + target = parent, + range = MESSAGE_RANGE_INVENTORY_SOFT, + visible = "[actor.performer] puts [inserting] into [parent].", + visible_self = "You put [inserting] into [parent]", + ) + return TRUE + /datum/object_system/storage/proc/try_insert(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed, no_update) if(!can_be_inserted(inserting, actor, silent)) return FALSE @@ -633,36 +644,6 @@ //* Limits *// -/datum/object_system/storage/proc/check_insertion_limits(obj/item/candidate) - var/atom/movable/indirection = real_contents_loc() - if(!isnull(max_items) && length(indirection.contents) > max_items) - return FALSE - if(!isnull(max_combined_volume) && (cached_combined_volume + candidate.get_weight_volume() > max_combined_volume)) - return FALSE - var/their_weight_class = candidate.get_weight_class() - if(!isnull(max_single_weight_class) && (their_weight_class > max_single_weight_class)) - return FALSE - if(!isnull(max_combined_weight_class) && (cached_combined_weight_class + their_weight_class > max_combined_weight_class)) - return FALSE - if(candidate.obj_storage && (candidate.w_class >= parent.w_class) && disallow_equal_weight_class_storage_nesting) - return FALSE - return TRUE - -/datum/object_system/storage/proc/why_failed_insertion_limits(obj/item/candidate) - var/atom/movable/indirection = real_contents_loc() - if(!isnull(max_items) && length(indirection.contents) > max_items) - return "too many items" - if(!isnull(max_combined_volume) && (cached_combined_volume + candidate.get_weight_volume() > max_combined_volume)) - return "insufficient volume" - var/their_weight_class = candidate.get_weight_class() - if(!isnull(max_single_weight_class) && (their_weight_class > max_single_weight_class)) - return "too large" - if(!isnull(max_combined_weight_class) && (cached_combined_weight_class + their_weight_class > max_combined_weight_class)) - return "insufficient space" - if(candidate.obj_storage && (candidate.w_class >= parent.w_class) && disallow_equal_weight_class_storage_nesting) - return "can't nest storage" - return null - /** * generally a bad idea to call, tbh. * @@ -713,34 +694,6 @@ //* Quickdraw *// // todo: quickdraw -/* -/datum/component/storage/proc/on_alt_click(datum/source, mob/user) - if(!isliving(user) || !user.CanReach(parent)) - return - if(check_locked(source, user, TRUE)) - return TRUE - - var/atom/A = parent - if(!quickdraw) - A.add_fingerprint(user) - user_show_to_mob(user, trigger_on_found = TRUE) - if(rustle_sound) - playsound(A, "rustle", 50, 1, -5) - return TRUE - - if(user.can_hold_items() && !user.incapacitated()) - var/obj/item/I = locate() in real_location() - if(!I) - return - A.add_fingerprint(user) - remove_from_storage(I, get_turf(user)) - if(!user.put_in_hands(I)) - user.visible_message("[user] fumbles with the [parent], letting [I] fall on the floor.", \ - "You fumble with [parent], letting [I] fall on the floor.") - return TRUE - user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") - return TRUE -*/ //* Redirection *// @@ -1169,12 +1122,6 @@ parent.object_storage_closed(viewer) -/** - * Hooked into obj/Moved(). - */ -/datum/object_system/storage/proc/on_parent_moved(atom/old_loc, forced) - reconsider_mob_viewable() - /datum/object_system/storage/proc/refresh(mob/viewer) ui_refresh_queued = FALSE if(isnull(viewer)) @@ -1183,26 +1130,6 @@ return refresh_ui(viewer) -/** - * Do not modify the returned appearances; they might be real instances! - * - * @return list(/datum/storage_numerical_display instance, ...) - */ -/datum/object_system/storage/proc/render_numerical_display(list/obj/item/for_items) - RETURN_TYPE(/list) - . = list() - var/list/types = list() - for(var/obj/item/iterating in (for_items || real_contents_loc())) - var/datum/storage_numerical_display/collation - if(isnull(types[iterating.type])) - collation = new - collation.rendered_object = iterating - collation.amount = 0 - . += collation - types[iterating.type] = collation - collation = types[iterating.type] - ++collation.amount - tim_sort(., /proc/cmp_storage_numerical_displays_name_asc) /datum/object_system/storage/proc/reconsider_mob_viewable(mob/user) if(isnull(user)) @@ -1213,259 +1140,6 @@ return hide(user) -/datum/object_system/storage/proc/ui_queue_refresh() - if(ui_refresh_queued) - return - ui_refresh_queued = TRUE - addtimer(CALLBACK(src, PROC_REF(refresh)), 0) - -/datum/object_system/storage/proc/cleanup_ui(mob/user) - var/list/objects = ui_by_mob[user] - user.client?.screen -= objects - QDEL_LIST(objects) - ui_by_mob -= user - -/** - * we assume that the display style didn't change. - */ -/datum/object_system/storage/proc/refresh_ui(mob/user) - // for now, we just do a full redraw. - cleanup_ui(user) - create_ui(user) - -/datum/object_system/storage/proc/create_ui(mob/user) - var/uses_volumetric_ui = uses_volumetric_ui() - var/list/atom/movable/screen/storage/objects - if(uses_volumetric_ui) - objects += create_ui_volumetric_mode(user) - else - objects += create_ui_slot_mode(user) - LAZYINITLIST(ui_by_mob) - ui_by_mob[user] = objects - user.client?.screen += objects - -/** - * this should not rely on uses_numerical_ui() - */ -/datum/object_system/storage/proc/uses_volumetric_ui() - return max_combined_volume && !ui_numerical_mode && !ui_force_slot_mode - -/** - * this should not rely on uses_volumetric_ui() - */ -/datum/object_system/storage/proc/uses_numerical_ui() - return ui_numerical_mode - -/datum/object_system/storage/proc/create_ui_slot_mode(mob/user) - . = list() - var/atom/movable/screen/storage/closer/closer = new - . += closer - var/atom/movable/screen/storage/panel/slot/boxes/boxes = new - . += boxes - // todo: clientless support is awful here - var/list/decoded_view = decode_view_size(user.client?.view || world.view) - var/view_x = decoded_view[1] - // clamp to max items if needed - var/rendering_width = STORAGE_UI_TILES_FOR_SCREEN_VIEW_X(view_x) - if(max_items) - rendering_width = min(max_items, rendering_width) - // see if we need to process numerical display - var/list/datum/storage_numerical_display/numerical_rendered = uses_numerical_ui()? render_numerical_display() : null - // process indirection - var/atom/indirection = real_contents_loc() - // if we have expand when needed, only show 1 more than the actual amount. - if(ui_expand_when_needed) - rendering_width = min(rendering_width, (isnull(numerical_rendered)? length(indirection.contents) : length(numerical_rendered)) + 1) - // compute count and rows - var/item_count = isnull(numerical_rendered)? length(indirection.contents) : length(numerical_rendered) - var/rows_needed = ROUND_UP(item_count / rendering_width) || 1 - // prepare iteration - var/current_row = 1 - var/current_column = 1 - // render boxes - boxes.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \ - LEFT+[STORAGE_UI_START_TILE_X + rendering_width - 1]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y + rows_needed - 1]:[STORAGE_UI_START_PIXEL_Y]" - // render closer - closer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + rendering_width]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y]" - // render items - if(islist(numerical_rendered)) - for(var/datum/storage_numerical_display/display as anything in numerical_rendered) - var/atom/movable/screen/storage/item/slot/renderer = new(null, display.rendered_object) - . += renderer - // render amount - display.rendered_object.maptext = MAPTEXT("[display.amount]") - // position - renderer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + current_column - 1]:[STORAGE_UI_START_PIXEL_X],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" - // advance - ++current_column - if(current_column > rendering_width) - current_column = 1 - ++current_row - if(current_row > STORAGE_UI_MAX_ROWS) - break - else - for(var/obj/item/item in indirection) - var/atom/movable/screen/storage/item/slot/renderer = new(null, item) - . += renderer - // position - renderer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + current_column - 1]:[STORAGE_UI_START_PIXEL_X],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" - // advance - ++current_column - if(current_column > rendering_width) - current_column = 1 - ++current_row - if(current_row > STORAGE_UI_MAX_ROWS) - break - -/datum/object_system/storage/proc/create_ui_volumetric_mode(mob/user) - // guard against divide-by-0's - if(!max_combined_volume) - return create_ui_slot_mode(user) - . = list() - - //? resolve view and rendering - // todo: clientless support is awful here - - // resolve view - var/list/decoded_view = decode_view_size(user.client?.view || world.view) - var/view_x = decoded_view[1] - // setup initial width - var/rendering_width = STORAGE_UI_TILES_FOR_SCREEN_VIEW_X(view_x) - var/rendering_width_in_pixels = rendering_width * 32 - // effective max scales up if we're overrunning - var/effective_max_volume = max(max_combined_volume, cached_combined_volume) - // scale down width to volume - rendering_width_in_pixels = min(rendering_width_in_pixels, effective_max_volume * VOLUMETRIC_STORAGE_STANDARD_PIXEL_RATIO) - - //? resolve items - - // resolve indirection - var/atom/indirection = real_contents_loc() - - //? prepare iteration - - // max x used in all rows, including padding. - var/maximum_used_width = 0 - // current consumed x of row - var/iteration_used_width = 0 - // current consumed item padding of row - var/iteration_used_padding = 0 - // current row - var/current_row = 1 - // safety - var/safety = VOLUMETRIC_STORAGE_MAX_ITEMS - // iterate and render - for(var/obj/item/item in indirection) - // check safety - safety-- - if(safety <= 0) - to_chat(user, SPAN_WARNING("Some items in this storage have been truncated for performance reasons.")) - break - - // check row - if(iteration_used_width >= rendering_width_in_pixels) - // check if we're out of rows - if(current_row >= STORAGE_UI_MAX_ROWS) - to_chat(user, SPAN_WARNING("Some items in this storage have been truncated for performance reasons.")) - break - // make another row - current_row++ - // register to maximum used width - // we add the edge padding for both edges, but remove the last item's padding. - maximum_used_width = max(maximum_used_width, iteration_used_width + iteration_used_padding + VOLUMETRIC_STORAGE_EDGE_PADDING * 2 - VOLUMETRIC_STORAGE_ITEM_PADDING) - // reset vars - iteration_used_padding = 0 - iteration_used_width = 0 - - // render the item - var/atom/movable/screen/storage/item/volumetric/renderer = new(null, item) - // scale it as necessary, to nearest multiple of 2 - var/used_pixels = max(VOLUMETRIC_STORAGE_MINIMUM_PIXELS_PER_ITEM, CEILING(rendering_width_in_pixels * (item.get_weight_volume() / effective_max_volume), 2)) - // emit to renderer - renderer.set_pixel_width(used_pixels) - // set screen loc - renderer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + (iteration_used_width + iteration_used_padding + VOLUMETRIC_STORAGE_EDGE_PADDING) + (used_pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" - // add to emitted screen list - . += renderer - // add to iteration tracking - iteration_used_width += used_pixels - iteration_used_padding += VOLUMETRIC_STORAGE_ITEM_PADDING - // register to maximum used width - // we add the edge padding for both edges, but remove the last item's padding. - maximum_used_width = max(maximum_used_width, iteration_used_width + iteration_used_padding + VOLUMETRIC_STORAGE_EDGE_PADDING * 2 - VOLUMETRIC_STORAGE_ITEM_PADDING) - - // now that everything's set up, we can render everything based on the solved sizes. - // middle size; we also keep in account padding so there's a smooth expansion instead of a sudden expansion at the end. - var/middle_width = max(maximum_used_width, rendering_width_in_pixels + iteration_used_padding) - // i hate byond i hate byond i hate byond i hate byond; this is because things break if we don't extend by 2 pixels - // at a time for left/right as we use a dumb transform matrix and screen loc to shift, instead of a scale and shift matrix - middle_width = CEILING(middle_width, 2) - // todo: instead of this crap we should instead have the translation matrix do the shift - var/middle_shift = round(middle_width * 0.5 - VOLUMETRIC_STORAGE_BOX_ICON_SIZE * 0.5) - // render left - var/atom/movable/screen/storage/panel/volumetric/left/p_left = new - . += p_left - p_left.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ - BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \ - LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" - // render middle - var/atom/movable/screen/storage/panel/volumetric/middle/p_box = new - . += p_box - p_box.set_pixel_width(middle_width) - p_box.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_shift],\ - BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \ - LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_shift],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" - // render closer on bottom - var/atom/movable/screen/storage/closer/closer = new - . += closer - closer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_width],\ - BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y]" - // render right sides above closer - if(current_row > 1) - var/atom/movable/screen/storage/panel/volumetric/right/p_right = new - . += p_right - p_right.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_width - WORLD_ICON_SIZE + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + 1]:[STORAGE_UI_START_PIXEL_Y] to \ - LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_width - WORLD_ICON_SIZE + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE],\ - BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]" - -//* Indirection *// - -/** - * **USE AT YOUR OWN PERIL** - */ -/datum/object_system/storage/proc/indirect(atom/where) - ASSERT(isnull(indirection)) - indirection = new(where, src) - -/** - * remove indirection by obliterating contents - */ -/datum/object_system/storage/proc/destructively_remove_indirection() - QDEL_NULL(indirection) - -/** - * remove indirection by moving contents - */ -/datum/object_system/storage/proc/relocate_remove_indirection(atom/where_to) - ASSERT(!isnull(where_to) && where_to != indirection) - for(var/atom/movable/AM as anything in indirection) - AM.forceMove(where_to) - QDEL_NULL(indirection) - -/** - * move indirection somewhere else - */ -/datum/object_system/storage/proc/move_indirection_to(atom/where_to) - indirection.forceMove(where_to) - -//? Numerical Display Helper - //? Action /datum/action/storage_gather_mode @@ -1495,49 +1169,3 @@ else obj_storage.indirect(src) return obj_storage - -//? Indirection Holder - -/atom/movable/storage_indirection - atom_flags = ATOM_ABSTRACT - - /// owner - var/datum/object_system/storage/parent - -/atom/movable/storage_indirection/Initialize(mapload, datum/object_system/storage/parent) - src.parent = parent - return ..() - -/atom/movable/storage_indirection/Destroy() - if(src.parent.indirection == src) - src.parent.indirection = null - src.parent = null - return ..() - -/atom/movable/storage_indirection/CanReachIn(atom/movable/mover, atom/target, obj/item/tool, list/cache) - return TRUE - -/atom/movable/storage_indirection/CanReachOut(atom/movable/mover, atom/target, obj/item/tool, list/cache) - return TRUE - -/atom/movable/storage_indirection/Exited(atom/movable/AM, atom/newLoc) - . = ..() - if(isitem(AM)) - parent.on_item_exited(AM) - -/atom/movable/storage_indirection/Entered(atom/movable/AM, atom/oldLoc) - . = ..() - if(isitem(AM)) - parent.on_item_entered(AM) - -/atom/movable/storage_indirection/on_contents_weight_class_change(obj/item/item, old_weight_class, new_weight_class) - parent.on_contents_weight_class_change(item, old_weight_class, new_weight_class) - -/atom/movable/storage_indirection/on_contents_weight_volume_change(obj/item/item, old_weight_volume, new_weight_volume) - parent.on_contents_weight_volume_change(item, old_weight_volume, new_weight_volume) - -/atom/movable/storage_indirection/on_contents_weight_change(obj/item/item, old_weight, new_weight) - parent.on_contents_weight_change(item, old_weight, new_weight) - -/atom/movable/storage_indirection/on_contents_item_new(obj/item/item) - parent.on_contents_item_new(item) diff --git a/code/modules/admin/verbs/SDQL2/wrappers/map.dm b/code/modules/admin/verbs/SDQL2/wrappers/map.dm index 10eb86995ca1..ea7014d05c4f 100644 --- a/code/modules/admin/verbs/SDQL2/wrappers/map.dm +++ b/code/modules/admin/verbs/SDQL2/wrappers/map.dm @@ -1,5 +1,5 @@ //* This file is explicitly licensed under the MIT license. *// -//* Copyright (c) 2024 silicons *// +//* Copyright (c) 2024 Citadel Station Developers *// // * Mapping Functions * // @@ -156,9 +156,10 @@ results = range(radius, A) if(!length(results)) continue + . += results if(length(.) > safety) stack_trace("hit safety limit") - return + break else var/list/hashed = list() for(var/atom/A in movables) diff --git a/code/modules/admin/verbs/SDQL2/wrappers/math.dm b/code/modules/admin/verbs/SDQL2/wrappers/math.dm new file mode 100644 index 000000000000..e147b1b29490 --- /dev/null +++ b/code/modules/admin/verbs/SDQL2/wrappers/math.dm @@ -0,0 +1,28 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +// * Math Functions * // + +/proc/sdql_sin(n) + return sin(n) + +/proc/sdql_cos(n) + return cos(n) + +/proc/sdql_tan(n) + return tan(n) + +/proc/sdql_arctan(a, b) + return arctan(a, b) + +/proc/sdql_max(...) + return max(arglist(args)) + +/proc/sdql_min(...) + return min(arglist(args)) + +/proc/sdql_clamp(a, b, c) + return clamp(a, b, c) + +/proc/sdql_turn(dir, angle) + return turn(dir, angle) diff --git a/code/modules/examine/descriptions/stacks.dm b/code/modules/examine/descriptions/stacks.dm index ec7f8cc6f8cc..1f2b1085f229 100644 --- a/code/modules/examine/descriptions/stacks.dm +++ b/code/modules/examine/descriptions/stacks.dm @@ -19,6 +19,3 @@ /obj/item/stack/material/cyborg/steel description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it.
\ You can replenish your supply of metal as a synthetic by recharging." - -/obj/item/stack/material - description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it." diff --git a/code/modules/ghostroles/instantiator.dm b/code/modules/ghostroles/instantiator.dm index 2b532457ddf5..604ce5902a7b 100644 --- a/code/modules/ghostroles/instantiator.dm +++ b/code/modules/ghostroles/instantiator.dm @@ -67,8 +67,6 @@ return H /datum/ghostrole_instantiator/human/Equip(client/C, mob/M, list/params) - var/mob/living/carbon/human/H = M - // H.dna.species.before_equip_job(null, H) var/datum/outfit/O = GetOutfit(C, M, params) @@ -76,7 +74,6 @@ O = new O O.equip(M) - H.species.equip_survival_gear(H, TRUE, TRUE) // H.dna.species.after_equip_job(null, H) /** diff --git a/code/modules/materials/definitions/metals/steel.dm b/code/modules/materials/definitions/metals/steel.dm index 5e2488fe04e7..da0d73625da7 100644 --- a/code/modules/materials/definitions/metals/steel.dm +++ b/code/modules/materials/definitions/metals/steel.dm @@ -1,6 +1,13 @@ -/datum/prototype/material/steel +GENERATE_MATERIAL_STACKS(/steel) +DECLARE_MATERIAL(/steel) id = MAT_STEEL name = MAT_STEEL + + display_name = "steel" + + icon = 'icons/materials/metals/steel.dmi' + icon_stack_count = 3 + stack_type = /obj/item/stack/material/steel icon_base = 'icons/turf/walls/solid_wall.dmi' icon_reinf = 'icons/turf/walls/solid_wall_reinforced.dmi' diff --git a/code/modules/materials/material.dm b/code/modules/materials/material.dm index 248ed587c822..6c3450395419 100644 --- a/code/modules/materials/material.dm +++ b/code/modules/materials/material.dm @@ -132,6 +132,16 @@ /// material constraint flags - what we are considered var/material_constraints = NONE + //* Icon *// + /// Icon file. This is used for many miscellaneous states defined here. + var/icon + /// Count, from 1 to N, of stack states. + /// * If 3, and there's a stack of 50, we'll be `stack-1` from 1 to around 17, `stack-2` + /// from 18 to around 35, and `stack-3` for the rest. + /// * If null, no stack states are provided. + /// * If provided, a raw `stack` state should always be provided for on-map and in-UI previews. + var/icon_stack_count + //* Traits /// Material traits - set to list of paths to instance on New / register; associate them to their initial data. var/list/material_traits diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index bfb65929f36c..fbe144cf9964 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -14,8 +14,12 @@ ) drop_sound = 'sound/items/drop/axe.ogg' pickup_sound = 'sound/items/pickup/axe.ogg' + description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it." material_parts = MATERIAL_DEFAULT_DISABLED + + skip_legacy_icon_update = TRUE + /// material - direct ref because stack var/datum/prototype/material/material @@ -26,9 +30,14 @@ /obj/item/stack/material/Initialize(mapload, new_amount, merge = TRUE, material) if(!isnull(material)) src.material = material + src.material = RSmaterials.fetch_or_defer(src.material) if(src.material == REPOSITORY_FETCH_DEFER) stack_trace("material deferred on a material stack. this isn't supported.") + + if(src.material.icon && icon != src.material.icon) + icon = src.material.icon + . = ..() pixel_x = rand(0,4)-4 @@ -49,6 +58,11 @@ /obj/item/stack/material/get_materials(respect_multiplier) return list(material.id = (respect_multiplier? material_multiplier : 1) * SHEET_MATERIAL_AMOUNT) +/obj/item/stack/material/update_icon() + if(material.icon_stack_count) + icon_state = "stack-[min(ceil((amount / max_amount) * material.icon_stack_count), material.icon_stack_count)]" + return ..() + /obj/item/stack/material/tgui_recipes() var/list/assembled = ..() for(var/datum/stack_recipe/recipe as anything in material.get_recipes()) @@ -213,12 +227,6 @@ apply_colour = 1 no_variants = FALSE -/obj/item/stack/material/steel - name = MAT_STEEL - icon_state = "sheet-metal" - material = /datum/prototype/material/steel - no_variants = FALSE - /obj/item/stack/material/steel/hull name = MAT_STEELHULL material = /datum/prototype/material/steel/hull diff --git a/code/modules/mining/tools/vertibore.dm b/code/modules/mining/tools/vertibore.dm index 180c3ffd05fc..eb2319b91713 100644 --- a/code/modules/mining/tools/vertibore.dm +++ b/code/modules/mining/tools/vertibore.dm @@ -1,4 +1,3 @@ - /obj/item/vertibore name = "portable shaft excavation device" desc = "A heavily modified shaft bore utilizing phorogenic blasts to tunnel vertically through rock. Much faster than a large industrial drill unit, but is very resource- and power-intensive." @@ -8,7 +7,6 @@ icon_state = "vertibore" item_state = "vertibore" - var/obj/item/cell/cell //loaded cell var/power_cost = 1000 //10 shots off a highcap var/load_type = /obj/item/stack/material @@ -81,7 +79,7 @@ if(power_cost > cell.charge) to_chat(user, "The [src] flashes a warning light, it doesn't have enough charge to dig.") return - if(cell.use(power_cost) && do_after(user, 2.5 SECONDS)) + if(do_after(user, 2.5 SECONDS) && cell.use(power_cost)) var/turf/T = get_turf(user) LEGACY_EX_ACT(T, 1, null) diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index f7971dab6c18..15112d12b63e 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -2,6 +2,8 @@ /obj/item/holder name = "holder" desc = "You shouldn't ever see this." + icon = 'icons/system/blank_32x32.dmi' + icon_state = "" SET_APPEARANCE_FLAGS(KEEP_TOGETHER | PIXEL_SCALE | TILE_BOUND) slot_flags = SLOT_HEAD | SLOT_HOLSTER show_messages = 1 diff --git a/code/modules/mob/inventory/inventory-slot-equip.dm b/code/modules/mob/inventory/inventory-slot-equip.dm index 21cbe837e1e4..62fddfeb99f1 100644 --- a/code/modules/mob/inventory/inventory-slot-equip.dm +++ b/code/modules/mob/inventory/inventory-slot-equip.dm @@ -5,10 +5,10 @@ * Equips an item to a slot or deletes it. * * @params - * * Entity - Item being equipped. + * * entity - Item being equipped. * * type_or_id - A typepath, or string ID. * * inv_op_flags - INV_OP_* bits. - * * actors - Actor data of who did it. + * * actor - Actor data of who did it. * * @return TRUE / FALSE */ @@ -19,10 +19,10 @@ * Equips an item to a slot or drops it beneath our owner. * * @params - * * Entity - Item being equipped. + * * entity - Item being equipped. * * type_or_id - A typepath, or string ID. * * inv_op_flags - INV_OP_* bits. - * * actors - Actor data of who did it. + * * actor - Actor data of who did it. * * @return TRUE / FALSE */ @@ -36,10 +36,10 @@ * Equips an item to a slot if possible * * @params - * * Entity - Item being equipped. + * * entity - Item being equipped. * * type_or_id - A typepath, or string ID. * * inv_op_flags - INV_OP_* bits. - * * actors - Actor data of who did it. + * * actor - Actor data of who did it. * * @return TRUE / FALSE */ @@ -50,10 +50,10 @@ * Equips an item to a slot forcefully, trampling anything in the way. * * @params - * * Entity - Item being equipped. + * * entity - Item being equipped. * * type_or_id - A typepath, or string ID. * * inv_op_flags - INV_OP_* bits. - * * actors - Actor data of who did it. + * * actor - Actor data of who did it. * * @return TRUE / FALSE */ @@ -64,12 +64,38 @@ * Equips an item to a slot. This is the advanced version of the proc that returns an INV_RETURN_* result. * * @params - * * Entity - Item being equipped. + * * entity - Item being equipped. * * type_or_id - A typepath, or string ID. * * inv_op_flags - INV_OP_* bits. - * * actors - Actor data of who did it. + * * actor - Actor data of who did it. * * @return INV_RETURN_* */ /datum/inventory/proc/equip_to_slot(obj/item/entity, datum/inventory_slot/type_or_id, inv_op_flags, datum/event_args/actor/actor) return owner._equip_item(entity, inv_op_flags, type_or_id, actor?.performer) ? INV_RETURN_SUCCESS : INV_RETURN_FAILED + +/** + * Equips an item to an ordered list of slots. This is an advanced version of the proc that returns an INV_RETURN_* result + * + * @params + * * entity - item being equipped + * * slots - A list of: typepaths, or string ids + * * inv_op_flags - INV_OP_* bits + * * actor - actor data of who did it. + * + * @return INV_RETURN_* + */ +/datum/inventory/proc/equip_to_slots(obj/item/entity, list/datum/inventory_slot/slots, inv_op_flags, datum/event_args/actor/actor) + for(var/slot in slots) + switch(owner._equip_item(entity, inv_op_flags, slot, actor?.performer)) + if(INV_RETURN_DELETED) + return INV_RETURN_DELETED + if(INV_RETURN_FAILED) + continue + if(INV_RETURN_RELOCATED) + return INV_RETURN_RELOCATED + if(INV_RETURN_SUCCESS) + return INV_RETURN_SUCCESS + else + CRASH("unimplemented inv return: [.]") + return INV_RETURN_FAILED diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index abb3dd94c120..75e0e658cfd5 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -42,7 +42,7 @@ client.screen -= module_state_2 contents -= module_state_2 module_state_2.unequipped(src, SLOT_ID_HANDS, NONE) - module_state_1.on_unequipped(src, 2, NONE) + module_state_2.on_unequipped(src, 2, NONE) module_active = null module_state_2:loc = module module_state_2 = null @@ -54,7 +54,7 @@ client.screen -= module_state_3 contents -= module_state_3 module_state_3.unequipped(src, SLOT_ID_HANDS, NONE) - module_state_1.on_unequipped(src, 3, NONE) + module_state_3.on_unequipped(src, 3, NONE) module_active = null module_state_3:loc = module module_state_3 = null diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth.dm index 0f07603df036..7a2d7ceb611f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth.dm @@ -131,11 +131,10 @@ original_temp = heating_power //We remember our old goal, for use in non perpetual heating level increase /mob/living/simple_mob/vore/solarmoth/proc/explode() - src.anchored = 0 + set_anchored(FALSE) set_light(0) if(empulse(src, emp_heavy, emp_med, emp_light, emp_long)) qdel(src) - return /mob/living/simple_mob/vore/solarmoth/death() explode() @@ -145,16 +144,12 @@ explode() ..() - /mob/living/simple_mob/vore/solarmoth/handle_light() . = ..() if(. == 0 && !is_dead()) set_light(9.5, 1, mycolour) //9.5 makes the brightness range super huge. return 1 - -/mob/living/simple_mob/vore/solarmoth //active noms - /mob/living/simple_mob/vore/solarmoth/lunarmoth name = "Lunarmoth" desc = "A peculiar adult variation of a solargrub. Don't stare for too long and start running." diff --git a/code/modules/mob/mob-inventory-internal.dm b/code/modules/mob/mob-inventory-internal.dm index b080bc7ca19d..e267b69c5d92 100644 --- a/code/modules/mob/mob-inventory-internal.dm +++ b/code/modules/mob/mob-inventory-internal.dm @@ -33,12 +33,12 @@ var/obj/item/held = item_by_slot_id(SLOT_ID_BELT) if(flags & INV_OP_FORCE) return held?.obj_storage?.insert(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_SOUND) - return held?.obj_storage?.auto_handle_interacted_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND) + return held?.obj_storage?.auto_handle_inventory_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND) if(/datum/inventory_slot/abstract/put_in_backpack) var/obj/item/held = item_by_slot_id(SLOT_ID_BACK) if(flags & INV_OP_FORCE) return held?.obj_storage?.insert(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_SOUND) - return held?.obj_storage?.auto_handle_interacted_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND) + return held?.obj_storage?.auto_handle_inventory_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND) if(/datum/inventory_slot/abstract/put_in_hands) return put_in_hands(I, flags) if(/datum/inventory_slot/abstract/put_in_storage, /datum/inventory_slot/abstract/put_in_storage_try_active) @@ -48,7 +48,7 @@ if(active_storage?.insert(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING)) return TRUE else - if(active_storage?.auto_handle_interacted_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND)) + if(active_storage?.auto_handle_inventory_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND)) return TRUE for(var/obj/item/held in get_equipped_items_in_slots(list( SLOT_ID_BELT, @@ -62,7 +62,7 @@ continue if(flags & INV_OP_FORCE) return held.obj_storage.insert(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_SOUND) - return held.obj_storage.auto_handle_interacted_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND) + return held.obj_storage.auto_handle_inventory_insertion(I, new /datum/event_args/actor(src), flags & INV_OP_SUPPRESS_WARNING, flags & INV_OP_SUPPRESS_SOUND) return FALSE if(/datum/inventory_slot/abstract/attach_as_accessory) for(var/obj/item/clothing/C in get_equipped_items()) diff --git a/code/modules/mob/mob-inventory.dm b/code/modules/mob/mob-inventory.dm index fe69870ff7af..2207340baa24 100644 --- a/code/modules/mob/mob-inventory.dm +++ b/code/modules/mob/mob-inventory.dm @@ -408,7 +408,7 @@ * semantically returns true if we transferred something from our inventory to newloc in the call * * if the item is null, this returns true - * if an item is not in us, this crashes + * if an item is not in us, this returns FALSE */ /mob/proc/transfer_item_to_loc(obj/item/I, newloc, flags, mob/user) if(!I) @@ -424,7 +424,7 @@ * semantically returns true if we transferred something from our inventory to null in the call * * if the item is null, this returns true - * if an item is not in us, this crashes + * if an item is not in us, this returns false */ /mob/proc/transfer_item_to_nullspace(obj/item/I, flags, mob/user) if(!I) diff --git a/code/modules/organs/subtypes/nano.dm b/code/modules/organs/subtypes/nano.dm index e466cc56a486..c6a60e47236a 100644 --- a/code/modules/organs/subtypes/nano.dm +++ b/code/modules/organs/subtypes/nano.dm @@ -146,6 +146,11 @@ //Failure return 0 +/obj/item/organ/internal/nano/refactory/loaded + stored_materials = list( + MAT_STEEL = /obj/item/organ/internal/nano/refactory::max_storage, + ) + /obj/item/organ/internal/mmi_holder/posibrain/nano name = "protean posibrain" desc = "A more advanced version of the standard posibrain, typically found in protean bodies." diff --git a/code/modules/random_map/drop/drop_types.dm b/code/modules/random_map/drop/drop_types.dm index 802a54af3656..71562b900c41 100644 --- a/code/modules/random_map/drop/drop_types.dm +++ b/code/modules/random_map/drop/drop_types.dm @@ -267,9 +267,9 @@ var/global/list/datum/supply_drop_loot/supply_drop /datum/supply_drop_loot/materials/New() ..() contents = list( - /obj/fiftyspawner/steel, - /obj/fiftyspawner/steel, - /obj/fiftyspawner/steel, + /obj/item/stack/material/steel/full_stack, + /obj/item/stack/material/steel/full_stack, + /obj/item/stack/material/steel/full_stack, /obj/fiftyspawner/glass, /obj/fiftyspawner/glass, /obj/fiftyspawner/wood, @@ -283,7 +283,7 @@ var/global/list/datum/supply_drop_loot/supply_drop /datum/supply_drop_loot/materials_advanced/New() ..() contents = list( - /obj/fiftyspawner/steel, + /obj/item/stack/material/steel/full_stack, /obj/fiftyspawner/glass, /obj/fiftyspawner/wood, /obj/fiftyspawner/plastic, diff --git a/code/modules/species/outsider/scori.dm b/code/modules/species/outsider/scori.dm index 960fdfc90800..34ba50ec16a4 100644 --- a/code/modules/species/outsider/scori.dm +++ b/code/modules/species/outsider/scori.dm @@ -66,6 +66,3 @@ /mob/living/carbon/human/proc/hide_wings, /mob/living/carbon/human/proc/hide_tail ) - -/datum/species/scori/equip_survival_gear() - return diff --git a/code/modules/species/outsider/vox.dm b/code/modules/species/outsider/vox.dm index 847423b80fa6..593439488543 100644 --- a/code/modules/species/outsider/vox.dm +++ b/code/modules/species/outsider/vox.dm @@ -119,14 +119,40 @@ var/datum/prototype/language/species_language = RSlanguages.fetch(default_language) return species_language.get_random_name(gender) -/datum/species/vox/equip_survival_gear(mob/living/carbon/human/H, extendedtank = FALSE, comprehensive = FALSE) - . = ..() - - H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), SLOT_ID_MASK, INV_OP_SILENT | INV_OP_FLUFFLESS) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), SLOT_ID_BACK, INV_OP_SILENT | INV_OP_FLUFFLESS) +/datum/species/vox/apply_survival_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + // ensure they have a valid mask + var/mask_type = /obj/item/clothing/mask/breath + if(for_target) + var/obj/item/existing_mask = for_target.inventory.get_slot_single(/datum/inventory_slot/inventory/mask) + if(existing_mask?.clothing_flags & ALLOWINTERNALS) + else + if(for_target.temporarily_remove_from_inventory(existing_mask, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(existing_mask) + var/obj/item/creating_mask = new mask_type + if(for_target.inventory.equip_to_slot_if_possible(creating_mask, /datum/inventory_slot/inventory/mask, INV_OP_SILENT | INV_OP_FLUFFLESS)) + else + into_inv?.Add(creating_mask) + else + into_inv?.Add(mask_type) + else + into_inv?.Add(mask_type) + // ensure they have a vox tank + var/tank_type = /obj/item/tank/vox + if(for_target) + var/obj/item/tank/equipping_tank = new tank_type + var/could_place = TRUE + if(for_target.inventory.equip_to_slot_if_possible(equipping_tank, /datum/inventory_slot/inventory/pocket/left)) + else if(for_target.inventory.equip_to_slot_if_possible(equipping_tank, /datum/inventory_slot/inventory/pocket/right)) + else if(for_target.inventory.put_in_hands(equipping_tank)) + else + could_place = FALSE + if(could_place) + // todo: refactor this shit + for_target.internal = equipping_tank + for_target.internals.icon_state = "internal1" + else + into_inv?.Add(tank_type) else - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), /datum/inventory_slot/abstract/hand/right, INV_OP_SILENT | INV_OP_FLUFFLESS) - H.internal = locate(/obj/item/tank) in H.contents - if(istype(H.internal,/obj/item/tank) && H.internals) - H.internals.icon_state = "internal1" + into_inv?.Add(tank_type) + + return ..() diff --git a/code/modules/species/promethean/promethean.dm b/code/modules/species/promethean/promethean.dm index 5f4f719f95a0..96917863c673 100644 --- a/code/modules/species/promethean/promethean.dm +++ b/code/modules/species/promethean/promethean.dm @@ -153,7 +153,9 @@ var/datum/species/shapeshifter/promethean/prometheans ..() prometheans = src -/datum/species/shapeshifter/promethean/equip_survival_gear(mob/living/carbon/human/H) +/datum/species/shapeshifter/promethean/apply_survival_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + . = ..() + var/boxtype = pick(list( /obj/item/storage/toolbox/lunchbox, /obj/item/storage/toolbox/lunchbox/heart, @@ -165,13 +167,9 @@ var/datum/species/shapeshifter/promethean/prometheans /obj/item/storage/toolbox/lunchbox/syndicate )) //Only pick the empty types - var/obj/item/storage/toolbox/lunchbox/L = new boxtype(get_turf(H)) + var/obj/item/storage/toolbox/lunchbox/L = new boxtype new /obj/item/reagent_containers/food/snacks/wrapped/proteinbar(L) - new /obj/item/tool/prybar/red(L) - if(H.backbag == 1) - H.equip_to_slot_or_del(L, /datum/inventory_slot/abstract/hand/right) - else - H.equip_to_slot_or_del(L, /datum/inventory_slot/abstract/put_in_backpack) + into_inv += L /datum/species/shapeshifter/promethean/hug(mob/living/carbon/human/H, mob/living/target) diff --git a/code/modules/species/protean/protean.dm b/code/modules/species/protean/protean.dm index b0840303649c..74a28eea0e29 100644 --- a/code/modules/species/protean/protean.dm +++ b/code/modules/species/protean/protean.dm @@ -70,8 +70,9 @@ has_organ = list( O_BRAIN = /obj/item/organ/internal/mmi_holder/posibrain/nano, O_ORCH = /obj/item/organ/internal/nano/orchestrator, - O_FACT = /obj/item/organ/internal/nano/refactory + O_FACT = /obj/item/organ/internal/nano/refactory/loaded, ) + vision_organ = O_BRAIN has_limbs = list( BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable/nano), @@ -173,18 +174,11 @@ var/obj/item/hardsuit/protean/prig = new /obj/item/hardsuit/protean(H) prig.myprotean = H -/datum/species/protean/equip_survival_gear(var/mob/living/carbon/human/H) - var/obj/item/storage/box/box = new /obj/item/storage/box/survival/synth(H) - var/obj/item/stack/material/steel/metal_stack = new(box) - metal_stack.amount = 3 // Less starting steel due to regen changes - new /obj/item/fbp_backup_cell(box) - var/obj/item/clothing/accessory/permit/nanotech/permit = new(box) - permit.set_name(H.real_name) - - if(H.backbag == 1) //Somewhat misleading, 1 == no bag (not boolean) - H.equip_to_slot_or_del(box, /datum/inventory_slot/abstract/hand/left) - else - H.equip_to_slot_or_del(box, /datum/inventory_slot/abstract/put_in_backpack) +/datum/species/protean/apply_racial_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + var/obj/item/clothing/accessory/permit/nanotech/permit = new + permit.set_name(for_target.real_name) + into_box?.Add(permit) + return ..() /datum/species/protean/get_blood_colour(var/mob/living/carbon/human/H) return rgb(80,80,80,230) diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm index c94cfb4b646b..b7bbcbef64a2 100644 --- a/code/modules/species/species.dm +++ b/code/modules/species/species.dm @@ -512,6 +512,10 @@ //! LEGACY is_subspecies = id != uid superspecies_id = id + if(!id) + id = uid + if(!uid) + uid = id if(hud_type) hud = new hud_type() @@ -630,50 +634,81 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list( GAS_ID_CARBON_DIOXIDE = /obj/item/tank/emergency/carbon_dioxide )) -/datum/species/proc/equip_survival_gear(var/mob/living/carbon/human/H,var/extendedtank = 0,var/comprehensive = 0) - var/boxtype = /obj/item/storage/box/survival //Default survival box - - var/synth = H.isSynthetic() - - //Empty box for synths - if(synth) - boxtype = /obj/item/storage/box/survival/synth +/** + * Injects spawn descriptors into `into_box` and `into_inv` lists. Both must be provided. + * + * Descriptors can be; + * * a typepath + * * an anonymous type + * + * Notes: + * * The `into_box` and `into_inv` lists should always be added to via `?.Add()`, incase they are null. + * * Returned lists **must** be handled. If you aren't equipping anything, properly qdel() any spawned items, or + * a memory leak will result. + * + * @params + * * for_target - (optional) person who is getting survival gear. if this is not provided, default + * survival gear that would go on them through inventory calls should be put into `into_inv`. + * * into_box - things to put into their survival kit. do not put anything large in here. + * * into_inv - things to make sure they have somewhere on, or near them. anything large can be put in here. + * things will not necessarily be put in their backpack, as an example a wheelchair would be put under them. + */ +/datum/species/proc/apply_racial_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + return - //Special box with extra equipment - else if(comprehensive) - boxtype = /obj/item/storage/box/survival/comp +/** + * Injects spawn descriptors into `into_box` and `into_inv` lists. Both must be provided. + * + * Descriptors can be; + * * a typepath + * * an anonymous type + * + * Notes: + * * The `into_box` and `into_inv` lists should always be added to via `?.Add()`, incase they are null. + * * Returned lists **must** be handled. If you aren't equipping anything, properly qdel() any spawned items, or + * a memory leak will result. + * + * @params + * * for_target - (optional) person who is getting survival gear. if this is not provided, default + * survival gear that would go on them through inventory calls should be put into `into_inv`. + * * into_box - things to put into their survival kit. do not put anything large in here. + * * into_inv - things to make sure they have somewhere on, or near them. anything large can be put in here. + * things will not necessarily be put in their backpack, as an example a wheelchair would be put under them. + */ +/datum/species/proc/apply_survival_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + into_box?.Add(/obj/item/tool/prybar/red) - //Create the box - var/obj/item/storage/box/box = new boxtype(H) + // todo: crank flashlight + prybar combo? + into_box?.Add(/obj/item/flashlight/flare/survival) - //If not synth, they get an air tank (if they breathe) - if(!synth && breath_type) - //Create a tank (if such a thing exists for this species) - var/given_path = GLOB.species_oxygen_tank_by_gas[breath_type] - var/tankpath - if(extendedtank) + if(for_target.isSynthetic()) + into_box?.Add(/obj/item/fbp_backup_cell) + else + into_box?.Add( + /obj/item/clothing/mask/breath, + /obj/item/stack/medical/bruise_pack, + /obj/item/reagent_containers/hypospray/autoinjector, + /obj/item/reagent_containers/food/snacks/wrapped/proteinbar, + /obj/item/clothing/glasses/goggles, + ) + + if(breath_type) + var/given_path = GLOB.species_oxygen_tank_by_gas[breath_type] + var/tankpath + + // always extended now! + // if(extendedtank) tankpath = text2path("[given_path]" + "/engi") if(!tankpath) //Is it just that there's no /engi? tankpath = text2path("[given_path]" + "/double") - if(!tankpath) - tankpath = given_path + if(!tankpath) + tankpath = given_path - if(tankpath) - new tankpath(box) - else - stack_trace("Could not find a tank path for breath type [breath_type], given path was [given_path].") - - //If they are synth, they get a smol battery - else if(synth) - new /obj/item/fbp_backup_cell(box) - - box.obj_storage.fit_to_contents(no_shrink = TRUE) - - if(H.backbag == 1) - H.equip_to_slot_or_del(box, /datum/inventory_slot/abstract/hand/right, INV_OP_SILENT | INV_OP_FLUFFLESS) - else - H.equip_to_slot_or_del(box, /datum/inventory_slot/abstract/put_in_backpack, INV_OP_FORCE | INV_OP_SILENT) + if(tankpath) + into_box?.Add(tankpath) + else + stack_trace("Could not find a tank path for breath type [breath_type], given path was [given_path].") /** * called to ensure organs are consistent with our species's diff --git a/code/modules/species/station/adherent.dm b/code/modules/species/station/adherent.dm index f55fd5a8f4ae..11a278e95e43 100644 --- a/code/modules/species/station/adherent.dm +++ b/code/modules/species/station/adherent.dm @@ -151,8 +151,11 @@ /datum/inventory_slot/inventory/id::id, ) -/datum/species/adherent/equip_survival_gear(mob/living/carbon/human/H, extendedtank = FALSE, comprehensive = FALSE) - H.equip_to_slot_or_del(new /obj/item/storage/belt/utility/crystal, /datum/inventory_slot/abstract/put_in_backpack) +/datum/species/adherent/apply_racial_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + var/obj/item/storage/belt/utility/crystal/give_them_the_toolbelt = new + if(!for_target?.inventory?.equip_to_slot_if_possible(give_them_the_toolbelt, /datum/inventory_slot/inventory/belt)) + into_inv += give_them_the_toolbelt + return ..() /datum/species/adherent/New() /*equip_adjust = list( diff --git a/code/modules/species/station/custom_species.dm b/code/modules/species/station/custom_species.dm index 2dfdcf2295d3..d4596f74d607 100644 --- a/code/modules/species/station/custom_species.dm +++ b/code/modules/species/station/custom_species.dm @@ -68,32 +68,3 @@ var/datum/species/real = SScharacters.resolve_species_name(base_species) return real.real_race_key(H) -// Stub species overrides for shoving trait abilities into - -//Called when face-down in the water or otherwise over their head. -// Return: TRUE for able to breathe fine in water. -/datum/species/custom/can_breathe_water() - return ..() - -//Called during handle_environment in Life() ticks. -// Return: Not used. -/datum/species/custom/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt) - return ..() - -//Called when spawning to equip them with special things. -/datum/species/custom/equip_survival_gear(mob/living/carbon/human/H) - /* Example, from Vox: - H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), SLOT_ID_MASK) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), SLOT_ID_BACK) - H.equip_to_slot_or_del(new /obj/item/storage/box/vox(H), /datum/inventory_slot/abstract/hand/right) - H.internal = H.back - else - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), /datum/inventory_slot/abstract/hand/right) - H.equip_to_slot_or_del(new /obj/item/storage/box/vox(H.back), /datum/inventory_slot/abstract/put_in_backpack) - H.internal = H.r_hand - H.internal = locate(/obj/item/tank) in H.contents - if(istype(H.internal,/obj/item/tank) && H.internals) - H.internals.icon_state = "internal1" - */ - return ..() diff --git a/code/modules/species/station/diona.dm b/code/modules/species/station/diona.dm index 18c736fc3852..52bcd43f3d3c 100644 --- a/code/modules/species/station/diona.dm +++ b/code/modules/species/station/diona.dm @@ -148,12 +148,6 @@ return TRUE return FALSE -/datum/species/diona/equip_survival_gear(mob/living/carbon/human/H) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/flashlight/flare(H), /datum/inventory_slot/abstract/hand/right) - else - H.equip_to_slot_or_del(new /obj/item/flashlight/flare(H.back), /datum/inventory_slot/abstract/put_in_backpack) - /datum/species/diona/handle_death(mob/living/carbon/human/H) var/mob/living/carbon/alien/diona/S = new(get_turf(H)) diff --git a/code/modules/species/station/phoronoids.dm b/code/modules/species/station/phoronoids.dm index 3033d87f7d5c..c56d37cf5d3c 100644 --- a/code/modules/species/station/phoronoids.dm +++ b/code/modules/species/station/phoronoids.dm @@ -102,143 +102,174 @@ H.IgniteMob() enviroment_bad = FALSE -/datum/species/phoronoid/equip_survival_gear(mob/living/carbon/human/H, extendedtank = FALSE, comprehensive = FALSE) - . = ..() - var/suit = /obj/item/clothing/suit/space/plasman - var/helm = /obj/item/clothing/head/helmet/space/plasman +/datum/species/phoronoid/apply_survival_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + // ensure they have a valid mask + var/mask_type = /obj/item/clothing/mask/breath + if(for_target) + var/obj/item/existing_mask = for_target.inventory.get_slot_single(/datum/inventory_slot/inventory/mask) + if(existing_mask?.clothing_flags & ALLOWINTERNALS) + else + into_inv?.Add(existing_mask) + for_target.temporarily_remove_from_inventory(existing_mask, INV_OP_FORCE) + for_target.equip_to_slot_or_del(new mask_type(for_target), /datum/inventory_slot/inventory/mask, INV_OP_SILENT | INV_OP_FLUFFLESS) + else + into_inv?.Add(mask_type) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), SLOT_ID_MASK) + var/suit_path = /obj/item/clothing/suit/space/plasman + var/helm_path = /obj/item/clothing/head/helmet/space/plasman - switch(H.mind?.assigned_role) + // todo: deal with this dumpster fire of a switch + switch(for_target.mind?.assigned_role) if("Security Officer") - suit=/obj/item/clothing/suit/space/plasman/sec - helm=/obj/item/clothing/head/helmet/space/plasman/sec + suit_path = /obj/item/clothing/suit/space/plasman/sec + helm_path = /obj/item/clothing/head/helmet/space/plasman/sec if("Detective") - suit=/obj/item/clothing/suit/space/plasman/sec/detective - helm=/obj/item/clothing/head/helmet/space/plasman/sec/detective + suit_path = /obj/item/clothing/suit/space/plasman/sec/detective + helm_path = /obj/item/clothing/head/helmet/space/plasman/sec/detective if("Warden") - suit=/obj/item/clothing/suit/space/plasman/sec/warden - helm=/obj/item/clothing/head/helmet/space/plasman/sec + suit_path = /obj/item/clothing/suit/space/plasman/sec/warden + helm_path = /obj/item/clothing/head/helmet/space/plasman/sec if("Head of Security") - suit=/obj/item/clothing/suit/space/plasman/sec/hos - helm=/obj/item/clothing/head/helmet/space/plasman/sec/hos + suit_path = /obj/item/clothing/suit/space/plasman/sec/hos + helm_path = /obj/item/clothing/head/helmet/space/plasman/sec/hos if("Facility Director") - suit=/obj/item/clothing/suit/space/plasman/sec/captain - helm=/obj/item/clothing/head/helmet/space/plasman/sec/captain + suit_path = /obj/item/clothing/suit/space/plasman/sec/captain + helm_path = /obj/item/clothing/head/helmet/space/plasman/sec/captain if("Head of Personnel") - suit=/obj/item/clothing/suit/space/plasman/sec/hop - helm=/obj/item/clothing/head/helmet/space/plasman/sec/hop + suit_path = /obj/item/clothing/suit/space/plasman/sec/hop + helm_path = /obj/item/clothing/head/helmet/space/plasman/sec/hop if("Scientist","Roboticist","Xenobiologist") - suit=/obj/item/clothing/suit/space/plasman/science - helm=/obj/item/clothing/head/helmet/space/plasman/science + suit_path = /obj/item/clothing/suit/space/plasman/science + helm_path = /obj/item/clothing/head/helmet/space/plasman/science if("Explorer","Pilot","Pathfinder") - suit=/obj/item/clothing/suit/space/plasman/science/explorer - helm=/obj/item/clothing/head/helmet/space/plasman/science/explorer + suit_path = /obj/item/clothing/suit/space/plasman/science/explorer + helm_path = /obj/item/clothing/head/helmet/space/plasman/science/explorer if("Research Director") - suit=/obj/item/clothing/suit/space/plasman/science/rd - helm=/obj/item/clothing/head/helmet/space/plasman/science/rd + suit_path = /obj/item/clothing/suit/space/plasman/science/rd + helm_path = /obj/item/clothing/head/helmet/space/plasman/science/rd if("Station Engineer") - suit=/obj/item/clothing/suit/space/plasman/engi/ - helm=/obj/item/clothing/head/helmet/space/plasman/engi/ + suit_path = /obj/item/clothing/suit/space/plasman/engi/ + helm_path = /obj/item/clothing/head/helmet/space/plasman/engi/ if("Chief Engineer") - suit=/obj/item/clothing/suit/space/plasman/engi/ce - helm=/obj/item/clothing/head/helmet/space/plasman/engi/ce + suit_path = /obj/item/clothing/suit/space/plasman/engi/ce + helm_path = /obj/item/clothing/head/helmet/space/plasman/engi/ce if("Atmospheric Technician") - suit=/obj/item/clothing/suit/space/plasman/engi/atmos - helm=/obj/item/clothing/head/helmet/space/plasman/engi/atmos + suit_path = /obj/item/clothing/suit/space/plasman/engi/atmos + helm_path = /obj/item/clothing/head/helmet/space/plasman/engi/atmos if("Medical Doctor","Paramedic","Psychiatrist") - suit=/obj/item/clothing/suit/space/plasman/med - helm=/obj/item/clothing/head/helmet/space/plasman/med + suit_path = /obj/item/clothing/suit/space/plasman/med + helm_path = /obj/item/clothing/head/helmet/space/plasman/med if("Field Medic") - suit=/obj/item/clothing/suit/space/plasman/med/rescue - helm=/obj/item/clothing/head/helmet/space/plasman/med/rescue + suit_path = /obj/item/clothing/suit/space/plasman/med/rescue + helm_path = /obj/item/clothing/head/helmet/space/plasman/med/rescue if("Chemist") - suit=/obj/item/clothing/suit/space/plasman/med/chemist - helm=/obj/item/clothing/head/helmet/space/plasman/med/chemist + suit_path = /obj/item/clothing/suit/space/plasman/med/chemist + helm_path = /obj/item/clothing/head/helmet/space/plasman/med/chemist if("Chief Medical Officer") - suit=/obj/item/clothing/suit/space/plasman/med/cmo - helm=/obj/item/clothing/head/helmet/space/plasman/med/cmo + suit_path = /obj/item/clothing/suit/space/plasman/med/cmo + helm_path = /obj/item/clothing/head/helmet/space/plasman/med/cmo if("Bartender","Chef") - suit=/obj/item/clothing/suit/space/plasman/service - helm=/obj/item/clothing/head/helmet/space/plasman/service + suit_path = /obj/item/clothing/suit/space/plasman/service + helm_path = /obj/item/clothing/head/helmet/space/plasman/service if("Cargo Technician","Quartermaster") - suit=/obj/item/clothing/suit/space/plasman/cargo - helm=/obj/item/clothing/head/helmet/space/plasman/cargo + suit_path = /obj/item/clothing/suit/space/plasman/cargo + helm_path = /obj/item/clothing/head/helmet/space/plasman/cargo if("Shaft Miner") - suit=/obj/item/clothing/suit/space/plasman/cargo/miner - helm=/obj/item/clothing/head/helmet/space/plasman/cargo/miner + suit_path = /obj/item/clothing/suit/space/plasman/cargo/miner + helm_path = /obj/item/clothing/head/helmet/space/plasman/cargo/miner if("Botanist") - suit=/obj/item/clothing/suit/space/plasman/botanist - helm=/obj/item/clothing/head/helmet/space/plasman/botanist + suit_path = /obj/item/clothing/suit/space/plasman/botanist + helm_path = /obj/item/clothing/head/helmet/space/plasman/botanist if("Chaplain") - suit=/obj/item/clothing/suit/space/plasman/chaplain - helm=/obj/item/clothing/head/helmet/space/plasman/chaplain + suit_path = /obj/item/clothing/suit/space/plasman/chaplain + helm_path = /obj/item/clothing/head/helmet/space/plasman/chaplain if("Janitor") - suit=/obj/item/clothing/suit/space/plasman/janitor - helm=/obj/item/clothing/head/helmet/space/plasman/janitor + suit_path = /obj/item/clothing/suit/space/plasman/janitor + helm_path = /obj/item/clothing/head/helmet/space/plasman/janitor if("Internal Affairs Agent","Command Secretary") - suit=/obj/item/clothing/suit/space/plasman/fancy - helm=/obj/item/clothing/head/helmet/space/plasman/fancy + suit_path = /obj/item/clothing/suit/space/plasman/fancy + helm_path = /obj/item/clothing/head/helmet/space/plasman/fancy if("Visitor") - suit=/obj/item/clothing/suit/space/plasman/assistant - helm=/obj/item/clothing/head/helmet/space/plasman/assistant + suit_path = /obj/item/clothing/suit/space/plasman/assistant + helm_path = /obj/item/clothing/head/helmet/space/plasman/assistant if("Clown") - suit=/obj/item/clothing/suit/space/plasman/clown - helm=/obj/item/clothing/head/helmet/space/plasman/clown + suit_path = /obj/item/clothing/suit/space/plasman/clown + helm_path = /obj/item/clothing/head/helmet/space/plasman/clown if("Mime") - suit=/obj/item/clothing/suit/space/plasman/mime - helm=/obj/item/clothing/head/helmet/space/plasman/mime - H.equip_to_slot_or_del(new suit(H), SLOT_ID_SUIT) - H.equip_to_slot_or_del(new helm(H), SLOT_ID_HEAD) - H.put_in_hands_or_del(new /obj/item/extinguisher/mini/plasman(H)) - - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), SLOT_ID_BACK) - H.internal = H.back + suit_path = /obj/item/clothing/suit/space/plasman/mime + helm_path = /obj/item/clothing/head/helmet/space/plasman/mime + + into_inv += /obj/item/extinguisher/mini/plasman + + if(for_target) + var/obj/item/existing_head_slot = for_target.inventory.get_slot_single(/datum/inventory_slot/inventory/head) + var/obj/item/existing_suit_slot = for_target.inventory.get_slot_single(/datum/inventory_slot/inventory/suit) + var/obj/item/creating_head_slot = new helm_path + var/obj/item/creating_suit_slot = new suit_path + if(existing_head_slot) + if(for_target.temporarily_remove_from_inventory(existing_head_slot, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(existing_head_slot) + if(!for_target.inventory.equip_to_slot_if_possible(creating_head_slot, /datum/inventory_slot/inventory/head, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(creating_head_slot) + else + into_inv?.Add(creating_head_slot) + if(existing_suit_slot) + if(for_target.temporarily_remove_from_inventory(existing_suit_slot, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(existing_suit_slot) + if(!for_target.inventory.equip_to_slot_if_possible(creating_suit_slot, /datum/inventory_slot/inventory/suit, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(creating_suit_slot) + else + into_inv?.Add(creating_suit_slot) + else + into_inv?.Add(helm_path) + into_inv?.Add(suit_path) + + //! legacy: just in case + for_target.ExtinguishMob() + + // ensure they have a vox tank + var/tank_type = /obj/item/tank/vox + if(for_target) + var/obj/item/tank/equipping_tank = new tank_type + var/could_place = TRUE + if(for_target.inventory.equip_to_slot_if_possible(equipping_tank, /datum/inventory_slot/inventory/pocket/left)) + else if(for_target.inventory.equip_to_slot_if_possible(equipping_tank, /datum/inventory_slot/inventory/pocket/right)) + else if(for_target.inventory.equip_to_slot_if_possible(equipping_tank, /datum/inventory_slot/inventory/suit_storage)) + else if(for_target.inventory.put_in_hands(equipping_tank)) + else + could_place = FALSE + if(could_place) + // todo: refactor this shit + for_target.internal = equipping_tank + for_target.internals.icon_state = "internal1" + else + into_inv?.Add(tank_type) else - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), SLOT_ID_SUIT_STORAGE) - H.internal = H.s_store - - H.internal = locate(/obj/item/tank) in H.contents - if(istype(H.internal,/obj/item/tank) && H.internals) - H.internals.icon_state = "internal1" - - spawn(2) - if(H.head && !istype(H.head,/obj/item/clothing/head/helmet/space/plasman)) - qdel(H.head) - H.equip_to_slot_or_del(new helm(H), SLOT_ID_HEAD) - if(H.on_fire) - H.ExtinguishMob() - - if(H.wear_suit && !istype(H.wear_suit,/obj/item/clothing/suit/space/plasman)) - qdel(H.wear_suit) - H.equip_to_slot_or_del(new suit(H), SLOT_ID_SUIT) - if(H.on_fire) - H.ExtinguishMob() - H.equip_to_slot_or_del(new /obj/item/tank/vox(H), SLOT_ID_SUIT_STORAGE) - H.internal = H.s_store + into_inv?.Add(tank_type) + + return ..() diff --git a/code/modules/species/station/standard/tajaran.dm b/code/modules/species/station/standard/tajaran.dm index 1e8b8b3bb9cd..b459f8d92664 100644 --- a/code/modules/species/station/standard/tajaran.dm +++ b/code/modules/species/station/standard/tajaran.dm @@ -127,6 +127,12 @@ /mob/living/carbon/human/proc/hide_tail, ) -/datum/species/tajaran/equip_survival_gear(mob/living/carbon/human/H) - . = ..() - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), SLOT_ID_SHOES) +/datum/species/tajaran/apply_racial_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + var/footwear_type = /obj/item/clothing/shoes/sandal + if(for_target && !for_target.inventory?.get_slot_single(/datum/inventory_slot/inventory/shoes)) + var/obj/item/footwear_instance = new footwear_type + if(!for_target.inventory.equip_to_slot_if_possible(footwear_instance, /datum/inventory_slot/inventory/shoes)) + into_inv += footwear_instance + else + into_inv += footwear_type + return ..() diff --git a/code/modules/species/station/standard/teshari.dm b/code/modules/species/station/standard/teshari.dm index 2a387379d718..699ca60bd146 100644 --- a/code/modules/species/station/standard/teshari.dm +++ b/code/modules/species/station/standard/teshari.dm @@ -178,10 +178,15 @@ /obj/item/clothing/suit/straight_jacket, ) - -/datum/species/teshari/equip_survival_gear(mob/living/carbon/human/H) - ..() - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),SLOT_ID_SHOES) +/datum/species/teshari/apply_racial_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + var/footwear_type = /obj/item/clothing/shoes/sandal + if(for_target && !for_target.inventory?.get_slot_single(/datum/inventory_slot/inventory/shoes)) + var/obj/item/footwear_instance = new footwear_type + if(!for_target.inventory.equip_to_slot_if_possible(footwear_instance, /datum/inventory_slot/inventory/shoes)) + into_inv += footwear_instance + else + into_inv += footwear_type + return ..() /datum/species/teshari/handle_falling(mob/living/carbon/human/H, atom/hit_atom, damage_min, damage_max, silent, planetary) diff --git a/code/modules/species/station/standard/unathi.dm b/code/modules/species/station/standard/unathi.dm index fc7f8fcac053..c0831d4bf9f8 100644 --- a/code/modules/species/station/standard/unathi.dm +++ b/code/modules/species/station/standard/unathi.dm @@ -145,6 +145,12 @@ /mob/living/carbon/human/proc/hide_tail, ) -/datum/species/unathi/equip_survival_gear(mob/living/carbon/human/H) - . = ..() - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), SLOT_ID_SHOES) +/datum/species/unathi/apply_racial_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + var/footwear_type = /obj/item/clothing/shoes/sandal + if(for_target && !for_target.inventory?.get_slot_single(/datum/inventory_slot/inventory/shoes)) + var/obj/item/footwear_instance = new footwear_type + if(!for_target.inventory.equip_to_slot_if_possible(footwear_instance, /datum/inventory_slot/inventory/shoes)) + into_inv += footwear_instance + else + into_inv += footwear_type + return ..() diff --git a/code/modules/species/station/standard/zaddat.dm b/code/modules/species/station/standard/zaddat.dm index 911a4a28ec52..044723cb907e 100644 --- a/code/modules/species/station/standard/zaddat.dm +++ b/code/modules/species/station/standard/zaddat.dm @@ -96,30 +96,46 @@ descriptors = list() -/datum/species/zaddat/equip_survival_gear(mob/living/carbon/human/H) - ..() - if(H.wear_suit) //get rid of job labcoats so they don't stop us from equipping the Shroud - qdel(H.wear_suit) //if you know how to gently set it in like, their backpack or whatever, be my guest - if(H.wear_mask) - qdel(H.wear_mask) - if(H.head) - qdel(H.head) - - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/zaddat/(H), SLOT_ID_MASK) // mask has to come first or Shroud helmet will get in the way - H.equip_to_slot_or_del(new /obj/item/clothing/suit/space/void/zaddat/(H), SLOT_ID_SUIT) - - var/obj/item/storage/toolbox/lunchbox/survival/L = new(H) +/datum/species/zaddat/apply_survival_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) + // ensure they have a valid mask + var/mask_type = /obj/item/clothing/mask/gas/zaddat + if(for_target) + var/obj/item/existing_mask = for_target.inventory.get_slot_single(/datum/inventory_slot/inventory/mask) + if(for_target.temporarily_remove_from_inventory(existing_mask, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(existing_mask) + var/obj/item/creating_mask = new mask_type + if(for_target.inventory.equip_to_slot_if_possible(creating_mask, /datum/inventory_slot/inventory/mask, INV_OP_SILENT | INV_OP_FLUFFLESS)) + else + into_inv?.Add(creating_mask) + else + into_inv?.Add(mask_type) + else + into_inv?.Add(mask_type) + + var/suit_path = /obj/item/clothing/suit/space/void/zaddat + if(for_target) + var/obj/item/existing_suit_slot = for_target.inventory.get_slot_single(/datum/inventory_slot/inventory/suit) + var/obj/item/creating_suit_slot = new suit_path + if(existing_suit_slot) + if(for_target.temporarily_remove_from_inventory(existing_suit_slot, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(existing_suit_slot) + if(!for_target.inventory.equip_to_slot_if_possible(creating_suit_slot, /datum/inventory_slot/inventory/suit, INV_OP_FORCE | INV_OP_SILENT)) + into_inv?.Add(creating_suit_slot) + else + into_inv?.Add(creating_suit_slot) + else + into_inv?.Add(suit_path) + + var/obj/item/storage/toolbox/lunchbox/survival/L = new new /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose(L) new /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose(L) new /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose(L) new /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose(L) new /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose(L) new /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose(L) + into_inv += L - if(H.backbag == 1) - H.put_in_hands_or_del(L) - else - H.equip_to_slot_or_del(L, /datum/inventory_slot/abstract/put_in_backpack) + return ..() /datum/species/zaddat/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt) diff --git a/icons/README.md b/icons/README.md index 29507811d3e8..f12e24330b6c 100644 --- a/icons/README.md +++ b/icons/README.md @@ -28,6 +28,7 @@ Yes, this currently includes all turfs, mobs, objs, and misc things. Sorry. We'l - /helpers - mapping helpers like autopipe/autocable/baseturf replacers go here - /landmarks - landmark icons - /spawners - things like window spawners + - /materials - material sprites - /mob - mob sprites - /bodysets - limbs and their corrosponding sprite accessories & markings & miscellaneous. used in the abstraction of limb sprite from limb definition. diff --git a/icons/materials/metals/steel.dmi b/icons/materials/metals/steel.dmi new file mode 100644 index 000000000000..a6d60b5e2a8f Binary files /dev/null and b/icons/materials/metals/steel.dmi differ diff --git a/maps/endeavour/levels/flagship.dmm b/maps/endeavour/levels/flagship.dmm index 2b482e7554d8..fd734c7363ba 100644 --- a/maps/endeavour/levels/flagship.dmm +++ b/maps/endeavour/levels/flagship.dmm @@ -15084,14 +15084,14 @@ /area/centcom/security) "Vj" = ( /obj/structure/table/steel_reinforced, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, /turf/unsimulated/floor{ icon_state = "dark" }, diff --git a/maps/rift/levels/rift-05-surface2.dmm b/maps/rift/levels/rift-05-surface2.dmm index c115095ab382..2c91b54b863b 100644 --- a/maps/rift/levels/rift-05-surface2.dmm +++ b/maps/rift/levels/rift-05-surface2.dmm @@ -9969,26 +9969,26 @@ desc = null; pixel_y = 24 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8; pixel_y = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8; pixel_y = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8; pixel_y = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8; pixel_y = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8 }, /turf/simulated/floor/tiled/white, diff --git a/maps/rift/levels/rift-11-orbital.dmm b/maps/rift/levels/rift-11-orbital.dmm index 64ee068034da..51a154262ab2 100644 --- a/maps/rift/levels/rift-11-orbital.dmm +++ b/maps/rift/levels/rift-11-orbital.dmm @@ -9573,14 +9573,14 @@ /area/centcom/specops) "Vb" = ( /obj/structure/table/steel_reinforced, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, /turf/unsimulated/floor/dark, /area/centcom/specops) "Vd" = ( diff --git a/maps/sectors/admin_planets_192/andromeda.dmm b/maps/sectors/admin_planets_192/andromeda.dmm index 17dcc5bf1efd..21dce2c0dbd3 100644 --- a/maps/sectors/admin_planets_192/andromeda.dmm +++ b/maps/sectors/admin_planets_192/andromeda.dmm @@ -3500,25 +3500,25 @@ /area/admin_planet/andromeda/sec_briefing) "kE" = ( /obj/structure/table/rack/shelf, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -6; pixel_y = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8; pixel_y = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8; pixel_y = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -6 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -6; pixel_y = -8 }, diff --git a/maps/sectors/admin_planets_192/croatoan.dmm b/maps/sectors/admin_planets_192/croatoan.dmm index 33761393dfae..5bd53c6c9b6d 100644 --- a/maps/sectors/admin_planets_192/croatoan.dmm +++ b/maps/sectors/admin_planets_192/croatoan.dmm @@ -5377,15 +5377,15 @@ /area/admin_planet/croatoan/civ_bar_public) "sN" = ( /obj/structure/table/reinforced, -/obj/item/storage/hypokit, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded, +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8; pixel_y = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8; pixel_y = 8 }, @@ -10471,27 +10471,27 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/storage/hypokit, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded, +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8; pixel_y = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = -8; pixel_y = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8; pixel_y = 8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8; pixel_y = -8 }, -/obj/item/storage/hypokit{ +/obj/item/storage/hypokit/full/loaded{ pixel_x = 8 }, /obj/effect/floor_decal/corner_techfloor_grid/diagonal, diff --git a/maps/sectors/admin_planets_192/fey_map.dmm b/maps/sectors/admin_planets_192/fey_map.dmm index 1373f97a056c..ce262d5a73e2 100644 --- a/maps/sectors/admin_planets_192/fey_map.dmm +++ b/maps/sectors/admin_planets_192/fey_map.dmm @@ -56,10 +56,10 @@ /area/admin_planet/fey_forest/gateway_facility) "bS" = ( /obj/structure/table/rack/shelf/steel, -/obj/item/storage/hypokit/advanced/loaded{ +/obj/item/storage/hypokit/advanced/full/loaded/loaded{ pixel_y = -7 }, -/obj/item/storage/hypokit/advanced/loaded, +/obj/item/storage/hypokit/advanced/full/loaded/loaded, /turf/simulated/floor/tiled/techfloor, /area/admin_planet/fey_forest/gateway_facility) "ca" = ( diff --git a/maps/templates/admin/dhael_centcom.dmm b/maps/templates/admin/dhael_centcom.dmm index 57ffc8028093..beea1612d512 100644 --- a/maps/templates/admin/dhael_centcom.dmm +++ b/maps/templates/admin/dhael_centcom.dmm @@ -10341,22 +10341,22 @@ /area/centcom/security) "Fo" = ( /obj/structure/table/reinforced, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /turf/unsimulated/floor{ diff --git a/maps/templates/admin/ert.dmm b/maps/templates/admin/ert.dmm index 557e41dbcba6..146cbac625b8 100644 --- a/maps/templates/admin/ert.dmm +++ b/maps/templates/admin/ert.dmm @@ -1285,7 +1285,7 @@ "lv" = ( /obj/structure/closet/wardrobe/ert, /obj/item/modular_computer/laptop, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/effect/floor_decal/industrial/outline/grey, @@ -2447,7 +2447,7 @@ "sz" = ( /obj/structure/closet/wardrobe/ert, /obj/item/modular_computer/laptop, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/light, @@ -4257,7 +4257,7 @@ "Gw" = ( /obj/structure/closet/wardrobe/ert, /obj/item/modular_computer/laptop, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/light{ diff --git a/maps/templates/admin/ert_base.dmm b/maps/templates/admin/ert_base.dmm index b82c3d08903c..4bca0261c364 100644 --- a/maps/templates/admin/ert_base.dmm +++ b/maps/templates/admin/ert_base.dmm @@ -211,7 +211,7 @@ "az" = ( /obj/structure/closet/wardrobe/ert, /obj/item/modular_computer/laptop/preset/custom_loadout/elite, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /turf/simulated/shuttle/floor/black, @@ -222,7 +222,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /turf/simulated/shuttle/floor/black, diff --git a/maps/templates/shelters/shelter_2.dmm b/maps/templates/shelters/shelter_2.dmm index 90940ce2c552..23f6355c0e38 100644 --- a/maps/templates/shelters/shelter_2.dmm +++ b/maps/templates/shelters/shelter_2.dmm @@ -50,7 +50,7 @@ /obj/item/fbp_backup_cell, /obj/item/fbp_backup_cell, /obj/item/storage/pill_bottle/antitox, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/healthanalyzer, /obj/item/storage/pill_bottle/dice_nerd, /turf/simulated/shuttle/floor/voidcraft, diff --git a/maps/templates/shelters/shelter_4.dmm b/maps/templates/shelters/shelter_4.dmm index 4995bc145b32..b7ef075b8aa4 100644 --- a/maps/templates/shelters/shelter_4.dmm +++ b/maps/templates/shelters/shelter_4.dmm @@ -60,15 +60,15 @@ /obj/item/survivalcapsule, /obj/item/survivalcapsule, /obj/item/survivalcapsule, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/gun/energy/frontier/locked/holdout, /obj/item/gun/energy/frontier/locked/holdout, /obj/item/bluespace_radio/commerce, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, /obj/item/binoculars, /obj/item/perfect_tele, /obj/item/storage/pill_bottle/nutriment, @@ -116,7 +116,7 @@ /obj/item/gun/ballistic/pistol, /obj/item/clothing/accessory/storage/black_vest, /obj/item/material/knife/tacknife/survival, -/obj/item/storage/box/survival/comp, +/obj/item/storage/box/legacy_survival/comp, /turf/simulated/floor/carpet/bcarpet, /area/survivalpod) "k" = ( @@ -242,7 +242,7 @@ /obj/item/gun/ballistic/pistol, /obj/item/clothing/accessory/storage/black_vest, /obj/item/material/knife/tacknife/survival, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /turf/simulated/floor/carpet/bcarpet, diff --git a/maps/templates/shelters/shelter_a.dmm b/maps/templates/shelters/shelter_a.dmm index b1df9619c991..0738467e6f0d 100644 --- a/maps/templates/shelters/shelter_a.dmm +++ b/maps/templates/shelters/shelter_a.dmm @@ -68,10 +68,10 @@ /obj/item/storage/firstaid/adv, /obj/item/storage/firstaid/regular, /obj/item/modular_computer/laptop/preset/custom_loadout/rugged, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/extinguisher/mini, /obj/item/radio{ icon_state = "walkietalkieOLD"; diff --git a/maps/templates/shuttles/overmaps/generic/cruiser.dmm b/maps/templates/shuttles/overmaps/generic/cruiser.dmm index edee389cfccd..2a4525f28f68 100644 --- a/maps/templates/shuttles/overmaps/generic/cruiser.dmm +++ b/maps/templates/shuttles/overmaps/generic/cruiser.dmm @@ -1731,11 +1731,11 @@ /area/mothership/dorm1) "eb" = ( /obj/structure/closet/wardrobe/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/atmospherics/component/unary/vent_scrubber/on, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /turf/simulated/floor/wood, /area/mothership/dorm1) @@ -1782,11 +1782,11 @@ /area/mothership/teleporter) "ei" = ( /obj/structure/closet/wardrobe/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/atmospherics/component/unary/vent_scrubber/on, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /turf/simulated/floor/wood, /area/mothership/dorm2) @@ -3541,25 +3541,25 @@ /area/mothership/dorm3) "ig" = ( /obj/structure/closet/wardrobe/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/atmospherics/component/unary/vent_scrubber/on{ dir = 1 }, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /turf/simulated/floor/wood, /area/mothership/dorm3) "ih" = ( /obj/structure/closet/wardrobe/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/atmospherics/component/unary/vent_scrubber/on{ dir = 1 }, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /turf/simulated/floor/wood, /area/mothership/dorm4) @@ -4657,11 +4657,11 @@ /area/mothership/dorm5) "kF" = ( /obj/structure/closet/wardrobe/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/atmospherics/component/unary/vent_scrubber/on, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /turf/simulated/floor/wood, /area/mothership/dorm5) @@ -4673,11 +4673,11 @@ /area/mothership/dorm6) "kI" = ( /obj/structure/closet/wardrobe/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/machinery/atmospherics/component/unary/vent_scrubber/on, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /turf/simulated/floor/wood, /area/mothership/dorm6) @@ -6861,7 +6861,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 9 }, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, /turf/simulated/floor/tiled/techfloor, /area/mothership/holodeck) "pe" = ( @@ -7609,12 +7609,12 @@ dir = 1 }, /obj/structure/closet/emcloset/legacy, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/box/syndie_kit/space, /obj/item/storage/box/syndie_kit/space, /turf/simulated/floor/tiled/steel_grid, diff --git a/maps/templates/shuttles/overmaps/generic/overmap_ship_paperclipper.dmm b/maps/templates/shuttles/overmaps/generic/overmap_ship_paperclipper.dmm index faa824a293f2..9f01169a2c8e 100644 --- a/maps/templates/shuttles/overmaps/generic/overmap_ship_paperclipper.dmm +++ b/maps/templates/shuttles/overmaps/generic/overmap_ship_paperclipper.dmm @@ -705,10 +705,10 @@ /obj/effect/floor_decal/techfloor{ dir = 1 }, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/gps, /obj/item/tank/emergency/oxygen/engi, /obj/item/tank/emergency/oxygen/engi, diff --git a/maps/templates/shuttles/overmaps/generic/shelter_5.dmm b/maps/templates/shuttles/overmaps/generic/shelter_5.dmm index 912e1e3267cf..a86910d30893 100644 --- a/maps/templates/shuttles/overmaps/generic/shelter_5.dmm +++ b/maps/templates/shuttles/overmaps/generic/shelter_5.dmm @@ -44,10 +44,10 @@ /obj/effect/floor_decal/techfloor{ dir = 1 }, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/gps, /obj/item/tank/emergency/oxygen/engi, /obj/item/tank/emergency/oxygen/engi, diff --git a/maps/templates/shuttles/overmaps/generic/shelter_6.dmm b/maps/templates/shuttles/overmaps/generic/shelter_6.dmm index c215d0831b02..51944373eb4e 100644 --- a/maps/templates/shuttles/overmaps/generic/shelter_6.dmm +++ b/maps/templates/shuttles/overmaps/generic/shelter_6.dmm @@ -600,14 +600,14 @@ name = "Internals Locker"; pixel_y = -32 }, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, -/obj/item/storage/box/survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, +/obj/item/storage/box/legacy_survival/space, /obj/item/storage/toolbox/emergency, /obj/item/storage/toolbox/emergency, /obj/item/storage/toolbox/emergency, @@ -693,22 +693,22 @@ /obj/item/clothing/under/ert, /obj/item/clothing/under/ert, /obj/item/clothing/under/ert, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, -/obj/item/storage/box/survival/comp{ +/obj/item/storage/box/legacy_survival/comp{ starts_with = list(/obj/item/tool/prybar/red,/obj/item/clothing/glasses/goggles,/obj/item/reagent_containers/hypospray/autoinjector,/obj/item/stack/medical/bruise_pack,/obj/item/flashlight/glowstick,/obj/item/reagent_containers/food/snacks/wrapped/proteinbar,/obj/item/clothing/mask/breath,/obj/item/tank/emergency/oxygen/engi) }, /obj/item/perfect_tele, diff --git a/maps/triumph/levels/flagship.dmm b/maps/triumph/levels/flagship.dmm index b4be9d2061d9..5a692de119af 100644 --- a/maps/triumph/levels/flagship.dmm +++ b/maps/triumph/levels/flagship.dmm @@ -15084,14 +15084,14 @@ /area/centcom/security) "Vj" = ( /obj/structure/table/steel_reinforced, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, -/obj/item/storage/box/survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, +/obj/item/storage/box/legacy_survival/comp, /turf/unsimulated/floor{ icon_state = "dark" },