diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index 00db42bad50..3795d43bb76 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -551,7 +551,7 @@ /obj/item/circuitboard/machine/smartfridge/apply_default_parts(obj/machinery/smartfridge/smartfridge) build_path = smartfridge.base_build_path - if(!fridges_name_paths.Find(build_path, fridges_name_paths)) + if(!fridges_name_paths.Find(build_path)) name = "[initial(smartfridge.name)]" //if it's a unique type, give it a unique name. is_special_type = TRUE return ..() diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index dfe3987dfe2..3976908a5cd 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -17,8 +17,8 @@ var/base_build_path = /obj/machinery/smartfridge /// Maximum number of items that can be loaded into the machine var/max_n_of_items = 1500 - /// If the AI is allowed to retrieve items within the machine - var/allow_ai_retrieve = FALSE + /// The overlay for this fridge when it is filled with stuff + var/contents_icon_state = "plant" /// List of items that the machine starts with upon spawn var/list/initial_contents /// If the machine shows an approximate number of its contents on its sprite @@ -33,7 +33,7 @@ create_reagents(100, NO_REACT) air_update_turf(TRUE, TRUE) register_context() - if(mapload && !istype(src, /obj/machinery/smartfridge/drying_rack)) + if(mapload) welded_down = TRUE if(islist(initial_contents)) @@ -49,83 +49,115 @@ . = ..() move_update_air(old_loc) -/obj/machinery/smartfridge/can_be_unfasten_wrench(mob/user, silent) - if(welded_down) - to_chat(user, span_warning("[src] is welded to the floor!")) - return FAILED_UNFASTEN - return ..() - -/obj/machinery/smartfridge/set_anchored(anchorvalue) - . = ..() - if(!anchored && welded_down) //make sure they're keep in sync in case it was forcibly unanchored by badmins or by a megafauna. - welded_down = FALSE - can_atmos_pass = anchorvalue ? ATMOS_PASS_NO : ATMOS_PASS_YES - air_update_turf(TRUE, anchorvalue) - /obj/machinery/smartfridge/welder_act(mob/living/user, obj/item/tool) - ..() - if(istype(src, /obj/machinery/smartfridge/drying_rack)) - return FALSE + . = TOOL_ACT_TOOLTYPE_SUCCESS + if(welded_down) if(!tool.tool_start_check(user, amount=2)) - return TRUE + return + user.visible_message( span_notice("[user.name] starts to cut the [name] free from the floor."), span_notice("You start to cut [src] free from the floor..."), span_hear("You hear welding."), ) + if(!tool.use_tool(src, user, delay=100, volume=100)) - return FALSE + return + welded_down = FALSE to_chat(user, span_notice("You cut [src] free from the floor.")) - return TRUE + return + if(!anchored) - to_chat(user, span_warning("[src] needs to be wrenched to the floor!")) - return TRUE + balloon_alert(user, "wrench it first!") + return + if(!tool.tool_start_check(user, amount=2)) - return TRUE + return + user.visible_message( span_notice("[user.name] starts to weld the [name] to the floor."), span_notice("You start to weld [src] to the floor..."), span_hear("You hear welding."), ) - if(!tool.use_tool(src, user, delay=100, volume=100)) - balloon_alert(user, "cancelled!") - return FALSE + + if(!tool.use_tool(src, user, delay = 100, volume = 100)) + return + welded_down = TRUE to_chat(user, span_notice("You weld [src] to the floor.")) - return TRUE /obj/machinery/smartfridge/welder_act_secondary(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(!(machine_stat & BROKEN)) + balloon_alert(user, "no repair needed!") + return + + if(!tool.tool_start_check(user, amount=1)) + return + + user.visible_message( + span_notice("[user] is repairing [src]."), + span_notice("You begin repairing [src]..."), + span_hear("You hear welding."), + ) + + if(tool.use_tool(src, user, delay = 40, volume = 50)) + if(!(machine_stat & BROKEN)) + return + to_chat(user, span_notice("You repair [src]")) + atom_integrity = max_integrity + set_machine_stat(machine_stat & ~BROKEN) + update_icon() + +/obj/machinery/smartfridge/screwdriver_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + if(panel_open) + add_overlay("[initial(icon_state)]-panel") + else + cut_overlay("[initial(icon_state)]-panel") + SStgui.update_uis(src) + +/obj/machinery/smartfridge/can_be_unfasten_wrench(mob/user, silent) + if(welded_down) + balloon_alert(user, "unweld first!") + return FAILED_UNFASTEN + return ..() + +/obj/machinery/smartfridge/set_anchored(anchorvalue) . = ..() - if(istype(src, /obj/machinery/smartfridge/drying_rack)) - return FALSE - if(machine_stat & BROKEN) - if(!tool.tool_start_check(user, amount=1)) - return FALSE - user.visible_message( - span_notice("[user] is repairing [src]."), - span_notice("You begin repairing [src]..."), - span_hear("You hear welding."), - ) - if(tool.use_tool(src, user, delay=40, volume=50)) - if(!(machine_stat & BROKEN)) - return FALSE - balloon_alert(user, "repaired") - atom_integrity = max_integrity - set_machine_stat(machine_stat & ~BROKEN) - update_icon() - return TRUE + if(!anchored && welded_down) //make sure they're keep in sync in case it was forcibly unanchored by badmins or by a megafauna. + welded_down = FALSE + can_atmos_pass = anchorvalue ? ATMOS_PASS_NO : ATMOS_PASS_YES + air_update_turf(TRUE, anchorvalue) + +/obj/machinery/smartfridge/wrench_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + power_change() + +/obj/machinery/smartfridge/crowbar_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_pry_open(tool, close_after_pry = TRUE)) + return + + if(welded_down) + balloon_alert(user, "unweld first!") else - balloon_alert(user, "no repair needed!") - return FALSE + default_deconstruction_crowbar(tool) /obj/machinery/smartfridge/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) if(isnull(held_item)) return NONE var/tool_tip_set = FALSE - if(held_item.tool_behaviour == TOOL_WELDER && !istype(src, /obj/machinery/smartfridge/drying_rack)) + if(held_item.tool_behaviour == TOOL_WELDER) if(welded_down) context[SCREENTIP_CONTEXT_LMB] = "Unweld" tool_tip_set = TRUE @@ -136,6 +168,19 @@ context[SCREENTIP_CONTEXT_RMB] = "Repair" tool_tip_set = TRUE + else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "close" : "open"] panel" + tool_tip_set = TRUE + + else if(held_item.tool_behaviour == TOOL_CROWBAR) + if(panel_open) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + tool_tip_set = TRUE + + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchore" + tool_tip_set = TRUE + return tool_tip_set ? CONTEXTUAL_SCREENTIP_SET : NONE /obj/machinery/smartfridge/RefreshParts() @@ -149,19 +194,26 @@ if(in_range(user, src) || isobserver(user)) . += span_notice("The status display reads: This unit can hold a maximum of [max_n_of_items] items.") + . += structure_examine() + +/// Returns details related to the fridge structure +/obj/machinery/smartfridge/proc/structure_examine() + . = "" + if(welded_down) - . += span_info("It's moored firmly to the floor. You can unsecure its moorings with a welder.") - else if(anchored) - . += span_info("It's currently anchored to the floor. You can secure its moorings with a welder, or remove it with a wrench.") + . += span_info("It's moorings are firmly [EXAMINE_HINT("welded")] to the floor.") + else + . += span_info("It's moorings are loose and can be [EXAMINE_HINT("welded")] down.") + + if(anchored) + . += span_info("It is [EXAMINE_HINT("wrenched")] down on the floor.") else - . += span_info("It's not anchored to the floor. You can secure it in place with a wrench.") + . += span_info("It could be [EXAMINE_HINT("wrenched")] down.") /obj/machinery/smartfridge/update_appearance(updates=ALL) . = ..() - if(machine_stat & BROKEN) - set_light(0) - return - set_light(powered() ? MINIMUM_USEFUL_LIGHT_RANGE : 0) + + set_light((!(machine_stat & BROKEN) && powered()) ? MINIMUM_USEFUL_LIGHT_RANGE : 0) /obj/machinery/smartfridge/update_icon_state() icon_state = "[initial(icon_state)]" @@ -171,49 +223,33 @@ icon_state += "-off" return ..() +/// Returns the number of items visible in the fridge. Faster than subtracting 2 lists +/obj/machinery/smartfridge/proc/visible_items() + var/component_part_count = 0 + for(var/datum/stock_part/datum_part in component_parts) + component_part_count -= 1 + return contents.len - component_part_count + /obj/machinery/smartfridge/update_overlays() . = ..() - var/list/shown_contents = contents - component_parts - if(visible_contents && shown_contents.len > 0) - var/contents_icon_state = "[initial(icon_state)]" - switch(base_build_path) - if(/obj/machinery/smartfridge/extract) - contents_icon_state += "-slime" - if(/obj/machinery/smartfridge/food) - contents_icon_state += "-food" - if(/obj/machinery/smartfridge/drinks) - contents_icon_state += "-drink" - if(/obj/machinery/smartfridge/organ) - contents_icon_state += "-organ" - if(/obj/machinery/smartfridge/petri) - contents_icon_state += "-petri" - if(/obj/machinery/smartfridge/chemistry) - contents_icon_state += "-chem" - if(/obj/machinery/smartfridge/chemistry/virology) - contents_icon_state += "-viro" - else - contents_icon_state += "-plant" - switch(shown_contents.len) + var/shown_contents_length = visible_items() + if(visible_contents && shown_contents_length) + var/content_level = "[initial(icon_state)]-[contents_icon_state]" + switch(shown_contents_length) if(1 to 25) - contents_icon_state += "-1" + content_level += "-1" if(26 to 50) - contents_icon_state += "-2" + content_level += "-2" if(31 to INFINITY) - contents_icon_state += "-3" - . += mutable_appearance(icon, contents_icon_state) + content_level += "-3" + . += mutable_appearance(icon, content_level) . += mutable_appearance(icon, "[initial(icon_state)]-glass[(machine_stat & BROKEN) ? "-broken" : ""]") if(!machine_stat && has_emissive) . += emissive_appearance(icon, "[initial(icon_state)]-light-mask", src, alpha = src.alpha) -/obj/machinery/smartfridge/wrench_act(mob/living/user, obj/item/tool) - . = ..() - if(default_unfasten_wrench(user, tool)) - power_change() - return TOOL_ACT_TOOLTYPE_SUCCESS - /obj/machinery/smartfridge/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) if(BRUTE) @@ -225,101 +261,94 @@ playsound(src, SFX_SHATTER, 50, TRUE) return ..() -/******************* -* Item Adding -********************/ - -/obj/machinery/smartfridge/attackby(obj/item/O, mob/living/user, params) - if(default_deconstruction_screwdriver(user, icon_state, icon_state, O)) - if(panel_open) - add_overlay("[initial(icon_state)]-panel") - else - cut_overlay("[initial(icon_state)]-panel") - SStgui.update_uis(src) - return - - if(default_pry_open(O, close_after_pry = TRUE)) - return - - if(!welded_down && default_deconstruction_crowbar(O)) - SStgui.update_uis(src) - return - +/obj/machinery/smartfridge/attackby(obj/item/weapon, mob/living/user, params) if(!machine_stat) - var/list/shown_contents = contents - component_parts - if(shown_contents.len >= max_n_of_items) - to_chat(user, span_warning("\The [src] is full!")) + var/shown_contents_length = visible_items() + if(shown_contents_length >= max_n_of_items) + balloon_alert(user, "no space!") return FALSE - if(accept_check(O)) - load(O) - user.visible_message(span_notice("[user] adds \the [O] to \the [src]."), span_notice("You add \the [O] to \the [src].")) + if(!(weapon.item_flags & ABSTRACT) && \ + !(weapon.flags_1 & HOLOGRAM_1) && \ + accept_check(weapon) \ + ) + load(weapon) + user.visible_message(span_notice("[user] adds \the [weapon] to \the [src]."), span_notice("You add \the [weapon] to \the [src].")) SStgui.update_uis(src) if(visible_contents) update_appearance() return TRUE - if(istype(O, /obj/item/storage/bag)) - var/obj/item/storage/P = O + if(istype(weapon, /obj/item/storage/bag)) + var/obj/item/storage/bag = weapon var/loaded = 0 - for(var/obj/G in P.contents) - if(shown_contents.len >= max_n_of_items) + for(var/obj/item/object in bag.contents) + if(shown_contents_length >= max_n_of_items) break - if(accept_check(G)) - load(G) + if(!(object.item_flags & ABSTRACT) && \ + !(object.flags_1 & HOLOGRAM_1) && \ + accept_check(object) \ + ) + load(object) loaded++ SStgui.update_uis(src) if(loaded) - if(shown_contents.len >= max_n_of_items) - user.visible_message(span_notice("[user] loads \the [src] with \the [O]."), \ - span_notice("You fill \the [src] with \the [O].")) + if(shown_contents_length >= max_n_of_items) + user.visible_message(span_notice("[user] loads \the [src] with \the [weapon]."), \ + span_notice("You fill \the [src] with \the [weapon].")) else - user.visible_message(span_notice("[user] loads \the [src] with \the [O]."), \ - span_notice("You load \the [src] with \the [O].")) - if(O.contents.len > 0) + user.visible_message(span_notice("[user] loads \the [src] with \the [weapon]."), \ + span_notice("You load \the [src] with \the [weapon].")) + if(weapon.contents.len) to_chat(user, span_warning("Some items are refused.")) if (visible_contents) update_appearance() return TRUE else - to_chat(user, span_warning("There is nothing in [O] to put in [src]!")) + to_chat(user, span_warning("There is nothing in [weapon] to put in [src]!")) return FALSE if(!user.combat_mode) - to_chat(user, span_warning("\The [src] smartly refuses [O].")) - SStgui.update_uis(src) + to_chat(user, span_warning("\The [src] smartly refuses [weapon].")) return FALSE + else return ..() -/obj/machinery/smartfridge/proc/accept_check(obj/item/O) - if(istype(O, /obj/item/food/grown/) || istype(O, /obj/item/seeds/) || istype(O, /obj/item/grown/) || istype(O, /obj/item/graft/)) - return TRUE - return FALSE - -/obj/machinery/smartfridge/proc/load(obj/item/O) - if(ismob(O.loc)) - var/mob/M = O.loc - if(!M.transferItemToLoc(O, src)) - to_chat(usr, span_warning("\the [O] is stuck to your hand, you cannot put it in \the [src]!")) +/** + * Can this item be accepted by the smart fridge + * Arguments + * * [weapon][obj/item] - the item to accept + */ +/obj/machinery/smartfridge/proc/accept_check(obj/item/weapon) + var/static/list/accepted_items = list( + /obj/item/food/grown, + /obj/item/seeds, + /obj/item/grown, + /obj/item/graft, + ) + return is_type_in_list(weapon, accepted_items) + +/** + * Loads the item into the smart fridge + * Arguments + * * [weapon][obj/item] - the item to load. If the item is being held by a mo it will transfer it from hand else directly force move + */ +/obj/machinery/smartfridge/proc/load(obj/item/weapon) + if(ismob(weapon.loc)) + var/mob/owner = weapon.loc + if(!owner.transferItemToLoc(weapon, src)) + to_chat(usr, span_warning("\the [weapon] is stuck to your hand, you cannot put it in \the [src]!")) return FALSE - else - return TRUE + return TRUE else - if(O.loc.atom_storage) - return O.loc.atom_storage.attempt_remove(O, src) + if(weapon.loc.atom_storage) + return weapon.loc.atom_storage.attempt_remove(weapon, src, silent = TRUE) else - O.forceMove(src) + weapon.forceMove(src) return TRUE -///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge -/obj/machinery/smartfridge/proc/dispense(obj/item/O, mob/M) - if(!M.put_in_hands(O)) - O.forceMove(drop_location()) - adjust_item_drop_location(O) - use_power(active_power_usage) - /obj/machinery/smartfridge/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -331,18 +360,18 @@ . = list() var/listofitems = list() - for (var/I in src) + for (var/item in src) // We do not vend our own components. - if(I in component_parts) + if(item in component_parts) continue - var/atom/movable/O = I - if (!QDELETED(O)) - var/md5name = md5(O.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744 + var/atom/movable/atom = item + if (!QDELETED(atom)) + var/md5name = md5(atom.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744 if (listofitems[md5name]) // which is fixed in a version we cannot use due to ie8 incompatibility listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating else - listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1) + listofitems[md5name] = list("name" = atom.name, "amount" = 1) sort_list(listofitems) .["contents"] = listofitems @@ -353,27 +382,28 @@ . = ..() SStgui.update_uis(src) -/obj/machinery/smartfridge/ui_act(action, params) +/obj/machinery/smartfridge/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() - if(.) + if(. || !ui.user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return + + . = TRUE + var/mob/living_mob = ui.user + switch(action) if("Release") var/desired = 0 - if(!allow_ai_retrieve && isAI(usr)) - to_chat(usr, span_warning("[src] does not seem to be configured to respect your authority!")) + if(isAI(living_mob)) + to_chat(living_mob, span_warning("[src] does not respect your authority!")) return if (params["amount"]) desired = text2num(params["amount"]) else - desired = tgui_input_number(usr, "How many items would you like to take out?", "Release", max_value = 50) + desired = tgui_input_number(living_mob, "How many items would you like to take out?", "Release", max_value = 50) if(!desired) - return FALSE - - if(QDELETED(src) || QDELETED(usr) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH)) // Sanity checkin' in case stupid stuff happens while we wait for input() - return FALSE + return for(var/obj/item/dispensed_item in src) if(desired <= 0) @@ -384,12 +414,16 @@ if(format_text(dispensed_item.name) == format_text(params["name"])) if(dispensed_item in component_parts) CRASH("Attempted removal of [dispensed_item] component_part from smartfridge via smartfridge interface.") - dispense(dispensed_item, usr) + //dispense the item + if(!living_mob.put_in_hands(dispensed_item)) + dispensed_item.forceMove(drop_location()) + adjust_item_drop_location(dispensed_item) + use_power(active_power_usage) desired-- if (visible_contents) update_appearance() - return TRUE + return return FALSE @@ -408,48 +442,72 @@ idle_power_usage = 0 has_emissive = FALSE can_atmos_pass = ATMOS_PASS_YES + /// Is the rack currently drying stuff var/drying = FALSE -/obj/machinery/smartfridge/drying_rack/on_deconstruction() - new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) +/obj/machinery/smartfridge/drying_rack/Initialize(mapload) + . = ..() - //remove all component parts inherited from smartfridge cause they were not required in crafting - var/obj/item/circuitboard/machine/smartfridge/board = locate() in component_parts - component_parts -= board - qdel(board) - component_parts.Cut() + //you can't weld down wood + welded_down = FALSE - return ..() + //so we don't drop any of the parent smart fridge parts upon deconstruction + clear_components() +/// We cleared out the components in initialize so we can optimize this +/obj/machinery/smartfridge/drying_rack/visible_items() + return contents.len + +/obj/machinery/smartfridge/drying_rack/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + if(isnull(held_item)) + return NONE + + var/tool_tip_set = FALSE + if(held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + tool_tip_set = TRUE + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchore" + tool_tip_set = TRUE + + return tool_tip_set ? CONTEXTUAL_SCREENTIP_SET : NONE + +/obj/machinery/smartfridge/drying_rack/structure_examine() + . = "" + if(anchored) + . += span_info("It's currently anchored to the floor. It can be [EXAMINE_HINT("wrenched")] loose.") + else + . += span_info("It's not anchored to the floor. It can be [EXAMINE_HINT("wrenched")] down.") + . += span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") +/obj/machinery/smartfridge/drying_rack/welder_act(mob/living/user, obj/item/tool) +/obj/machinery/smartfridge/drying_rack/welder_act_secondary(mob/living/user, obj/item/tool) /obj/machinery/smartfridge/drying_rack/default_deconstruction_screwdriver() /obj/machinery/smartfridge/drying_rack/exchange_parts() -/obj/machinery/smartfridge/drying_rack/spawn_frame() +/obj/machinery/smartfridge/drying_rack/on_deconstruction() + new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) +/obj/machinery/smartfridge/drying_rack/crowbar_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1) - ..() + default_deconstruction_crowbar(tool, ignore_panel = TRUE) /obj/machinery/smartfridge/drying_rack/ui_data(mob/user) . = ..() .["isdryer"] = TRUE - .["verb"] = "Take" .["drying"] = drying - /obj/machinery/smartfridge/drying_rack/ui_act(action, params) . = ..() if(.) update_appearance() // This is to handle a case where the last item is taken out manually instead of through drying pop-out return + switch(action) if("Dry") toggle_drying(FALSE) return TRUE - return FALSE /obj/machinery/smartfridge/drying_rack/powered() - if(!anchored) - return FALSE - return ..() + return !anchored ? FALSE : ..() /obj/machinery/smartfridge/drying_rack/power_change() . = ..() @@ -464,12 +522,10 @@ . = ..() if(drying) . += "drying_rack_drying" - var/list/shown_contents = contents - component_parts - if(shown_contents.len) + if(contents.len) . += "drying_rack_filled" /obj/machinery/smartfridge/drying_rack/process() - ..() if(drying) for(var/obj/item/item_iterator in src) if(!accept_check(item_iterator)) @@ -481,10 +537,13 @@ use_power(active_power_usage) /obj/machinery/smartfridge/drying_rack/accept_check(obj/item/O) - if(HAS_TRAIT(O, TRAIT_DRYABLE)) //set on dryable element - return TRUE - return FALSE + return HAS_TRAIT(O, TRAIT_DRYABLE) +/** + * Toggles drying on or off + * Arguments + * * forceoff - if TRUE will force the dryer off always + */ /obj/machinery/smartfridge/drying_rack/proc/toggle_drying(forceoff) if(drying || forceoff) drying = FALSE @@ -503,7 +562,6 @@ return atmos_spawn_air("[TURF_TEMPERATURE(1000)]") - // ---------------------------- // Bar drink smartfridge // ---------------------------- @@ -511,12 +569,19 @@ name = "drink showcase" desc = "A refrigerated storage unit for tasty tasty alcohol." base_build_path = /obj/machinery/smartfridge/drinks + contents_icon_state = "drink" -/obj/machinery/smartfridge/drinks/accept_check(obj/item/O) - if(!is_reagent_container(O) || (O.item_flags & ABSTRACT) || istype(O,/obj/item/reagent_containers/cup/bowl) || !O.reagents || !O.reagents.reagent_list.len) +/obj/machinery/smartfridge/drinks/accept_check(obj/item/weapon) + //not an item or valid container + if(!is_reagent_container(weapon)) return FALSE - if(istype(O, /obj/item/reagent_containers/cup) || istype(O, /obj/item/reagent_containers/cup/glass) || istype(O, /obj/item/reagent_containers/condiment)) - return TRUE + + //an bowl or something that has no reagents + if(istype(weapon,/obj/item/reagent_containers/cup/bowl) || !length(weapon.reagents?.reagent_list)) + return FALSE + + //list of items acceptable + return (istype(weapon, /obj/item/reagent_containers/cup) || istype(weapon, /obj/item/reagent_containers/condiment)) // ---------------------------- // Food smartfridge @@ -524,11 +589,10 @@ /obj/machinery/smartfridge/food desc = "A refrigerated storage unit for food." base_build_path = /obj/machinery/smartfridge/food + contents_icon_state = "food" -/obj/machinery/smartfridge/food/accept_check(obj/item/O) - if(IS_EDIBLE(O) || (istype(O,/obj/item/reagent_containers/cup/bowl) && O.reagents && O.reagents.reagent_list.len)) - return TRUE - return FALSE +/obj/machinery/smartfridge/food/accept_check(obj/item/weapon) + return (IS_EDIBLE(weapon) || (istype(weapon,/obj/item/reagent_containers/cup/bowl) && length(weapon.reagents?.reagent_list))) // ------------------------------------- // Xenobiology Slime-Extract Smartfridge @@ -537,13 +601,10 @@ name = "smart slime extract storage" desc = "A refrigerated storage unit for slime extracts." base_build_path = /obj/machinery/smartfridge/extract + contents_icon_state = "slime" -/obj/machinery/smartfridge/extract/accept_check(obj/item/O) - if(istype(O, /obj/item/slime_extract)) - return TRUE - if(istype(O, /obj/item/slime_scanner)) - return TRUE - return FALSE +/obj/machinery/smartfridge/extract/accept_check(obj/item/weapon) + return (istype(weapon, /obj/item/slime_extract) || istype(weapon, /obj/item/slime_scanner)) /obj/machinery/smartfridge/extract/preloaded initial_contents = list(/obj/item/slime_scanner = 2) @@ -555,11 +616,10 @@ name = "smart petri dish storage" desc = "A refrigerated storage unit for petri dishes." base_build_path = /obj/machinery/smartfridge/petri + contents_icon_state = "petri" -/obj/machinery/smartfridge/petri/accept_check(obj/item/O) - if(istype(O, /obj/item/petri_dish)) - return TRUE - return FALSE +/obj/machinery/smartfridge/petri/accept_check(obj/item/weapon) + return istype(weapon, /obj/item/petri_dish) /obj/machinery/smartfridge/petri/preloaded initial_contents = list(/obj/item/petri_dish = 5) @@ -572,20 +632,22 @@ desc = "A refrigerated storage unit for organ storage." max_n_of_items = 20 //vastly lower to prevent processing too long base_build_path = /obj/machinery/smartfridge/organ + contents_icon_state = "organ" + /// The rate at which this fridge will repair damaged organs var/repair_rate = 0 /obj/machinery/smartfridge/organ/accept_check(obj/item/O) - if(isorgan(O) || isbodypart(O)) - return TRUE - return FALSE + return (isorgan(O) || isbodypart(O)) /obj/machinery/smartfridge/organ/load(obj/item/O) . = ..() if(!.) //if the item loads, clear can_decompose return + if(isorgan(O)) var/obj/item/organ/organ = O organ.organ_flags |= ORGAN_FROZEN + if(isbodypart(O)) var/obj/item/bodypart/bodypart = O for(var/obj/item/organ/stored in bodypart.contents) @@ -606,9 +668,11 @@ /obj/machinery/smartfridge/organ/Exited(atom/movable/gone, direction) . = ..() + if(isorgan(gone)) var/obj/item/organ/O = gone O.organ_flags &= ~ORGAN_FROZEN + if(isbodypart(gone)) var/obj/item/bodypart/bodypart = gone for(var/obj/item/organ/stored in bodypart.contents) @@ -621,8 +685,31 @@ name = "smart chemical storage" desc = "A refrigerated storage unit for medicine storage." base_build_path = /obj/machinery/smartfridge/chemistry + contents_icon_state = "chem" + +/obj/machinery/smartfridge/chemistry/accept_check(obj/item/weapon) + // not an item or reagent container + if(!is_reagent_container(weapon)) + return FALSE + + // empty pill prank ok + if(istype(weapon, /obj/item/reagent_containers/pill)) + return TRUE + + //check each pill in the pill bottle + if(istype(weapon, /obj/item/storage/pill_bottle)) + if(weapon.contents.len) + for(var/obj/item/target_item in weapon) + if(!accept_check(target_item)) + return FALSE + return TRUE + return FALSE -/obj/machinery/smartfridge/chemistry/accept_check(obj/item/O) + // other empty containers not accepted + if(!length(weapon.reagents?.reagent_list)) + return FALSE + + // the long list of other containers that can be accepted var/static/list/chemfridge_typecache = typecacheof(list( /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/cup/tube, @@ -633,23 +720,7 @@ /obj/item/reagent_containers/cup/vial, //SKYRAT EDIT ADDITION - HYPOSPRAYS /obj/item/reagent_containers/chem_pack )) - - if(istype(O, /obj/item/storage/pill_bottle)) - if(O.contents.len) - for(var/obj/item/I in O) - if(!accept_check(I)) - return FALSE - return TRUE - return FALSE - if(!is_reagent_container(O) || (O.item_flags & ABSTRACT)) - return FALSE - if(istype(O, /obj/item/reagent_containers/pill)) // empty pill prank ok - return TRUE - if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted - return FALSE - if(is_type_in_typecache(O, chemfridge_typecache)) - return TRUE - return FALSE + return is_type_in_typecache(weapon, chemfridge_typecache) /obj/machinery/smartfridge/chemistry/preloaded initial_contents = list( @@ -665,6 +736,7 @@ name = "smart virus storage" desc = "A refrigerated storage unit for volatile sample storage." base_build_path = /obj/machinery/smartfridge/chemistry/virology + contents_icon_state = "viro" /obj/machinery/smartfridge/chemistry/virology/preloaded initial_contents = list( @@ -691,8 +763,5 @@ visible_contents = FALSE base_build_path = /obj/machinery/smartfridge/disks -/obj/machinery/smartfridge/disks/accept_check(obj/item/O) - if(istype(O, /obj/item/disk/)) - return TRUE - else - return FALSE +/obj/machinery/smartfridge/disks/accept_check(obj/item/weapon) + return istype(weapon, /obj/item/disk) diff --git a/tgui/packages/tgui/interfaces/SmartVend.js b/tgui/packages/tgui/interfaces/SmartVend.tsx similarity index 81% rename from tgui/packages/tgui/interfaces/SmartVend.js rename to tgui/packages/tgui/interfaces/SmartVend.tsx index 9ca12a87b7d..54470b18a35 100644 --- a/tgui/packages/tgui/interfaces/SmartVend.js +++ b/tgui/packages/tgui/interfaces/SmartVend.tsx @@ -1,10 +1,23 @@ -import { map } from 'common/collections'; +import { BooleanLike } from 'common/react'; import { useBackend } from '../backend'; import { Button, NoticeBox, Section, Table } from '../components'; import { Window } from '../layouts'; +type Item = { + name: string; + amount: number; +}; + +type Data = { + contents: Item[]; + name: string; + isdryer: BooleanLike; + drying: BooleanLike; +}; + export const SmartVend = (props, context) => { - const { act, data } = useBackend(context); + const { act, data } = useBackend(context); + const { contents = [] } = data; return ( @@ -19,18 +32,18 @@ export const SmartVend = (props, context) => { ) }> - {(data.contents.length === 0 && ( + {contents.length === 0 ? ( Unfortunately, this {data.name} is empty. - )) || ( + ) : ( Item - {data.verb ? data.verb : 'Dispense'} + {data.isdryer ? 'Take' : 'Dispense'} - {map((value, key) => ( + {Object.values(contents).map((value, key) => ( {value.name} @@ -58,7 +71,7 @@ export const SmartVend = (props, context) => { /> - ))(data.contents)} + ))}
)}