diff --git a/code/__DEFINES/dcs/signals/signals_mod.dm b/code/__DEFINES/dcs/signals/signals_mod.dm index bc76dd3e87a..21442ee73eb 100644 --- a/code/__DEFINES/dcs/signals/signals_mod.dm +++ b/code/__DEFINES/dcs/signals/signals_mod.dm @@ -54,3 +54,9 @@ #define COMSIG_MOD_GET_VISOR_OVERLAY "mod_get_visor_overlay" /// Called when the MOD control unit updates its parts speed #define COMSIG_MOD_UPDATE_SPEED "mod_update_speed" +/// Called on the module when the user attempts to install it into a MOD control unit (obj/item/mod/control/suit, mob/user) +#define COMSIG_MODULE_TRY_INSTALL "mod_module_try_install" +/// Called on the MOD control unit when the user attempts to install a module (obj/item/mod/module/module, mob/user) +#define COMSIG_MOD_TRY_INSTALL_MODULE "mod_try_install_module" + /// Cancel module installation, with no message. Include feedback on your cancel. + #define MOD_ABORT_INSTALL (1<<0) diff --git a/code/datums/components/anomalock_module.dm b/code/datums/components/anomalock_module.dm new file mode 100644 index 00000000000..5dada406af9 --- /dev/null +++ b/code/datums/components/anomalock_module.dm @@ -0,0 +1,130 @@ +/datum/component/anomaly_locked_module + var/obj/item/assembly/signaler/anomaly/core + /// Accepted types of anomaly cores. + var/list/accepted_anomalies + /// If the core is removable once socketed. + var/core_removable + /// A proc to call before the core is inserted. Returns an ITEM_INTERACT define, which the component will itself return. + var/pre_insert_callback + /// A proc to call when the core is inserted. + var/core_insert_callback + /// A proc to call when the core is removed. + var/core_remove_callback + +/datum/component/anomaly_locked_module/Initialize(list/anomaly_types, prebuilt = FALSE, removable = TRUE, pre_insert_callback, insert_callback, remove_callback) + . = ..() + if(!istype(parent, /obj/item/mod/module)) + return COMPONENT_INCOMPATIBLE + accepted_anomalies = typecacheof(anomaly_types) + core_removable = removable + src.pre_insert_callback = pre_insert_callback + core_insert_callback = insert_callback + core_remove_callback = remove_callback + if(!(prebuilt && length(anomaly_types))) + return + var/obj/item/assembly/signaler/anomaly/core_type = pick(anomaly_types) + core = new core_type(parent) + +/datum/component/anomaly_locked_module/Destroy(force) + QDEL_NULL(core) + return ..() + +/datum/component/anomaly_locked_module/RegisterWithParent() + RegisterSignal(parent, COMSIG_MODULE_TRIGGERED, PROC_REF(on_module_triggered)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_interact)) + RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), PROC_REF(on_screwdriver_act)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_update_icon_state)) + +/datum/component/anomaly_locked_module/UnregisterFromParent() + UnregisterSignal(parent, list( + COMSIG_MODULE_TRIGGERED, + COMSIG_ATOM_ITEM_INTERACTION, + COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), + COMSIG_ATOM_EXAMINE, + COMSIG_ATOM_UPDATE_ICON_STATE, + )) + +/datum/component/anomaly_locked_module/proc/on_module_triggered(obj/item/mod/module/source, mob/living/wearer) + SIGNAL_HANDLER + if(!core) + source.balloon_alert(wearer, "no core!") + return MOD_ABORT_USE + +/datum/component/anomaly_locked_module/proc/on_item_interact(obj/item/mod/module/source, mob/living/user, obj/item/tool, list/modifiers) + SIGNAL_HANDLER + if(!is_type_in_typecache(tool, accepted_anomalies)) + return 0 + if(core) + source.balloon_alert(user, "already has core!") + return ITEM_INTERACT_FAILURE + if(pre_insert_callback) + var/callback_return + if(istype(pre_insert_callback, /datum/callback)) + var/datum/callback/pre_insert_callback_datum = pre_insert_callback + callback_return = pre_insert_callback_datum.Invoke(user, tool, modifiers) + else + callback_return = call(source, pre_insert_callback)(user, tool, modifiers) + if(callback_return) + return callback_return + return insert_core(source, user, tool, modifiers) + +/datum/component/anomaly_locked_module/proc/insert_core(obj/item/mod/module/source, mob/living/user, obj/item/tool, list/modifiers) + if(!user.transferItemToLoc(tool, source)) + return ITEM_INTERACT_FAILURE + core = tool + source.balloon_alert(user, "core inserted") + playsound(source, 'sound/machines/click.ogg', 30, TRUE) + source.update_appearance(UPDATE_ICON_STATE) + if(core_insert_callback) + if(istype(core_insert_callback, /datum/callback)) + var/datum/callback/core_insert_callback_datum = core_insert_callback + core_insert_callback_datum.Invoke(core, user, modifiers) + else + call(source, core_insert_callback)(core, user, modifiers) + return ITEM_INTERACT_SUCCESS + +/datum/component/anomaly_locked_module/proc/on_screwdriver_act(obj/item/mod/module/source, mob/living/user, obj/item/tool) + SIGNAL_HANDLER + if(!core) + source.balloon_alert(user, "no core!") + return ITEM_INTERACT_FAILURE + if(!core_removable) + source.balloon_alert(user, "cannot remove core!") + INVOKE_ASYNC(src, PROC_REF(try_remove_core), source, user, tool) + return ITEM_INTERACT_SUCCESS + +/datum/component/anomaly_locked_module/proc/try_remove_core(obj/item/mod/module/source, mob/living/user, obj/item/tool) + if(!do_after(user, 3 SECONDS, source)) + source.balloon_alert(user, "interrupted!") + return + source.balloon_alert(user, "core removed") + core.forceMove(source.drop_location()) + if(source.Adjacent(user) && !issilicon(user)) + user.put_in_hands(core) + core = null + source.update_appearance(UPDATE_ICON_STATE) + if(core_remove_callback) + if(istype(core_remove_callback, /datum/callback)) + var/datum/callback/core_remove_callback_datum = core_remove_callback + core_remove_callback_datum.Invoke(core, user) + else + call(source, core_remove_callback)(core, user) + +/datum/component/anomaly_locked_module/proc/on_examine(obj/item/mod/module/source, mob/viewer, list/examine_list) + SIGNAL_HANDLER + if(!length(accepted_anomalies)) + return + if(core) + examine_list += span_notice("There is a [core.name] installed in it. [core_removable ? "You could remove it with a screwdriver..." : "Unfortunately, due to a design quirk, it's unremovable."]") + return + var/list/core_list = list() + for(var/atom/core_path as anything in accepted_anomalies) + core_list += initial(core_path.name) + examine_list += span_notice("You need to insert \a [english_list(core_list, and_text = " or ")] for this module to function.") + if(!core_removable) + examine_list += span_notice("Due to some design quirk, once a core is inserted, it won't be removable.") + +/datum/component/anomaly_locked_module/proc/on_update_icon_state(obj/item/mod/module/source) + SIGNAL_HANDLER + source.icon_state = source::icon_state + (core ? "-core" : "") diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index d8fdb8f846b..9983761fa91 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -31,8 +31,13 @@ if(istype(teleatom, /obj/item/storage/backpack/holding)) precision = rand(1,100) - var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding) + var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding, /obj/item/mod/control, /obj/item/mod/module/storage) var/list/bagholding = typecache_filter_list(teleatom.get_all_contents(), bag_cache) + for(var/obj/item/mod/modsuit_or_module in bagholding) + var/datum/storage/storage = modsuit_or_module.atom_storage + if(istype(storage, /datum/storage/bag_of_holding) && storage.real_location == storage.parent) + continue + bagholding -= modsuit_or_module if(bagholding.len) precision = max(rand(1,100)*bagholding.len,100) if(isliving(teleatom)) diff --git a/code/datums/storage/subtypes/mod_storage.dm b/code/datums/storage/subtypes/mod_storage.dm new file mode 100644 index 00000000000..5f6fdc791df --- /dev/null +++ b/code/datums/storage/subtypes/mod_storage.dm @@ -0,0 +1,22 @@ +/datum/storage/mod_storage + max_total_storage = 15 + max_slots = 7 + +/datum/storage/mod_storage/expanded + max_total_storage = 21 + max_slots = 14 + +/datum/storage/mod_storage/syndicate + max_total_storage = 30 + max_slots = 21 + +/datum/storage/mod_storage/belt + max_total_storage = 21 + max_slots = 7 + max_specific_storage = WEIGHT_CLASS_SMALL + +/datum/storage/mod_storage/bluespace + max_total_storage = 60 + max_slots = 21 + max_specific_storage = WEIGHT_CLASS_GIGANTIC + allow_big_nesting = TRUE diff --git a/code/datums/storage/subtypes/others/bag_of_holding.dm b/code/datums/storage/subtypes/others/bag_of_holding.dm index 4028d4f789c..8a4ae79c293 100644 --- a/code/datums/storage/subtypes/others/bag_of_holding.dm +++ b/code/datums/storage/subtypes/others/bag_of_holding.dm @@ -5,30 +5,38 @@ allow_big_nesting = TRUE /datum/storage/bag_of_holding/attempt_insert(obj/item/to_insert, mob/user, override, force, messages) - var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(to_insert.get_all_contents(), typecacheof(/obj/item/storage/backpack/holding)) + var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(to_insert.get_all_contents(), typecacheof(/obj/item/storage/backpack/holding, /obj/item/mod/control, /obj/item/mod/module/storage)) matching -= parent matching -= real_location + for(var/obj/item/mod/modsuit_or_module in matching) + var/datum/storage/storage = modsuit_or_module.atom_storage + if(istype(storage, /datum/storage/bag_of_holding) && storage.real_location == storage.parent) + continue + matching -= modsuit_or_module - if((istype(to_insert, /obj/item/storage/backpack/holding) || length(matching)) && can_insert(to_insert, user)) + if((istype(to_insert.atom_storage, /datum/storage/bag_of_holding) || length(matching)) && can_insert(to_insert, user)) INVOKE_ASYNC(src, PROC_REF(recursive_insertion), to_insert, user) return FALSE return ..() /datum/storage/bag_of_holding/proc/recursive_insertion(obj/item/to_insert, mob/living/user) + if(confirm_recursive_insertion(to_insert, user)) + create_rift(to_insert, user) + +/datum/storage/bag_of_holding/proc/confirm_recursive_insertion(obj/item/to_insert, mob/living/user) var/area/bag_area = get_area(user) var/safety = tgui_alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [to_insert.name]?", list("Proceed", "Abort")) - if(safety != "Proceed" \ - || QDELETED(to_insert) \ - || QDELETED(parent) \ - || QDELETED(real_location) \ - || QDELETED(user) \ - || !user.can_perform_action(parent, NEED_DEXTERITY) \ - || !can_insert(to_insert, user) \ - || (bag_area.area_flags & NO_BOH) \ - ) - return + return safety == "Proceed" \ + && !QDELETED(to_insert) \ + && !QDELETED(parent) \ + && !QDELETED(real_location) \ + && !QDELETED(user) \ + && user.can_perform_action(parent, NEED_DEXTERITY) \ + && can_insert(to_insert, user) \ + && !(bag_area.area_flags & NO_BOH) +/datum/storage/bag_of_holding/proc/create_rift(obj/item/inserted, mob/living/user) var/turf/rift_loc = get_turf(parent) user.visible_message( span_userdanger("The Bluespace interfaces of the two devices catastrophically malfunction!"), @@ -42,5 +50,5 @@ user.gib() var/obj/reality_tear/tear = new(rift_loc) tear.start_disaster() - qdel(to_insert) + qdel(inserted) qdel(parent) diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index fcc27c3e2e6..2e7eb25baf8 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -572,6 +572,13 @@ balloon_alert(user, "can't install!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return + if(SEND_SIGNAL(src, COMSIG_MOD_TRY_INSTALL_MODULE, new_module, user) & MOD_ABORT_INSTALL) + return + if(SEND_SIGNAL(new_module, COMSIG_MODULE_TRY_INSTALL, src, user) & MOD_ABORT_INSTALL) + return + finish_install(new_module, user) + +/obj/item/mod/control/proc/finish_install(obj/item/mod/module/new_module, mob/user) new_module.forceMove(src) modules += new_module complexity += new_module.complexity diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index c2a43b6dd95..432a2676653 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -35,6 +35,10 @@ var/overlay_state_use /// Icon file for the overlay. var/overlay_icon_file = 'icons/mob/clothing/modsuit/mod_modules.dmi' + /// Overlay given to the item icon of the control unit + var/overlay_state_item + /// Icon file for the item overlay + var/item_overlay_icon_file = 'icons/obj/clothing/modsuit/mod_modules.dmi' /// Does the overlay use the control unit's colors? var/use_mod_colors = FALSE /// What modules are we incompatible with? @@ -459,13 +463,10 @@ deactivate() return COMSIG_KB_ACTIVATED -///Anomaly Locked - Causes the module to not function without an anomaly. +///Anomaly Locked - Mostly just a wrapper for modules that don't need to descend from any other module but need the anomaly_locked_module component /obj/item/mod/module/anomaly_locked name = "MOD anomaly locked module" desc = "A form of a module, locked behind an anomalous core to function." - incompatible_modules = list() - /// The core item the module runs off. - var/obj/item/assembly/signaler/anomaly/core /// Accepted types of anomaly cores. var/list/accepted_anomalies = list(/obj/item/assembly/signaler/anomaly) /// If this one starts with a core in. @@ -475,80 +476,4 @@ /obj/item/mod/module/anomaly_locked/Initialize(mapload) . = ..() - if(!prebuilt || !length(accepted_anomalies)) - return - var/core_path = pick(accepted_anomalies) - core = new core_path(src) - update_icon_state() - -/obj/item/mod/module/anomaly_locked/Destroy() - QDEL_NULL(core) - return ..() - -/obj/item/mod/module/anomaly_locked/examine(mob/user) - . = ..() - if(!length(accepted_anomalies)) - return - if(core) - . += span_notice("There is a [core.name] installed in it. [core_removable ? "You could remove it with a screwdriver..." : "Unfortunately, due to a design quirk, it's unremovable."]") - else - var/list/core_list = list() - for(var/path in accepted_anomalies) - var/atom/core_path = path - core_list += initial(core_path.name) - . += span_notice("You need to insert \a [english_list(core_list, and_text = " or ")] for this module to function.") - if(!core_removable) - . += span_notice("Due to some design quirk, once a core is inserted, it won't be removable.") - -/obj/item/mod/module/anomaly_locked/on_select() - if(!core) - balloon_alert(mod.wearer, "no core!") - return - return ..() - -/obj/item/mod/module/anomaly_locked/on_process(seconds_per_tick) - . = ..() - if(!core) - return FALSE - -/obj/item/mod/module/anomaly_locked/on_active_process(seconds_per_tick) - if(!core) - return FALSE - return TRUE - -/obj/item/mod/module/anomaly_locked/attackby(obj/item/item, mob/living/user, list/modifiers, list/attack_modifiers) - if(item.type in accepted_anomalies) - if(core) - balloon_alert(user, "core already in!") - return - if(!user.transferItemToLoc(item, src)) - return - core = item - balloon_alert(user, "core installed") - playsound(src, 'sound/machines/click.ogg', 30, TRUE) - update_icon_state() - else - return ..() - -/obj/item/mod/module/anomaly_locked/screwdriver_act(mob/living/user, obj/item/tool) - . = ..() - if(!core) - balloon_alert(user, "no core!") - return - if(!core_removable) - balloon_alert(user, "already has core!") - return - balloon_alert(user, "removing core...") - if(!do_after(user, 3 SECONDS, target = src)) - balloon_alert(user, "interrupted!") - return - balloon_alert(user, "core removed") - core.forceMove(drop_location()) - if(Adjacent(user) && !issilicon(user)) - user.put_in_hands(core) - core = null - update_icon_state() - -/obj/item/mod/module/anomaly_locked/update_icon_state() - icon_state = initial(icon_state) + (core ? "-core" : "") - return ..() + AddComponent(/datum/component/anomaly_locked_module, accepted_anomalies, prebuilt, core_removable) diff --git a/code/modules/mod/modules/module_holding.dm b/code/modules/mod/modules/module_holding.dm new file mode 100644 index 00000000000..fc235663f1f --- /dev/null +++ b/code/modules/mod/modules/module_holding.dm @@ -0,0 +1,100 @@ +#define HOLDING_MODULE_PREVENT_DUPLICATE_CHECK 1 +#define HOLDING_MODULE_CHECK_CONFIRMED 2 + +/obj/item/mod/module/storage/holding + name = "MOD storage module of holding" + desc = "A prototype storage module utilizing the power of anomalous bluespace phenomena \ + to store copious amounts of matter. Unfortunately, it suffers from the same drawbacks as its standalone counterpart, \ + including tearing catastrophic rifts in reality when nested inside bluespace pockets produced through similar means." + icon_state = "storage_holding" + complexity = 4 + storage_type = null // core-less modules should be safe to insert into bags of holding + var/prebuilt = FALSE + var/core_removable = TRUE + var/datum/component/anomaly_locked_module/anomalock + var/list/possible_bag_bombs = list() + +/obj/item/mod/module/storage/holding/Initialize(mapload) + . = ..() + anomalock = AddComponent(/datum/component/anomaly_locked_module,\ + list(/obj/item/assembly/signaler/anomaly/bluespace),\ + prebuilt,\ + core_removable,\ + PROC_REF(pre_core_inserted),\ + PROC_REF(on_core_inserted),\ + PROC_REF(on_core_removed),\ + ) + RegisterSignal(src, COMSIG_MODULE_TRY_INSTALL, PROC_REF(try_install)) + +/obj/item/mod/module/storage/holding/Destroy() + possible_bag_bombs.Cut() + return ..() + +/obj/item/mod/module/storage/holding/proc/pre_core_inserted(mob/user, obj/item/core, list/modifiers) + if(possible_bag_bombs[core] == HOLDING_MODULE_PREVENT_DUPLICATE_CHECK) + return ITEM_INTERACT_FAILURE + var/datum/storage/bag_of_holding/other_bag + for(var/atom/nested_loc in get_nested_locs(src)) + if(istype(nested_loc.atom_storage, /datum/storage/bag_of_holding)) + other_bag = nested_loc.atom_storage + break + if(other_bag && !possible_bag_bombs[core]) + INVOKE_ASYNC(src, PROC_REF(recursive_core_insertion), other_bag, user, core, modifiers) + return ITEM_INTERACT_BLOCKING + +/obj/item/mod/module/storage/holding/proc/recursive_core_insertion(datum/storage/bag_of_holding/bag_storage, mob/user, obj/item/core, list/modifiers) + possible_bag_bombs[core] = HOLDING_MODULE_PREVENT_DUPLICATE_CHECK + if(bag_storage.confirm_recursive_insertion(core, user) && !QDELETED(core) && user.is_holding(core) && IsReachableBy(user)) + anomalock.insert_core(src, user, core, modifiers) + possible_bag_bombs -= core + +/obj/item/mod/module/storage/holding/proc/on_core_inserted(obj/item/core, mob/user) + for(var/atom/nested_loc in get_nested_locs(src)) + var/datum/storage/bag_of_holding/boh = nested_loc.atom_storage + if(istype(boh)) + boh.create_rift(core, user) + return + core.moveToNullspace() // Otherwise, the core would become part of the suit's inventory. + storage_type = /datum/storage/bag_of_holding + create_storage(storage_type = /datum/storage/bag_of_holding) + atom_storage.set_locked(STORAGE_FULLY_LOCKED) + +/obj/item/mod/module/storage/holding/proc/on_core_removed() + QDEL_NULL(atom_storage) + storage_type = null + +/obj/item/mod/module/storage/holding/proc/try_install(_source, obj/item/mod/control/suit, mob/user) + SIGNAL_HANDLER + if(possible_bag_bombs[suit] == HOLDING_MODULE_PREVENT_DUPLICATE_CHECK) + return MOD_ABORT_INSTALL + if(!anomalock.core) + balloon_alert(user, "no core!") + playsound(suit, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) + return MOD_ABORT_INSTALL + var/datum/storage/bag_of_holding/other_bag + for(var/atom/nested_loc in get_nested_locs(suit)) + if(istype(nested_loc.atom_storage, /datum/storage/bag_of_holding)) + other_bag = nested_loc.atom_storage + break + if(other_bag) + if(possible_bag_bombs[suit] == HOLDING_MODULE_CHECK_CONFIRMED) + other_bag.create_rift(src, user) + else + INVOKE_ASYNC(src, PROC_REF(recursive_installation), other_bag, suit, user) + return MOD_ABORT_INSTALL + +/obj/item/mod/module/storage/holding/proc/recursive_installation(datum/storage/bag_of_holding/bag_storage, obj/item/mod/control/suit, mob/user) + possible_bag_bombs[suit] = HOLDING_MODULE_PREVENT_DUPLICATE_CHECK + if(bag_storage.confirm_recursive_insertion(src, user) && !QDELETED(suit) && user.is_holding(src) && suit.IsReachableBy(user)) + possible_bag_bombs[suit] = HOLDING_MODULE_CHECK_CONFIRMED + suit.install(src, user) + possible_bag_bombs -= suit + +/obj/item/mod/module/storage/holding/prebuilt + prebuilt = TRUE + +/obj/item/mod/module/storage/holding/prebuilt/locked + core_removable = FALSE + +#undef HOLDING_MODULE_PREVENT_DUPLICATE_CHECK +#undef HOLDING_MODULE_CHECK_CONFIRMED diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 86e7120237e..e45e59c5f2a 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -9,26 +9,19 @@ complexity = 1 incompatible_modules = list(/obj/item/mod/module/storage, /obj/item/mod/module/plate_compression) required_slots = list(ITEM_SLOT_BACK) - /// Max weight class of items in the storage. - var/max_w_class = WEIGHT_CLASS_NORMAL - /// Max combined weight of all items in the storage. - var/max_combined_w_class = 15 - /// Max amount of items in the storage. - var/max_items = 7 - /// Is nesting same-size storage items allowed? - var/big_nesting = FALSE + /// The storage type to create for the module + var/datum/storage/storage_type = /datum/storage/mod_storage /obj/item/mod/module/storage/Initialize(mapload) . = ..() - create_storage(max_specific_storage = max_w_class, max_total_storage = max_combined_w_class, max_slots = max_items) - atom_storage.allow_big_nesting = TRUE - atom_storage.set_locked(STORAGE_FULLY_LOCKED) + if(storage_type) + create_storage(storage_type = storage_type) + atom_storage.set_locked(STORAGE_FULLY_LOCKED) /obj/item/mod/module/storage/on_install() . = ..() - var/datum/storage/modstorage = mod.create_storage(max_specific_storage = max_w_class, max_total_storage = max_combined_w_class, max_slots = max_items) + var/datum/storage/modstorage = mod.create_storage(storage_type = storage_type) modstorage.set_real_location(src) - modstorage.allow_big_nesting = big_nesting atom_storage.set_locked(STORAGE_NOT_LOCKED) var/obj/item/clothing/suit = mod.get_part_from_slot(ITEM_SLOT_OCLOTHING) if(istype(suit)) @@ -61,18 +54,16 @@ whether smuggling, or simply hauling." complexity = 3 icon_state = "storage_large" - max_combined_w_class = 21 - max_items = 14 + storage_type = /datum/storage/mod_storage/expanded /obj/item/mod/module/storage/syndicate name = "MOD syndicate storage module" desc = "A storage system using nanotechnology developed by Cybersun Industries, these compartments use \ esoteric technology to compress the physical matter of items put inside of them, \ essentially shrinking items for much easier and more portable storage." - icon_state = "storage_syndi" complexity = 3 - max_combined_w_class = 30 - max_items = 21 + icon_state = "storage_syndi" + storage_type = /datum/storage/mod_storage/syndicate /obj/item/mod/module/storage/belt name = "MOD case storage module" @@ -81,10 +72,8 @@ If you find this equipped to a standard modular suit, then someone has almost certainly shortchanged you on a proper storage module." icon_state = "storage_case" complexity = 0 - max_w_class = WEIGHT_CLASS_SMALL - max_combined_w_class = 21 - max_items = 7 required_slots = list(ITEM_SLOT_BELT) + storage_type = /datum/storage/mod_storage/belt /obj/item/mod/module/storage/bluespace name = "MOD bluespace storage module" @@ -92,10 +81,7 @@ miniaturized bluespace pockets for the ultimate in storage technology; regardless of the weight of objects put inside." complexity = 3 icon_state = "storage_large" - max_w_class = WEIGHT_CLASS_GIGANTIC - max_combined_w_class = 60 - max_items = 21 - big_nesting = TRUE + storage_type = /datum/storage/mod_storage/bluespace ///Ion Jetpack - Lets the user fly freely through space using battery charge. /obj/item/mod/module/jetpack diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 3d3270622b2..44aaec1a21b 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -2114,6 +2114,17 @@ ) build_path = /obj/item/mod/module/storage/large_capacity +/datum/design/module/mod_storage_holding + name = "Storage Module of Holding" + id = "mod_storage_holding" + materials = list( + /datum/material/gold =SHEET_MATERIAL_AMOUNT * 1.5, + /datum/material/diamond =HALF_SHEET_MATERIAL_AMOUNT * 1.5, + /datum/material/uranium = SMALL_MATERIAL_AMOUNT*2.5, + /datum/material/bluespace =SHEET_MATERIAL_AMOUNT + ) + build_path = /obj/item/mod/module/storage/holding + /datum/design/module/mod_visor_medhud name = "Medical Visor Module" id = "mod_visor_medhud" diff --git a/code/modules/research/techweb/nodes/research_nodes.dm b/code/modules/research/techweb/nodes/research_nodes.dm index bf22457c7ba..41c2a48ecdd 100644 --- a/code/modules/research/techweb/nodes/research_nodes.dm +++ b/code/modules/research/techweb/nodes/research_nodes.dm @@ -93,6 +93,7 @@ design_ids = list( "bag_holding", "cybernetic_heart_anomalock", + "mod_storage_holding", "wormholeprojector", "gravitygun", "polymorph_belt", diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi index 0cd210d85da..7ff5dcd95a9 100644 Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 75d442d6ed2..b7cd4d5d5bb 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1089,6 +1089,7 @@ #include "code\datums\components\ai_retaliate_advanced.dm" #include "code\datums\components\alternative_sharpness.dm" #include "code\datums\components\amputating_limbs.dm" +#include "code\datums\components\anomalock_module.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\appearance_on_aggro.dm" #include "code\datums\components\aquarium.dm" @@ -2067,6 +2068,7 @@ #include "code\datums\storage\subtypes\holsters.dm" #include "code\datums\storage\subtypes\lockboxes.dm" #include "code\datums\storage\subtypes\medkits.dm" +#include "code\datums\storage\subtypes\mod_storage.dm" #include "code\datums\storage\subtypes\pockets.dm" #include "code\datums\storage\subtypes\toolboxes.dm" #include "code\datums\storage\subtypes\others\bag_of_holding.dm" @@ -5632,6 +5634,7 @@ #include "code\modules\mod\mod_types.dm" #include "code\modules\mod\mod_ui.dm" #include "code\modules\mod\modules\_module.dm" +#include "code\modules\mod\modules\module_holding.dm" #include "code\modules\mod\modules\module_kinesis.dm" #include "code\modules\mod\modules\module_pathfinder.dm" #include "code\modules\mod\modules\modules_antag.dm"