diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index c157be159a4e..c1472d132ff8 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -9908,8 +9908,9 @@ "doR" = ( /obj/machinery/power/apc/auto_name/directional/south, /obj/structure/cable, -/obj/effect/mapping_helpers/apc/cell_5k, /obj/machinery/plumbing/ooze_compressor, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/effect/mapping_helpers/apc/full_charge, /turf/open/floor/iron/white, /area/station/science/xenobiology) "doW" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 29a07339b6ba..43768adc6127 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -42678,6 +42678,8 @@ /obj/effect/turf_decal/siding/purple{ dir = 9 }, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/effect/mapping_helpers/apc/full_charge, /turf/open/floor/iron, /area/station/science/xenobiology) "kpy" = ( @@ -89711,6 +89713,11 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/engineering/atmos) +"vUy" = ( +/obj/machinery/duct, +/obj/machinery/light/floor/has_bulb, +/turf/open/floor/engine, +/area/station/science/xenobiology) "vUz" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, @@ -121069,7 +121076,7 @@ feF gcr pTC iLv -gvX +vUy duq fMl fMl @@ -121079,7 +121086,7 @@ taA fMl fMl xsN -gvX +vUy iLv mAt aAx @@ -122868,7 +122875,7 @@ woj rrU pTC iLv -gvX +vUy pQz fMl fMl @@ -122878,7 +122885,7 @@ taA fMl fMl esm -gvX +vUy iLv mAt cZl diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 6cae56e2d386..10dc68395186 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -1194,6 +1194,8 @@ }, /obj/machinery/power/apc/auto_name/directional/south, /obj/structure/cable, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/effect/mapping_helpers/apc/full_charge, /turf/open/floor/iron/white, /area/station/science/xenobiology) "aut" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index bcc8844dcc25..b477ff8f1011 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -13278,6 +13278,8 @@ /obj/effect/turf_decal/tile/purple/half/contrasted{ dir = 8 }, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/effect/mapping_helpers/apc/full_charge, /turf/open/floor/iron/white, /area/station/science/cytology) "eYw" = ( @@ -32577,8 +32579,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/duct, -/obj/machinery/power/apc/auto_name/directional/west, -/obj/structure/cable, /turf/open/floor/stone, /area/station/science/xenobiology) "lJh" = ( @@ -49930,6 +49930,10 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/effect/mapping_helpers/apc/full_charge, +/obj/structure/cable, /turf/open/floor/stone, /area/station/science/xenobiology) "rMz" = ( diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 4903964ca680..cef5e292f535 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -19077,16 +19077,6 @@ }, /turf/open/floor/plating, /area/station/engineering/atmos/pumproom) -"eXC" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/catwalk_floor, -/area/station/maintenance/starboard/central) "eYi" = ( /obj/machinery/camera/directional/east, /mob/living/basic/chicken/brown, @@ -44319,6 +44309,16 @@ /obj/structure/cable, /turf/open/floor/carpet, /area/station/command/heads_quarters/hos) +"nme" = ( +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/effect/mapping_helpers/apc/full_charge, +/turf/open/floor/stone, +/area/station/science/xenobiology) "nmf" = ( /obj/structure/table/wood, /obj/machinery/computer/security/wooden_tv, @@ -54568,14 +54568,6 @@ /obj/structure/cable, /turf/open/space/basic, /area/space/nearstation) -"qCW" = ( -/obj/effect/turf_decal/trimline/purple/filled/line{ - dir = 1 - }, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/turf/open/floor/stone, -/area/station/science/xenobiology) "qCX" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -67180,6 +67172,16 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/cargo/drone_bay) +"uAW" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/catwalk_floor, +/area/station/maintenance/starboard/central) "uAZ" = ( /obj/effect/turf_decal/trimline/white/warning{ dir = 8 @@ -124267,7 +124269,7 @@ xPQ vud tml qVr -qCW +nme pbt xcM dtN @@ -126550,7 +126552,7 @@ hFC bwz xks qxm -eXC +uAW lLW iix tuN diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index 18a07c0d0197..b86931a592a5 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -7,6 +7,9 @@ #define IS_FINITE__UNSAFE(a) (a-a == a-a) #define IS_FINITE(a) (isnum(a) && IS_FINITE__UNSAFE(a)) + +#define IS_SAFE_NUM(a) (isnum(a) && !IS_INF__UNSAFE(a) && IS_FINITE__UNSAFE(a)) + // ------------------------------------ // Aight dont remove the rest diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 2ef99e3dc5f2..99d5fd4e91c9 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -508,6 +508,7 @@ /obj/item/reagent_containers/syringe, /obj/item/slime_extract, /obj/item/swab, + /obj/item/stack/biomass // monke: make science bags able to hold biomass cubes )) /* diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index a7c6c3baed07..366e4d2e692a 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -470,8 +470,8 @@ colour = "grey" /datum/status_effect/stabilized/grey/tick() - for(var/mob/living/basic/slime/S in range(1, get_turf(owner))) - SEND_SIGNAL(S, COMSIG_FRIENDSHIP_CHANGE, owner, 1) + for(var/mob/living/basic/slime/new_friend in range(3, get_turf(owner))) + SEND_SIGNAL(new_friend, COMSIG_FRIENDSHIP_CHANGE, owner, 1) return ..() /datum/status_effect/stabilized/orange diff --git a/monkestation/code/modules/slimecore/items/mutation_syringe.dm b/monkestation/code/modules/slimecore/items/mutation_syringe.dm index fd3998c06be8..75883df8a3ff 100644 --- a/monkestation/code/modules/slimecore/items/mutation_syringe.dm +++ b/monkestation/code/modules/slimecore/items/mutation_syringe.dm @@ -5,25 +5,41 @@ icon = 'monkestation/code/modules/slimecore/icons/slimes.dmi' icon_state = "mutation_syringe" - ///the path we infuse + w_class = WEIGHT_CLASS_SMALL + + /// Type path of the slime trait to infuse. var/datum/slime_trait/infusing_trait_path - /// have we been used? - var/used = FALSE + /// Amount of uses remaining. + var/uses = 1 +/obj/item/slime_mutation_syringe/examine(mob/user) + . = ..() + if(uses) + . += span_notice("It has [uses] uses left.") + else + . += span_warning("It has been completely used up.") /obj/item/slime_mutation_syringe/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() - if(!infusing_trait_path || used) + if(!ispath(infusing_trait_path)) + return + if(!uses) + user.balloon_alert(user, "used up") + to_chat(user, span_warning("[src] has been completely used up!")) return if(!istype(target, /mob/living/basic/slime)) return var/mob/living/basic/slime/slime = target if(slime.add_trait(infusing_trait_path)) - used = TRUE - icon_state = "mutation_syringe-empty" + uses-- + update_icon_state() + user.balloon_alert_to_viewers("injected mutator") to_chat(user, span_notice("You inject [target] with [src].")) +/obj/item/slime_mutation_syringe/update_icon_state() + . = ..() + icon_state = uses ? initial(icon_state) : "[initial(icon_state)]-empty" /obj/item/slime_mutation_syringe/cleaner name = "cleaner slime mutation syringe" @@ -64,19 +80,32 @@ icon = 'monkestation/code/modules/slimecore/icons/slimes.dmi' icon_state = "mutation_syringe" - /// have we been used? - var/used = FALSE + /// Amount of uses remaining. + var/uses = 1 +/obj/item/slime_mutation_syringe_random/examine(mob/user) + . = ..() + if(uses) + . += span_notice("It has [uses] uses left.") + else + . += span_warning("It has been completely used up.") /obj/item/slime_mutation_syringe_random/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() - if(used) + if(!uses) + user.balloon_alert(user, "used up") + to_chat(user, span_warning("[src] has been completely used up!")) return if(!istype(target, /mob/living/basic/slime)) return var/mob/living/basic/slime/slime = target slime.start_mutating(TRUE) - used = TRUE - icon_state = "mutation_syringe-empty" + uses-- + update_icon_state() + user.balloon_alert_to_viewers("injected mutator") to_chat(user, span_notice("You inject [target] with [src].")) + +/obj/item/slime_mutation_syringe_random/update_icon_state() + . = ..() + icon_state = uses ? initial(icon_state) : "[initial(icon_state)]-empty" diff --git a/monkestation/code/modules/slimecore/machines/biomass_recycler.dm b/monkestation/code/modules/slimecore/machines/biomass_recycler.dm index be89b669ffe2..bdb0a50209e1 100644 --- a/monkestation/code/modules/slimecore/machines/biomass_recycler.dm +++ b/monkestation/code/modules/slimecore/machines/biomass_recycler.dm @@ -34,37 +34,38 @@ GLOBAL_LIST_INIT(biomass_unlocks, list()) power_change() return TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/biomass_recycler/attackby(obj/item/O, mob/user, params) - if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", O)) - return - - if(default_pry_open(O)) - return - - if(default_deconstruction_crowbar(O)) +/obj/machinery/biomass_recycler/attackby(obj/item/item, mob/user, params) + . = ..() + if(. || default_deconstruction_screwdriver(user, "grinder_open", "grinder", item) || default_pry_open(item) || default_deconstruction_crowbar(item) || machine_stat) return - - if(machine_stat) //NOPOWER etc + if(istype(item, /obj/item/storage/bag/xeno)) + var/total_biomass = 0 + for(var/obj/item/stack/biomass/biomass in item) + total_biomass += biomass.amount + stored_matter += biomass.amount + qdel(biomass) + if(total_biomass > 0) + to_chat(user, span_notice("You dump [total_biomass] cube\s of biomass from [item] into [src].")) + user.balloon_alert_to_viewers("inserted biomass") return - - if(HAS_TRAIT(O, TRAIT_NODROP)) + else if(HAS_TRAIT(item, TRAIT_NODROP)) return - - if(istype(O, /obj/item/stack/biomass)) - var/obj/item/stack/biomass/biomass = O + else if(istype(item, /obj/item/stack/biomass)) + var/obj/item/stack/biomass/biomass = item to_chat(user, span_notice("You insert [biomass.amount] cube\s of biomass into [src].")) + user.balloon_alert_to_viewers("inserted biomass") stored_matter += biomass.amount qdel(biomass) return var/can_recycle for(var/recycable_type in recyclable_types) - if(istype(O, recycable_type)) + if(istype(item, recycable_type)) can_recycle = recycable_type break if(can_recycle) - recycle(O, user, can_recycle) + recycle(item, user, can_recycle) /obj/machinery/biomass_recycler/MouseDrop_T(mob/living/target, mob/living/user) if(!istype(target)) @@ -125,6 +126,7 @@ GLOBAL_LIST_INIT(biomass_unlocks, list()) var/spawn_type = item_names[pick] if(stored_matter < printable_types[spawn_type]) to_chat(user, span_warning("[src] does not have enough stored biomass for that! It currently has [stored_matter] out of [printable_types[spawn_type]] unit\s required.")) + balloon_alert(user, "not enough biomass") return var/spawned = new spawn_type(user.loc) @@ -139,7 +141,7 @@ GLOBAL_LIST_INIT(biomass_unlocks, list()) icon = 'monkestation/code/modules/slimecore/icons/stack_objects.dmi' icon_state = "biomass" base_icon_state = "biomass" - max_amount = 5 + max_amount = 15 singular_name = "biomass cube" merge_type = /obj/item/stack/biomass flags_1 = CONDUCT_1 diff --git a/monkestation/code/modules/slimecore/machines/extract_requestor.dm b/monkestation/code/modules/slimecore/machines/extract_requestor.dm index 1e254d48b130..faed4fff0690 100644 --- a/monkestation/code/modules/slimecore/machines/extract_requestor.dm +++ b/monkestation/code/modules/slimecore/machines/extract_requestor.dm @@ -6,8 +6,8 @@ base_icon_state = "civilian_pad" density = TRUE use_power = IDLE_POWER_USE - idle_power_usage = 10 - active_power_usage = 2000 + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION circuit = /obj/item/circuitboard/machine/slime_extract_requestor var/obj/machinery/computer/slime_market/console var/list/current_requests = list() diff --git a/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor.dm b/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor.dm index 8baef0b70d46..5ed9b18e56d8 100644 --- a/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor.dm +++ b/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor.dm @@ -18,12 +18,13 @@ icon = 'monkestation/code/modules/slimecore/icons/machinery.dmi' base_icon_state = "cross_compressor" icon_state = "cross_compressor" - category="Distribution" + category = "Distribution" anchored = TRUE - idle_power_usage = 10 - active_power_usage = 1000 + use_power = IDLE_POWER_USE + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION buffer = 5000 reagent_flags = NO_REACT @@ -74,9 +75,12 @@ /obj/machinery/plumbing/ooze_compressor/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() - context[SCREENTIP_CONTEXT_ALT_LMB] = "Toggle Repeated Extract Compression" - context[SCREENTIP_CONTEXT_LMB] = "Select a normal extract to make" - context[SCREENTIP_CONTEXT_RMB] = "Select a crossbreed to make" + if(current_recipe) + context[SCREENTIP_CONTEXT_RMB] = "Cancel current recipe" + else + context[SCREENTIP_CONTEXT_LMB] = "Select a normal extract to make" + context[SCREENTIP_CONTEXT_RMB] = "Select a crossbreed to make" + context[SCREENTIP_CONTEXT_CTRL_LMB] = "[repeat_recipe ? "Disable" : "Enable"] repeated extract compression" return CONTEXTUAL_SCREENTIP_SET /obj/machinery/plumbing/ooze_compressor/create_reagents(max_vol, flags) @@ -86,10 +90,7 @@ /obj/machinery/plumbing/ooze_compressor/update_icon_state() . = ..() - if(compressing) - icon_state = "cross_compressor_running" - else - icon_state = base_icon_state + icon_state = compressing ? "cross_compressor_running" : base_icon_state /obj/machinery/plumbing/ooze_compressor/examine(mob/user) . = ..() @@ -152,44 +153,73 @@ update_appearance() if(holder.total_volume == 0 && !compressing) //we were emptying, but now we aren't holder.flags |= NO_REACT + manage_hud_as_needed() return NONE -/obj/machinery/plumbing/ooze_compressor/process(seconds_per_tick) - if(!compressing) - use_power(active_power_usage * seconds_per_tick) - /obj/machinery/plumbing/ooze_compressor/proc/compress_recipe() compressing = TRUE update_appearance() if(!repeat_recipe) reagents_for_recipe = list() + manage_hud_as_needed() + update_power_usage() addtimer(CALLBACK(src, PROC_REF(finish_compressing)), 3 SECONDS) /obj/machinery/plumbing/ooze_compressor/proc/finish_compressing() for(var/i in 1 to current_recipe.created_amount) - new current_recipe.output_item(loc) + new current_recipe.output_item(drop_location()) compressing = FALSE update_appearance() reagents.clear_reagents() if(!repeat_recipe) current_recipe = null + update_power_usage() + manage_hud_as_needed() + +/obj/machinery/plumbing/ooze_compressor/proc/update_power_usage() + if(compressing) + update_use_power(ACTIVE_POWER_USE) + else if(current_recipe) + update_use_power(IDLE_POWER_USE) + else + update_use_power(NO_POWER_USE) /obj/machinery/plumbing/ooze_compressor/attack_hand(mob/living/user, list/modifiers) . = ..() + if(. || !can_interact(user)) + return + if(!anchored) + balloon_alert(user, "unanchored!") + return TRUE if(change_recipe(user)) reagents.clear_reagents() + return TRUE /obj/machinery/plumbing/ooze_compressor/attack_hand_secondary(mob/living/user, list/modifiers) . = ..() - if(change_recipe(user, TRUE)) - reagents.clear_reagents() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || !can_interact(user)) + return + . = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(!anchored) + balloon_alert(user, "unanchored!") + return + if(current_recipe) + repeat_recipe = FALSE + if(!compressing) + current_recipe = null + reagents.clear_reagents() + update_power_usage() + balloon_alert_to_viewers("cancelled recipe") + else + if(change_recipe(user, TRUE)) + reagents.clear_reagents() -/obj/machinery/plumbing/ooze_compressor/AltClick(mob/user) - if(anchored) - visible_message(span_notice("[user] presses a button turning the repeat recipe system [repeat_recipe ? "Off" : "On"]")) +/obj/machinery/plumbing/ooze_compressor/CtrlClick(mob/user) + if(anchored && can_interact(user)) repeat_recipe = !repeat_recipe - return TRUE - . = ..() + balloon_alert_to_viewers("[repeat_recipe ? "enabled" : "disabled"] repeating") + visible_message(span_notice("[user] presses a button turning the repeat recipe system [repeat_recipe ? span_green("on") : span_red("off")]")) + return ..() /obj/machinery/plumbing/ooze_compressor/proc/change_recipe(mob/user, cross_breed = FALSE) var/choice @@ -201,14 +231,14 @@ else choice = show_radial_menu(user, src, recipe_choices, require_near = TRUE, tooltips = TRUE) - if(!(choice in choice_to_datum)) - return - - if(compressing) + if(compressing || !(choice in choice_to_datum)) return current_recipe = choice_to_datum[choice] reagents_for_recipe = list() reagents_for_recipe += current_recipe.required_oozes + balloon_alert_to_viewers("set extract recipe") + manage_hud_as_needed() + update_power_usage() #undef CROSSBREED_BASE_PATHS diff --git a/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor_hud.dm b/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor_hud.dm new file mode 100644 index 000000000000..bec098500afa --- /dev/null +++ b/monkestation/code/modules/slimecore/machines/ooze_compressor/ooze_compressor_hud.dm @@ -0,0 +1,127 @@ +/obj/machinery/plumbing/ooze_compressor + var/image/hover_appearance + var/datum/atom_hud/alternate_appearance/basic/ooze_compressor/hover_popup + +/obj/machinery/plumbing/ooze_compressor/Destroy() + QDEL_NULL(hover_popup) + return ..() + +/obj/machinery/plumbing/ooze_compressor/MouseEntered(location, control, params) + . = ..() + if(!QDELETED(usr) && anchored) + manage_hud_as_needed() + hover_popup?.show_to(usr) + +/obj/machinery/plumbing/ooze_compressor/MouseExited(location, control, params) + . = ..() + if(!QDELETED(usr) && !QDELETED(hover_popup)) + hover_popup.hide_from(usr) + manage_hud_as_needed(cleanup = TRUE) + +/obj/machinery/plumbing/ooze_compressor/set_anchored(anchorvalue) + . = ..() + if(!anchored) + manage_hud_as_needed() + +/obj/machinery/plumbing/ooze_compressor/proc/manage_hud_as_needed(cleanup = FALSE) + if(!anchored || (cleanup && !QDELETED(hover_popup) && !length(hover_popup.hud_users_all_z_levels))) + // don't bother keeping the hud around if it isn't needed + QDEL_NULL(hover_popup) + return + setup_hud() + +/obj/machinery/plumbing/ooze_compressor/proc/setup_hud() + // delete old hud if it exists and collect a list of its users + var/list/mob/old_users + if(!QDELETED(hover_popup)) + old_users = hover_popup.hud_users_all_z_levels.Copy() + QDEL_NULL(hover_popup) + + if(!length(GLOB.compressor_recipe_previews)) // we can't initialize this normally bc it will shit itself if initialized early + GLOB.compressor_recipe_previews = create_compressor_previews() + + // setup new hover appearance + if(current_recipe) + hover_appearance = image(GLOB.compressor_recipe_previews[current_recipe.type], loc = src, layer = CHAT_LAYER) + hover_appearance.add_filter("extract_outline", 1, outline_filter(size = 1, color = COLOR_WHITE)) + hover_appearance.pixel_y = 10 + else + hover_appearance = image(loc = src, layer = CHAT_LAYER) + hover_appearance.pixel_y = 18 + SET_PLANE_EXPLICIT(hover_appearance, HUD_PLANE, src) + hover_appearance.plane = HUD_PLANE + hover_appearance.appearance_flags = RESET_COLOR + + // now setup the actual hud + hover_popup = add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/ooze_compressor, "ooze_compressor", hover_appearance) + // and the cooldown maptext + refresh_info_maptext() + + for(var/mob/old_user as anything in old_users) + if(QDELETED(old_user)) + continue + hover_popup.show_to(old_user) + +/obj/machinery/plumbing/ooze_compressor/proc/refresh_info_maptext() + if(!hover_popup) + return + if(!hover_popup.info_maptext) + hover_popup.info_maptext = image(loc = src, layer = CHAT_LAYER + 0.1) + SET_PLANE_EXPLICIT(hover_popup.info_maptext, HUD_PLANE, src) + hover_popup.info_maptext.plane = HUD_PLANE + hover_popup.info_maptext.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART + hover_popup.info_maptext.maptext_height = world.icon_size / 2 + hover_popup.info_maptext.maptext_y = 4 + var/maptext + if(compressing) + hover_popup.info_maptext.maptext_width = world.icon_size * 2 + hover_popup.info_maptext.maptext_x = -(world.icon_size / 2) + maptext = "compressing..." + else + hover_popup.info_maptext.maptext_width = world.icon_size + hover_popup.info_maptext.maptext_x = 0 + maptext = current_recipe ? "[get_progress()]%" : "inactive" + hover_popup.info_maptext.maptext = MAPTEXT_TINY_UNICODE("[maptext]") + hover_popup.give_info() + +/obj/machinery/plumbing/ooze_compressor/proc/get_progress() + if(!current_recipe || compressing) + return 0 + var/current = 0 + var/needed = 0 + for(var/datum/reagent/reagent as anything in current_recipe.required_oozes) + needed += current_recipe.required_oozes[reagent] || 0 + for(var/datum/reagent/listed_reagent as anything in reagents.reagent_list) + if(listed_reagent.type != reagent) + continue + current += listed_reagent.volume + return clamp(round((current / needed) * 100, 1), 0, 100) + +/datum/atom_hud/alternate_appearance/basic/ooze_compressor + var/image/info_maptext + +/datum/atom_hud/alternate_appearance/basic/ooze_compressor/show_to(mob/new_viewer) + . = ..() + if(info_maptext && !QDELETED(new_viewer) && !QDELETED(new_viewer.client)) + new_viewer.client.images |= info_maptext + +/datum/atom_hud/alternate_appearance/basic/ooze_compressor/hide_from(mob/former_viewer, absolute) + . = ..() + if(info_maptext && !QDELETED(former_viewer) && !QDELETED(former_viewer.client)) + former_viewer.client.images -= info_maptext + +/datum/atom_hud/alternate_appearance/basic/ooze_compressor/proc/give_info() + if(!info_maptext) + return + for(var/mob/user as anything in hud_users_all_z_levels) + if(QDELETED(user) || QDELETED(user.client)) + continue + user.client.images |= info_maptext + +/datum/atom_hud/alternate_appearance/basic/ooze_compressor/proc/take_cooldowns() + if(!info_maptext) + return + for(var/mob/user as anything in hud_users_all_z_levels) + if(QDELETED(user) || QDELETED(user.client)) + continue + user.client.images -= info_maptext diff --git a/monkestation/code/modules/slimecore/machines/ooze_compressor/recipes/_base_recipe.dm b/monkestation/code/modules/slimecore/machines/ooze_compressor/recipes/_base_recipe.dm index a60288732cb3..dbc827f25b35 100644 --- a/monkestation/code/modules/slimecore/machines/ooze_compressor/recipes/_base_recipe.dm +++ b/monkestation/code/modules/slimecore/machines/ooze_compressor/recipes/_base_recipe.dm @@ -1,6 +1,18 @@ +GLOBAL_LIST_EMPTY_TYPED(compressor_recipe_previews, /image) + /datum/compressor_recipe var/list/required_oozes = list() var/obj/item/output_item var/created_amount = 1 /datum/compressor_recipe/crossbreed + +/proc/create_compressor_previews() + . = list() + for(var/datum/compressor_recipe/recipe as anything in subtypesof(/datum/compressor_recipe)) + var/output_type = recipe::output_item + if(!ispath(output_type, /obj/item)) + continue + var/obj/item/preview = new output_type(null) + .[recipe] = image(getFlatIcon(preview)) + qdel(preview) diff --git a/monkestation/code/modules/slimecore/machines/ooze_sucker.dm b/monkestation/code/modules/slimecore/machines/ooze_sucker.dm index 216edb7dfdbe..69f2f497ee76 100644 --- a/monkestation/code/modules/slimecore/machines/ooze_sucker.dm +++ b/monkestation/code/modules/slimecore/machines/ooze_sucker.dm @@ -7,10 +7,13 @@ icon_state = "ooze_sucker" anchored = FALSE density = FALSE - idle_power_usage = 10 - active_power_usage = 1000 + + use_power = IDLE_POWER_USE + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.1 + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.15 + buffer = 3000 - category="Distribution" + category = "Distribution" reagent_flags = NO_REACT /// Pump is turned on by engineer, etc. @@ -31,6 +34,9 @@ /// Additional ratio of liquid volume to drain var/drain_percent = 1 + /// Whether draining was performed last process or not. + var/drained_last_process = FALSE + /obj/machinery/plumbing/ooze_sucker/Initialize(mapload, bolt, layer) . = ..() AddComponent(/datum/component/plumbing/simple_supply, bolt, layer) @@ -68,6 +74,22 @@ turned_on = FALSE update_icon_state() +/obj/machinery/plumbing/ooze_sucker/create_reagents(max_vol, flags) + . = ..() + RegisterSignals(reagents, list(COMSIG_REAGENTS_REM_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_CLEAR_REAGENTS, COMSIG_REAGENTS_REACTED), PROC_REF(on_reagent_change)) + RegisterSignal(reagents, COMSIG_QDELETING, PROC_REF(on_reagents_del)) + +/// Handles properly detaching signal hooks. +/obj/machinery/plumbing/ooze_sucker/proc/on_reagents_del(datum/reagents/reagents) + SIGNAL_HANDLER + UnregisterSignal(reagents, list(COMSIG_REAGENTS_REM_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_CLEAR_REAGENTS, COMSIG_REAGENTS_REACTED, COMSIG_QDELETING)) + return NONE + +/// Handles ensuring power usage becomes idle when reagents are full. +/obj/machinery/plumbing/ooze_sucker/proc/on_reagent_change(datum/reagents/holder, ...) + SIGNAL_HANDLER + update_power_usage() + return NONE /obj/machinery/plumbing/ooze_sucker/proc/toggle_state() turned_on = !turned_on @@ -109,12 +131,25 @@ // We're good, actually pump. for(var/turf/affected_turf as anything in affected_turfs) pump_turf(affected_turf, seconds_per_tick, multiplier) + update_power_usage() + +/obj/machinery/plumbing/ooze_sucker/proc/update_power_usage() + if(!turned_on) + update_use_power(NO_POWER_USE) + else if(reagents && reagents.total_volume >= reagents.maximum_volume) + update_use_power(IDLE_POWER_USE) + else if(drained_last_process) + update_use_power(ACTIVE_POWER_USE) + else + update_use_power(IDLE_POWER_USE) /obj/machinery/plumbing/ooze_sucker/proc/pump_turf(turf/affected_turf, seconds_per_tick, multiplier) if(processes < processes_required) processes++ return processes = 0 + drained_last_process = FALSE + if(!affected_turf.liquids || !affected_turf.liquids.liquid_group) return @@ -128,3 +163,12 @@ if(!targeted_group.reagents_per_turf) return targeted_group.transfer_specific_reagents(reagents, target_value, reagents_to_check = typesof(/datum/reagent/slime_ooze), merge = TRUE) + drained_last_process = TRUE + +/obj/machinery/plumbing/ooze_sucker/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + toggle_state() + balloon_alert_to_viewers("[turned_on ? "enabled" : "disabled"] ooze sucker") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/monkestation/code/modules/slimecore/machines/slime_grinder.dm b/monkestation/code/modules/slimecore/machines/slime_grinder.dm index 4cb79b472b19..b5ef7280e7c1 100644 --- a/monkestation/code/modules/slimecore/machines/slime_grinder.dm +++ b/monkestation/code/modules/slimecore/machines/slime_grinder.dm @@ -7,8 +7,11 @@ icon = 'monkestation/code/modules/slimecore/icons/slime_grinder.dmi' icon_state = "slime_grinder_backdrop" base_icon_state = "slime_grinder_backdrop" - idle_power_usage = 10 - active_power_usage = 1000 + + use_power = IDLE_POWER_USE + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION + buffer = 3000 category="Distribution" diff --git a/monkestation/code/modules/slimecore/machines/slime_market.dm b/monkestation/code/modules/slimecore/machines/slime_market.dm index 8e299bec9cda..57cd96c8397b 100644 --- a/monkestation/code/modules/slimecore/machines/slime_market.dm +++ b/monkestation/code/modules/slimecore/machines/slime_market.dm @@ -6,25 +6,11 @@ base_icon_state = "market_pad" density = TRUE use_power = IDLE_POWER_USE - idle_power_usage = 10 - active_power_usage = 2000 + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION circuit = /obj/item/circuitboard/machine/slime_market_pad var/obj/machinery/computer/slime_market/console -/obj/machinery/slime_market_pad/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) - user.visible_message(span_notice("\The [user] [panel_open ? "opens" : "closes"] the hatch on \the [src]."), span_notice("You [panel_open ? "open" : "close"] the hatch on \the [src].")) - update_appearance() - return TRUE - - if(default_unfasten_wrench(user, I)) - return TRUE - - if(default_deconstruction_crowbar(I)) - return TRUE - - . = ..() - /obj/machinery/slime_market_pad/examine(mob/user) . = ..() if(!panel_open) @@ -41,6 +27,8 @@ /obj/machinery/slime_market_pad/AltClick(mob/user) . = ..() + if(!.) + return link_console() /obj/machinery/slime_market_pad/proc/link_console() @@ -53,30 +41,39 @@ console.link_market_pad() break -/obj/machinery/slime_market_pad/attackby(obj/item/I, mob/living/user, params) +/obj/machinery/slime_market_pad/attackby(obj/item/item, mob/living/user, params) . = ..() - if(!console) + if(. || !can_interact(user)) + return + if(default_deconstruction_screwdriver(user, icon_state, icon_state, item)) + user.visible_message(span_notice("\The [user] [panel_open ? "opens" : "closes"] the hatch on \the [src]."), span_notice("You [panel_open ? "open" : "close"] the hatch on \the [src].")) + update_appearance() + return TRUE + if(default_unfasten_wrench(user, item) || default_deconstruction_crowbar(item)) + return TRUE + if(QDELETED(console)) to_chat(user, span_warning("[src] does not have a console linked to it!")) return - - if(istype(I, /obj/item/slime_extract)) - var/obj/item/slime_extract/extract = I + if(istype(item, /obj/item/slime_extract)) + var/obj/item/slime_extract/extract = item if(extract.tier == 0) to_chat(user, span_warning("[src] doesn't seem to accept this extract!")) return flick("[base_icon_state]_vend", src) sell_extract(extract) return - - else if(istype(I, /obj/item/storage/bag/xeno)) - if(tgui_alert(user, "Are you sure you want to sell all extracts from [I]?", "<3?", list("Yes", "No")) != "Yes") + else if(istype(item, /obj/item/storage/bag/xeno)) + if(tgui_alert(user, "Are you sure you want to sell all extracts from [item]?", "<3?", list("Yes", "No")) != "Yes") return - flick("[base_icon_state]_vend", src) - for(var/obj/item/slime_extract/extract in I) + var/sold_extracts = 0 + for(var/obj/item/slime_extract/extract in item) if(extract.tier == 0) continue sell_extract(extract) + sold_extracts++ + if(sold_extracts > 0) + user.balloon_alert_to_viewers("sold [sold_extracts] extracts") return /obj/machinery/slime_market_pad/proc/sell_extract(obj/item/slime_extract/extract) @@ -97,23 +94,38 @@ SSresearch.slime_core_prices[core_type] = (1 + price_mod * price_limiter) * SSresearch.slime_core_prices[core_type] qdel(extract) -/obj/machinery/slime_market_pad/attackby_secondary(obj/item/weapon, mob/user, params) - if(!console) - to_chat(user, span_warning("[src] does not have a console linked to it!")) +/obj/machinery/slime_market_pad/attackby_secondary(obj/item/item, mob/user, params) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || !can_interact(user)) return + if(QDELETED(console)) + to_chat(user, span_warning("[src] does not have a console linked to it!")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(!console.request_pad) + if(istype(item, /obj/item/storage/bag/xeno)) + flick("[base_icon_state]_vend", src) + var/sold_extracts = 0 + for(var/obj/item/slime_extract/extract in item) + if(extract.tier == 0) + continue + sell_extract(extract) + sold_extracts++ + if(sold_extracts > 0) + user.balloon_alert_to_viewers("sold [sold_extracts] extracts") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(QDELETED(console.request_pad)) to_chat(user, span_warning("[console] does not have a request_pad linked to it!")) - return + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN if(!length(console.request_pad.current_requests)) to_chat(user, span_warning("There are no current extract requests!")) - return + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(istype(weapon, /obj/item/slime_extract)) + if(istype(item, /obj/item/slime_extract)) var/list/radial_choices = list() var/list/choice_to_request = list() - var/obj/item/slime_extract/extract = weapon + var/obj/item/slime_extract/extract = item for(var/datum/extract_request_data/current as anything in console.request_pad.current_requests) if((current.extract_path != extract.type) || current.ready_for_pickup) continue @@ -134,4 +146,4 @@ flick("[base_icon_state]_vend", src) qdel(extract) - return + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/monkestation/code/modules/slimecore/machines/slime_market_computer.dm b/monkestation/code/modules/slimecore/machines/slime_market_computer.dm index 3c86eb44af7a..a3394c7a0105 100644 --- a/monkestation/code/modules/slimecore/machines/slime_market_computer.dm +++ b/monkestation/code/modules/slimecore/machines/slime_market_computer.dm @@ -66,7 +66,7 @@ GLOBAL_DATUM(default_slime_market, /obj/machinery/computer/slime_market) /obj/machinery/computer/slime_market/ui_assets(mob/user) return list( - get_asset_datum(/datum/asset/spritesheet/xenobio_market), + get_asset_datum(/datum/asset/spritesheet/xenobio_market) ) /obj/machinery/computer/slime_market/ui_interact(mob/user, datum/tgui/ui) @@ -110,19 +110,21 @@ GLOBAL_DATUM(default_slime_market, /obj/machinery/computer/slime_market) iter += 1 var/obj/item/slime_extract/core = core_type - var/list/core_data = list("icon" = "[initial(core.icon_state)]", - "price" = SSresearch.slime_core_prices[core_type], - "key" = iter % 4, - ) + var/list/core_data = list( + "icon" = "[initial(core.icon_state)]", + "price" = SSresearch.slime_core_prices[core_type], + "key" = iter % 4 + ) price_row.Add(list(core_data)) iter += 1 if(core_type == /obj/item/slime_extract/grey) core = /obj/item/slime_extract/rainbow - var/list/rainbow_core_data = list("icon" = "[initial(core.icon_state)]", - "price" = SSresearch.slime_core_prices[/obj/item/slime_extract/rainbow], - "key" = iter % 4, - ) + var/list/rainbow_core_data = list( + "icon" = "[initial(core.icon_state)]", + "price" = SSresearch.slime_core_prices[/obj/item/slime_extract/rainbow], + "key" = iter % 4 + ) price_row.Add(list(rainbow_core_data)) iter += 1 price_row.Add(list(list("key" = iter % 4))) diff --git a/monkestation/code/modules/slimecore/machines/slime_pen_controller.dm b/monkestation/code/modules/slimecore/machines/slime_pen_controller.dm index e071ac929ecb..862b41467872 100644 --- a/monkestation/code/modules/slimecore/machines/slime_pen_controller.dm +++ b/monkestation/code/modules/slimecore/machines/slime_pen_controller.dm @@ -28,7 +28,6 @@ . = ..() locate_machinery() - /obj/machinery/slime_pen_controller/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() @@ -69,13 +68,13 @@ var/list/mutation_info = list() var/mob_string for(var/mob/living/mob as anything in mutation_data.latch_needed) - mob_string += "[mutation_data.latch_needed[mob]] units of genetic data from [initial(mob.name)]. \n" + mob_string += "[mutation_data.latch_needed[mob]] units of genetic data from [mob::name]. \n" var/item_string for(var/obj/item/item as anything in mutation_data.needed_items) - item_string += "[initial(item.name)]. \n" + item_string += "[item:name]. \n" mutation_info += list( - "color" = capitalize(initial(mutation_data.output.name)), + "color" = capitalize(mutation_data.output::name), "weight" = mutation_data.weight, "mutate_chance" = mutation_data.mutate_probability, "mobs_needed" = mob_string, @@ -135,7 +134,6 @@ . = ..() if(.) return - switch(action) if("buy") for(var/datum/corral_upgrade/item as anything in subtypesof(/datum/corral_upgrade)) @@ -146,7 +144,7 @@ /obj/machinery/slime_pen_controller/proc/try_buy(datum/corral_upgrade/item) if(!linked_data) return - if(SSresearch.xenobio_points < initial(item.cost)) + if(SSresearch.xenobio_points < item::cost) return var/datum/corral_upgrade/new_upgrade = new item @@ -165,25 +163,23 @@ return /obj/machinery/slime_pen_controller/attack_hand_secondary(mob/user, list/modifiers) - if(linked_sucker) - visible_message(span_notice("[user] fiddles with the [src] toggling the pens ooze sucker.")) - linked_sucker.toggle_state() - return TRUE . = ..() - -/obj/machinery/slime_pen_controller/attackby(obj/item/weapon, mob/user, params) - if(weapon.tool_behaviour == TOOL_MULTITOOL) - if(!multitool_check_buffer(user, weapon)) - return - var/obj/item/multitool/M = weapon - if(!M.buffer) - return - var/obj/machinery/corral_corner/pad = M.buffer - if(!istype(pad)) - return - if(!pad.connected_data) - return - linked_data = pad.connected_data - to_chat(user, span_notice("You link the [pad] to the [src].")) + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) return + if(!QDELETED(linked_sucker)) + linked_sucker.toggle_state() + balloon_alert_to_viewers("[linked_sucker.turned_on ? "enabled" : "disabled"] ooze sucker") + visible_message(span_notice("[user] fiddles with the [src], [linked_sucker.turned_on ? "enabling" : "disabling"] the pens ooze sucker.")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/slime_pen_controller/multitool_act(mob/living/user, obj/item/multitool/multitool) . = ..() + if(!multitool_check_buffer(user, multitool) || QDELETED(multitool.buffer)) + return + var/obj/machinery/corral_corner/pad = multitool.buffer + if(!istype(pad) || !pad.connected_data) + return + linked_data = pad.connected_data + balloon_alert_to_viewers("linked pad") + pad.balloon_alert_to_viewers("linked to controller") + to_chat(user, span_notice("You link the [pad] to the [src].")) diff --git a/monkestation/code/modules/slimecore/mobs/_base_slime.dm b/monkestation/code/modules/slimecore/mobs/_base_slime.dm index dfbe5d102b8a..5b21399ca0ba 100644 --- a/monkestation/code/modules/slimecore/mobs/_base_slime.dm +++ b/monkestation/code/modules/slimecore/mobs/_base_slime.dm @@ -162,6 +162,7 @@ /mob/living/basic/slime/mob_try_pickup(mob/living/user, instant) if(!SEND_SIGNAL(src, COMSIG_FRIENDSHIP_CHECK_LEVEL, user, FRIENDSHIP_FRIEND)) to_chat(user, span_notice("[src] doesn't trust you enough to let you pick them up")) + balloon_alert(user, "not enough trust!") return FALSE . = ..() @@ -188,10 +189,9 @@ /mob/living/basic/slime/proc/recompile_ai_tree() var/list/new_planning_subtree = list() + RemoveElement(/datum/element/basic_eating, food_types = compiled_liked_foods) rebuild_foods() - RemoveElement(/datum/element/basic_eating) - new_planning_subtree |= add_or_replace_tree(/datum/ai_planning_subtree/pet_planning) if(!HAS_TRAIT(src, TRAIT_SLIME_RABID)) @@ -310,6 +310,7 @@ slime_flags |= SPLITTING_SLIME visible_message(span_notice("[name] starts to flatten, it looks to be splitting.")) + balloon_alert_to_viewers("splitting...") addtimer(CALLBACK(src, PROC_REF(finish_splitting)), 15 SECONDS) @@ -331,6 +332,7 @@ ai_controller.set_ai_status(AI_STATUS_OFF) visible_message(span_notice("[name] starts to undulate, it looks to be mutating.")) + balloon_alert_to_viewers("mutating...") slime_flags |= MUTATING_SLIME ungulate() @@ -414,8 +416,9 @@ . = ..() if(worn_accessory) visible_message("[user] takes the [worn_accessory] off the [src].") + balloon_alert_to_viewers("removed accessory") + worn_accessory.forceMove(user.drop_location()) worn_accessory = null - worn_accessory.forceMove(get_turf(user)) update_appearance() /mob/living/basic/slime/Life(seconds_per_tick, times_fired) diff --git a/tgstation.dme b/tgstation.dme index f548884e8d07..c31a3328ff04 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6759,6 +6759,7 @@ #include "monkestation\code\modules\slimecore\machines\slime_market_computer.dm" #include "monkestation\code\modules\slimecore\machines\slime_pen_controller.dm" #include "monkestation\code\modules\slimecore\machines\ooze_compressor\ooze_compressor.dm" +#include "monkestation\code\modules\slimecore\machines\ooze_compressor\ooze_compressor_hud.dm" #include "monkestation\code\modules\slimecore\machines\ooze_compressor\ooze_compressor_plumbing.dm" #include "monkestation\code\modules\slimecore\machines\ooze_compressor\shitcode.dm" #include "monkestation\code\modules\slimecore\machines\ooze_compressor\recipes\_base_recipe.dm"