Botanic trays: the hydroponics without hydro! (soil but better) (#96236)

## About The Pull Request
🚨THIS IS AN ADVANCED VERSION OF #96227 WITH NEW FEATURES, CLOSE #96227
IF THIS IS MERGED 🚨
this pr adds botanic trays - you can get one by filling an empty
hydroponic tray with any soil!
the botanic tray acts like a pile of soil but it can be upgraded, has
auto-grow and indicators.
once you fill the tray there is no way back - it becomes botanic
permanently (until you deconstruct it)

<details>
    <summary> Sprites </summary>

<img width="856" height="846" alt="image"
src="https://github.com/user-attachments/assets/ca9e2a55-ba29-4d08-80e7-aa79e73bb79f"
/>

<img width="825" height="285" alt="image"
src="https://github.com/user-attachments/assets/815e93c2-47cd-4540-86ae-0d2bd8efd325"
/>

Default on the left, reskin on the right
sprites made by me (trays from #96227 made by kreks) (also works with
old-designed tray mode)
see #96227 for tray resprite old/new
</details>


## Why It's Good For The Game
soil is boring and almost no one uses it
emissive is cool
you can now see the type of soil in your tray even when the auto-growth
is on


## Changelog
🆑
add: added botanic trays - hydroponic trays with soil instead of water,
just fill a tray with any soil and done!
image: resprited auto-growth mode and added emissives to it
image: resprited hydroponic trays 
add: added old-designed mode for hydroponic trays - use a screwdriver or
a plant analyzer on the circuit!
image: added emissives to hydroponic tray indicators
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
MelokG
2026-06-04 17:19:38 +02:00
committed by GitHub
co-authored by MrMelbert Ghom
parent 34500f77eb
commit 606ec48bd7
3 changed files with 96 additions and 10 deletions
@@ -1316,6 +1316,27 @@
/obj/item/stack/sheet/glass = 1)
needs_anchored = FALSE
/obj/item/circuitboard/machine/hydroponics/proc/changeindicators(mob/living/user, obj/item/I)
if(build_path == /obj/machinery/hydroponics/constructable/oldstyle)
name = "Hydroponics Tray"
build_path = /obj/machinery/hydroponics/constructable
balloon_alert(user, "defaulting indicator location.")
else
name = "Old-Designed Hydropoincs Tray"
build_path = /obj/machinery/hydroponics/constructable/oldstyle
balloon_alert(user, "moving the indicators...")
return TRUE
/obj/item/circuitboard/machine/hydroponics/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/plant_analyzer))
changeindicators(user)
else
return ..()
/obj/item/circuitboard/machine/hydroponics/screwdriver_act(mob/living/user, obj/item/tool)
src.changeindicators(user)
return
/obj/item/circuitboard/machine/hydroponics/fullupgrade
build_path = /obj/machinery/hydroponics/constructable/fullupgrade
specific_parts = TRUE
+75 -10
View File
@@ -1,4 +1,3 @@
/obj/machinery/hydroponics
name = "hydroponics tray"
desc = "A basin used to grow plants in."
@@ -53,6 +52,8 @@
var/datum/weakref/lastuser
///If the tray generates nutrients and water on its own
var/self_sustaining = FALSE
///If the tray is currently able to self-sustain
var/can_self_sustain = TRUE
///The icon state for the overlay used to represent that this tray is self-sustaining.
var/self_sustaining_overlay_icon_state = "gaia_blessing"
///Whether the plant is currently being pollinated or polinating the nearby plants
@@ -65,7 +66,12 @@
var/tray_flags = HYDROPONIC
///How many extra px to offset the plant sprite on the y axis, gets passed to the seed and added to the seeds offset
var/plant_offset_y = 0
///Suffix things
var/alt_tray = FALSE
var/indicatorsuffix = ""
///Soil things
var/obj/machinery/hydroponics/soil/current_soil = null
var/current_soil_overlay = null
/obj/machinery/hydroponics/Initialize(mapload)
//ALRIGHT YOU DEGENERATES. YOU HAD REAGENT HOLDERS FOR AT LEAST 4 YEARS AND NONE OF YOU MADE HYDROPONICS TRAYS HOLD NUTRIENT CHEMS INSTEAD OF USING "Points".
@@ -167,6 +173,12 @@
icon = 'icons/obj/service/hydroponics/equipment.dmi'
icon_state = "hydrotray3"
/obj/machinery/hydroponics/constructable/oldstyle
name = "hydroponics tray"
icon = 'icons/obj/service/hydroponics/equipment.dmi'
icon_state = "hydrotray3-alt"
alt_tray = TRUE
/obj/machinery/hydroponics/constructable/fullupgrade
name = "deluxe hydroponics tray"
desc = "A basin used to grown plants in, packed full of cutting-edge technology."
@@ -179,6 +191,9 @@
AddComponent(/datum/component/usb_port, typecacheof(list(/obj/item/circuit_component/hydroponics), only_root_path = TRUE))
AddComponent(/datum/component/fishing_spot, /datum/fish_source/hydro_tray)
/obj/machinery/hydroponics/constructable/on_deconstruction(disassembled)
current_soil?.forceMove(drop_location())
/obj/machinery/hydroponics/constructable/RefreshParts()
. = ..()
var/tmp_capacity = 0
@@ -186,8 +201,12 @@
tmp_capacity += matter_bin.tier
for (var/datum/stock_part/servo/servo in component_parts)
rating = servo.tier
maxwater = tmp_capacity * 50 // Up to 300
maxnutri = (tmp_capacity * 5) + STATIC_NUTRIENT_CAPACITY // Up to 50 Maximum
if(current_soil)
maxwater = current_soil.maxwater + ((tmp_capacity - 2)*50)
maxnutri = current_soil.maxnutri + ((tmp_capacity - 2)*5)
else
maxwater = tmp_capacity * 50
maxnutri = (tmp_capacity * 5) + STATIC_NUTRIENT_CAPACITY
reagents.maximum_volume = maxnutri
nutridrain = 1/rating
@@ -464,21 +483,32 @@
. += myseed.get_tray_overlay(age, plant_status, plant_offset_y)
. += update_status_light_overlays()
if(current_soil && current_soil_overlay)
. += mutable_appearance(icon, current_soil_overlay, OBJ_LAYER + 0.001)
if(self_sustaining && self_sustaining_overlay_icon_state)
. += mutable_appearance(icon, self_sustaining_overlay_icon_state)
. += mutable_appearance(icon, self_sustaining_overlay_icon_state, OBJ_LAYER + 0.002)
. += emissive_appearance(icon, self_sustaining_overlay_icon_state, src, OBJ_LAYER + 0.002)
/obj/machinery/hydroponics/proc/update_status_light_overlays()
. = list()
if(alt_tray)
indicatorsuffix = "-alt"
if(waterlevel <= 10)
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_lowwater3")
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_lowwater3[indicatorsuffix]")
. += emissive_appearance(icon, "over_lowwater3[indicatorsuffix]", src, alpha = src.alpha)
if(reagents.total_volume <= 2)
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_lownutri3")
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_lownutri3[indicatorsuffix]")
. += emissive_appearance(icon, "over_lownutri3[indicatorsuffix]", src, alpha = src.alpha)
if(plant_health <= (myseed.endurance / 2))
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_lowhealth3")
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_lowhealth3[indicatorsuffix]")
. += emissive_appearance(icon, "over_lowhealth3[indicatorsuffix]", src, alpha = src.alpha)
if(weedlevel >= 5 || pestlevel >= 5 || toxic >= 40)
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_alert3")
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_alert3[indicatorsuffix]")
. += emissive_appearance(icon, "over_alert3[indicatorsuffix]", src, alpha = src.alpha)
if(plant_status == HYDROTRAY_PLANT_HARVESTABLE)
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_harvest3")
. += mutable_appearance('icons/obj/service/hydroponics/equipment.dmi', "over_harvest3[indicatorsuffix]")
. += emissive_appearance(icon, "over_harvest3[indicatorsuffix]", src, alpha = src.alpha)
///Sets a new value for the myseed variable, which is the seed of the plant that's growing inside the tray.
/obj/machinery/hydroponics/proc/set_seed(obj/item/seeds/new_seed, delete_old_seed = TRUE)
@@ -1063,6 +1093,37 @@
flowergun.update_appearance()
to_chat(user, span_notice("[myseed.plantname]'s mutation was set to [locked_mutation], depleting [flowergun]'s cell!"))
return
else if(istype(O, /obj/item/soil_sack))
var/obj/item/soil_sack/oursoil = O
if(plant_status != HYDROTRAY_NO_PLANT)
balloon_alert(user, "remove the plants first!")
return
if(!isnull(current_soil))
balloon_alert(user, "tray is full")
return
balloon_alert(user, "filling the tray...")
if(!do_after(user, 2 SECONDS, src))
return
if(!oursoil.stored_soil)
balloon_alert(user, "sack is empty!")
return
current_soil = new oursoil.stored_soil(src)
RefreshParts()
tray_flags = current_soil.tray_flags
current_soil_overlay = "[current_soil.icon_state]_tray"
name = "botanic tray"
desc = "A basin used to grow plants in. Filled with [current_soil.name]."
qdel(oursoil)
update_appearance()
return
else
return ..()
@@ -1105,6 +1166,10 @@
update_use_power(NO_POWER_USE)
return CLICK_ACTION_BLOCKING
if(!can_self_sustain)
balloon_alert(user, "no self-sustain mode!")
return CLICK_ACTION_BLOCKING
set_self_sustaining(!self_sustaining)
to_chat(user, span_notice("You [self_sustaining ? "activate" : "deactivated"] [src]'s autogrow function[self_sustaining ? ", maintaining the tray's health while using high amounts of power" : ""]."))
return CLICK_ACTION_SUCCESS
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 52 KiB