diff --git a/code/game/machinery/centrifuge.dm b/code/game/machinery/centrifuge.dm new file mode 100644 index 00000000000..661521014ab --- /dev/null +++ b/code/game/machinery/centrifuge.dm @@ -0,0 +1,183 @@ +/datum/storage/hopper/industrial/centrifuge + can_hold = list( + /obj/item/food, + ) + expected_type = /obj/machinery/centrifuge + +/datum/storage/hopper/industrial/centrifuge/proc/should_ingest(mob/user, obj/item/thing) + if(thing.reagents?.total_volume <= 0) + if(user) + to_chat(user, SPAN_WARNING("\The [thing] is empty.")) + return FALSE + return TRUE + +/datum/storage/hopper/industrial/centrifuge/can_be_inserted(obj/item/W, mob/user, stop_messages, click_params) + . = ..() + if(. && !should_ingest(user, W)) + return FALSE + +/obj/machinery/centrifuge + name = "industrial centrifuge" + desc = "A machine used to extract reagents and materials from objects via spinning them at extreme speed." + icon = 'icons/obj/machines/centrifuge.dmi' + icon_state = ICON_STATE_WORLD + anchored = TRUE + density = TRUE + construct_state = /decl/machine_construction/default/panel_closed + uncreated_component_parts = null + storage = /datum/storage/hopper/industrial/centrifuge + base_type = /obj/machinery/centrifuge + stat_immune = 0 + + // Reference to our reagent container. Set to a path to create on init. + var/obj/item/loaded_beaker + + // Stolen from fabricators. + var/sound_id + var/datum/sound_token/sound_token + var/work_sound = 'sound/machines/fabricator_loop.ogg' + +/obj/machinery/centrifuge/mapped + loaded_beaker = /obj/item/chems/glass/beaker/large + +/obj/machinery/centrifuge/Initialize() + . = ..() + if(ispath(loaded_beaker)) + loaded_beaker = new loaded_beaker + +/obj/machinery/centrifuge/get_stored_inventory() + . = ..() + if(LAZYLEN(.)) + LAZYREMOVE(., loaded_beaker) + +/obj/machinery/centrifuge/Destroy() + QDEL_NULL(loaded_beaker) + return ..() + +/obj/machinery/centrifuge/dismantle() + if(loaded_beaker) + loaded_beaker.dropInto(loc) + loaded_beaker = null + return ..() + +/obj/machinery/centrifuge/components_are_accessible(path) + return use_power != POWER_USE_ACTIVE && ..() + +/obj/machinery/centrifuge/cannot_transition_to(state_path, mob/user) + if(use_power == POWER_USE_ACTIVE) + return SPAN_NOTICE("You must wait for \the [src] to finish first!") + return ..() + +/obj/machinery/centrifuge/attackby(obj/item/used_item, mob/user) + + if(use_power == POWER_USE_ACTIVE) + to_chat(user, SPAN_NOTICE("\The [src] is currently spinning, wait until it's finished.")) + return TRUE + + if((. = component_attackby(used_item, user))) + return + + // Load in a new container for products. + if(istype(used_item, /obj/item/chems/glass/beaker)) + if(loaded_beaker) + to_chat(user, SPAN_WARNING("\The [src] already has a beaker loaded.")) + return TRUE + if(user.try_unequip(used_item, src)) + loaded_beaker = used_item + to_chat(user, SPAN_NOTICE("You load \the [loaded_beaker] into \the [src].")) + return TRUE + + // Parent call handles inserting the frame into our contents, + return ..() + +/obj/machinery/centrifuge/attack_hand(mob/user) + + if(use_power == POWER_USE_ACTIVE) + user.visible_message("\The [user] disengages \the [src].") + update_use_power(POWER_USE_IDLE) + return TRUE + + if(use_power == POWER_USE_IDLE) + if(!loaded_beaker || QDELETED(loaded_beaker)) + to_chat(user, SPAN_WARNING("\The [src] has no beaker loaded to receive any products.")) + loaded_beaker = null // just in case + return TRUE + + if(length(get_stored_inventory())) + user.visible_message("\The [user] engages \the [src].") + update_use_power(POWER_USE_ACTIVE) + else + to_chat(user, SPAN_WARNING("\The [src]'s hopper is empty.")) + return TRUE + + if(use_power == POWER_USE_OFF || !operable()) + to_chat(user, SPAN_WARNING("\The [src]'s interface is unresponsive.")) + return TRUE + + return ..() + +/obj/machinery/centrifuge/Process(wait, tick) + ..() + + if(use_power != POWER_USE_ACTIVE) + return + + if(!loaded_beaker) + visible_message("\The [src] stops spinning and flashes a red light.") + update_use_power(POWER_USE_IDLE) + return + + var/list/processing_items = get_stored_inventory() + if(!length(processing_items)) + visible_message("\The [src] stops spinning and flashes a green light.") + update_use_power(POWER_USE_IDLE) + return + + var/obj/item/thing = processing_items[1] + thing.handle_centrifuge_process(src) + if(!QDELETED(thing) && loc) + thing.dropInto(loc) + +/obj/machinery/centrifuge/Initialize() + sound_id = "[work_sound]" + return ..() + +/obj/machinery/centrifuge/Destroy() + QDEL_NULL(sound_token) + return ..() + +/obj/machinery/centrifuge/update_use_power() + . = ..() + if(use_power == POWER_USE_ACTIVE) + if(!sound_token) + sound_token = play_looping_sound(src, sound_id, work_sound, volume = 30) + else + QDEL_NULL(sound_token) + +/obj/machinery/centrifuge/on_update_icon() + icon_state = initial(icon_state) + if(stat & BROKEN) + icon_state = "[icon_state]-broken" + else if(use_power == POWER_USE_OFF || !operable()) + icon_state = "[icon_state]-off" + else if(use_power == POWER_USE_ACTIVE) + icon_state = "[icon_state]-working" + +/obj/machinery/centrifuge/get_quick_interaction_handler(mob/user) + return loaded_beaker ? GET_DECL(/decl/interaction_handler/remove_centrifuge_beaker) : null + +/obj/machinery/centrifuge/get_alt_interactions(var/mob/user) + . = ..() + if(loaded_beaker) + LAZYADD(., /decl/interaction_handler/remove_centrifuge_beaker) + +/decl/interaction_handler/remove_centrifuge_beaker + name = "Remove Beaker" + expected_target_type = /obj/machinery/centrifuge + +/decl/interaction_handler/remove_centrifuge_beaker/invoked(atom/target, mob/user, obj/item/prop) + var/obj/machinery/centrifuge/centrifuge = target + if(centrifuge.loaded_beaker) + centrifuge.loaded_beaker.dropInto(centrifuge.loc) + user.put_in_hands(centrifuge.loaded_beaker) + centrifuge.loaded_beaker = null diff --git a/code/game/objects/items/__item.dm b/code/game/objects/items/__item.dm index 83baef59cca..bc8a7f9958f 100644 --- a/code/game/objects/items/__item.dm +++ b/code/game/objects/items/__item.dm @@ -472,27 +472,11 @@ return ..() && (!strict || loc == user) /obj/item/proc/squash_item(skip_qdel = FALSE) - if(!istype(material) || material.hardness > MAT_VALUE_MALLEABLE) return null - - var/list/leftover_mats = list() - for(var/mat in matter) - var/decl/material/material_decl = GET_DECL(mat) - if(material_decl.hardness <= MAT_VALUE_MALLEABLE) - var/spawn_amount = round(matter[mat] / SHEET_MATERIAL_AMOUNT) - if(spawn_amount > 0) - var/obj/item/stack/material/lump/lump = new(loc, spawn_amount, mat) - LAZYADD(., lump) - continue - leftover_mats[mat] = matter[mat] - - if(length(leftover_mats)) - var/obj/item/debris/scraps/remains = new(loc) - remains.matter = leftover_mats?.Copy() - remains.update_primary_material() - LAZYADD(., remains) - + var/list/results = convert_matter_to_lumps(skip_qdel) + if(length(results)) + . = results if(!skip_qdel) matter = null material = null @@ -1319,3 +1303,34 @@ modules/mob/living/human/life.dm if you die, you will be zoomed out. coating_string = FONT_COLORED(coating.get_color(), coating_string) return coating_string return ..() + +// Bespoke proc for handling when a centrifuge smooshes us, only currently used by growns and hive frames. +/obj/item/proc/handle_centrifuge_process(obj/machinery/centrifuge/centrifuge) + SHOULD_CALL_PARENT(TRUE) + return istype(centrifuge) && !QDELETED(centrifuge.loaded_beaker) && istype(centrifuge.loaded_beaker) + +/obj/item/proc/convert_matter_to_lumps(skip_qdel = FALSE) + + var/list/scrap_matter = list() + for(var/mat in matter) + var/mat_amount = matter[mat] + var/obj/item/stack/material/mat_stack = /obj/item/stack/material/lump + var/mat_per_stack = SHEET_MATERIAL_AMOUNT * initial(mat_stack.matter_multiplier) + var/sheet_amount = round(mat_amount / mat_per_stack) + if(sheet_amount) + var/obj/item/stack/material/lump/lump = new(loc, sheet_amount, mat) + LAZYADD(., lump) + mat_amount -= sheet_amount * mat_per_stack + if(mat_amount) + scrap_matter[mat] += mat_amount + + if(length(scrap_matter)) + var/obj/item/debris/scraps/scraps = new(loc) + scraps.matter = scrap_matter.Copy() + scraps.update_primary_material() + LAZYADD(., scraps) + + matter = null + material = null + if(!skip_qdel) + qdel(src) diff --git a/code/game/objects/items/circuitboards/machinery/household.dm b/code/game/objects/items/circuitboards/machinery/household.dm index 5ce6f6ead15..7035bedba94 100644 --- a/code/game/objects/items/circuitboards/machinery/household.dm +++ b/code/game/objects/items/circuitboards/machinery/household.dm @@ -46,6 +46,16 @@ /obj/item/stock_parts/circuitboard/cooker/get_buildable_types() return subtypesof(/obj/machinery/cooker) +/obj/item/stock_parts/circuitboard/centrifuge + name = "circuitboard (industrial centrifuge)" + build_path = /obj/machinery/centrifuge + board_type = "machine" + origin_tech = @'{"biotech":2,"engineering":1}' + req_components = list( + /obj/item/stock_parts/manipulator = 2, + /obj/item/stock_parts/matter_bin = 2 + ) + /obj/item/stock_parts/circuitboard/seed_extractor name = "circuitboard (seed extractor)" build_path = /obj/machinery/seed_extractor diff --git a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm index 845dfd8ed1c..48070e2e7e7 100644 --- a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm +++ b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm @@ -344,6 +344,9 @@ /datum/fabricator_recipe/imprinter/circuit/cooker path = /obj/item/stock_parts/circuitboard/cooker +/datum/fabricator_recipe/imprinter/circuit/centrifuge + path = /obj/item/stock_parts/circuitboard/centrifuge + /datum/fabricator_recipe/imprinter/circuit/seed_extractor path = /obj/item/stock_parts/circuitboard/seed_extractor diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index e453199fe21..bd7b83ef9d6 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -15,6 +15,18 @@ var/seeds_extracted = FALSE var/datum/seed/seed +// This is sort of pointless while food is a valid input on the ChemMaster but maybe +// in the future there will be some more interesting ways to process growns/food. +/obj/item/food/grown/handle_centrifuge_process(obj/machinery/centrifuge/centrifuge) + if(!(. = ..())) + return + if(reagents?.total_volume) + reagents.trans_to_holder(centrifuge.loaded_beaker.reagents, reagents.total_volume) + for(var/obj/item/thing in contents) + thing.dropInto(centrifuge.loc) + for(var/atom/movable/thing in convert_matter_to_lumps()) + thing.dropInto(centrifuge.loc) + /obj/item/food/grown/get_examine_strings(mob/user, distance, infix, suffix) . = ..() if(user && distance <= 1 && seed && user.skill_check(work_skill, SKILL_BASIC)) diff --git a/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm b/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm index 08eaa22b0c9..ad32f11030a 100644 --- a/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm +++ b/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm @@ -65,7 +65,7 @@ name = "spider venom" uid = "liquid_spider_venom" lore_text = "A deadly necrotic toxin produced by giant spiders to disable their prey." - taste_description = "absolutely vile" + taste_description = "vile poison" color = "#91d895" toxicity_targets_organ = BP_LIVER toxicity = 5 diff --git a/icons/obj/machines/centrifuge.dmi b/icons/obj/machines/centrifuge.dmi new file mode 100644 index 00000000000..6cae1e66cf3 Binary files /dev/null and b/icons/obj/machines/centrifuge.dmi differ diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm index f323c39ad5f..2c90ba1f9c2 100644 --- a/maps/exodus/exodus-2.dmm +++ b/maps/exodus/exodus-2.dmm @@ -26489,7 +26489,7 @@ pixel_x = -21; pixel_y = -10 }, -/obj/machinery/honey_extractor, +/obj/machinery/centrifuge/mapped, /turf/floor/tiled/steel_grid, /area/exodus/hydroponics/garden) "bev" = ( diff --git a/maps/ministation/ministation-1.dmm b/maps/ministation/ministation-1.dmm index 68b588d80e8..9ab4635ba0c 100644 --- a/maps/ministation/ministation-1.dmm +++ b/maps/ministation/ministation-1.dmm @@ -6040,7 +6040,7 @@ "zj" = ( /obj/effect/floor_decal/corner/beige/half, /obj/structure/table/glass, -/obj/machinery/honey_extractor, +/obj/machinery/centrifuge/mapped, /turf/floor/tiled, /area/ministation/hydro) "zl" = ( diff --git a/maps/tradeship/tradeship-0.dmm b/maps/tradeship/tradeship-0.dmm index ff571e169d9..05ce95d98f9 100644 --- a/maps/tradeship/tradeship-0.dmm +++ b/maps/tradeship/tradeship-0.dmm @@ -1562,7 +1562,7 @@ /turf/floor/tiled/steel_grid, /area/ship/trade/loading_bay) "yT" = ( -/obj/machinery/honey_extractor, +/obj/machinery/centrifuge/mapped, /obj/item/seeds/tomatoseed, /turf/floor, /area/ship/trade/aft_port_underside_maint) diff --git a/mods/content/beekeeping/_beekeeping.dm b/mods/content/beekeeping/_beekeeping.dm index cfa1427bbeb..d026d7d1f57 100644 --- a/mods/content/beekeeping/_beekeeping.dm +++ b/mods/content/beekeeping/_beekeeping.dm @@ -1,2 +1,17 @@ /decl/modpack/beekeeping name = "Beekeeping Content" + +/datum/storage/hopper/industrial/centrifuge/New() + ..() + can_hold |= /obj/item/honey_frame + +// Terrible, will be replaced in beewrite. +/datum/storage/hopper/industrial/centrifuge/should_ingest(mob/user, obj/item/thing) + if(istype(thing, /obj/item/honey_frame)) + var/obj/item/honey_frame/frame = thing + if(frame.honey > 0) + return TRUE + if(user) + to_chat(user, SPAN_WARNING("\The [thing] is empty.")) + return FALSE + return ..() diff --git a/mods/content/beekeeping/items.dm b/mods/content/beekeeping/items.dm index 69a888b2883..58778d36903 100644 --- a/mods/content/beekeeping/items.dm +++ b/mods/content/beekeeping/items.dm @@ -48,6 +48,16 @@ . = ..() overlays += "honeycomb" +// This is crap, will be replaced in beewrite PR. +/obj/item/honey_frame/handle_centrifuge_process(obj/machinery/centrifuge/centrifuge) + if(!(. = ..()) || !honey) + return + centrifuge?.loaded_beaker?.add_to_reagents(/decl/material/liquid/nutriment/honey, honey) + honey = 0 + new /obj/item/honey_frame(centrifuge.loc) + new /obj/item/stack/material/bar(centrifuge.loc, 1, /decl/material/solid/organic/wax) + qdel(src) + /obj/item/bee_pack name = "bee pack" desc = "Contains a queen bee and some worker bees. Everything you'll need to start a hive!" diff --git a/nebula.dme b/nebula.dme index d1296a75367..2f57515e37d 100644 --- a/nebula.dme +++ b/nebula.dme @@ -833,6 +833,7 @@ #include "code\game\machinery\buttons.dm" #include "code\game\machinery\CableLayer.dm" #include "code\game\machinery\cell_charger.dm" +#include "code\game\machinery\centrifuge.dm" #include "code\game\machinery\commsrelay.dm" #include "code\game\machinery\constructable_frame.dm" #include "code\game\machinery\cracker.dm"