diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 9de921e10fe..840a759cea7 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -20161,8 +20161,8 @@ }, /area/station/science/lobby) "hqH" = ( -/obj/structure/reagent_dispensers/watertank, /obj/item/reagent_containers/cup/watering_can/wood, +/obj/structure/table, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) "hqM" = ( @@ -32189,6 +32189,10 @@ /obj/item/camera, /turf/open/floor/iron, /area/station/security/prison/workout) +"lhd" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/station/security/prison/garden) "lhi" = ( /obj/machinery/airalarm/directional/north, /obj/machinery/button/door/directional/north{ @@ -33927,7 +33931,6 @@ "lGO" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/sink/directional/west, /turf/open/floor/iron, /area/station/security/prison/garden) "lGT" = ( @@ -54428,6 +54431,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/grimy, /area/station/commons/vacant_room/office) +"sJf" = ( +/obj/structure/water_source/puddle, +/turf/open/misc/asteroid, +/area/station/maintenance/starboard/greater) "sJg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, /obj/machinery/door/airlock/command{ @@ -86198,7 +86205,7 @@ xjz xjz xjz xjz -dDB +xjz dDB blb blb @@ -86454,7 +86461,7 @@ hJC aHJ wmy tBm -xjz +tBm xjz blb blb @@ -86711,7 +86718,7 @@ aWt sis sis sis -tBm +lhd xjz blb dDB @@ -129058,7 +129065,7 @@ ylD hqH vzv brz -cgM +sJf ylD wyj dYR diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 07982e7dabc..8959abab558 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -10390,14 +10390,12 @@ /area/station/command/corporate_showroom) "czg" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/item/plant_analyzer, /obj/machinery/camera/directional/east{ c_tag = "Permabrig - Garden"; network = list("ss13","prison") }, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "czi" = ( /obj/effect/decal/cleanable/dirt, @@ -19613,10 +19611,8 @@ /area/station/engineering/atmos) "eQx" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/item/shovel/spade, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "eQB" = ( /obj/machinery/door/airlock/public/glass{ @@ -27561,10 +27557,8 @@ "gLT" = ( /obj/machinery/hydroponics/soil, /obj/item/cultivator, -/obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/electric_shock/directional/west, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "gMd" = ( /obj/structure/window/reinforced/spawner/directional/west, @@ -30877,23 +30871,10 @@ /turf/open/floor/iron, /area/station/commons/vacant_room/commissary) "hHi" = ( -/obj/structure/closet/crate/hydroponics, -/obj/item/paper/guides/jobs/hydroponics, -/obj/item/seeds/onion, -/obj/item/seeds/garlic, -/obj/item/seeds/potato, -/obj/item/seeds/tomato, -/obj/item/seeds/carrot, -/obj/item/seeds/grass, -/obj/item/seeds/ambrosia, -/obj/item/seeds/wheat, -/obj/item/seeds/pumpkin, -/obj/effect/spawner/random/contraband/prison, /obj/structure/window/spawner/directional/south, -/obj/effect/decal/cleanable/dirt, -/obj/item/seeds/tower, /obj/structure/sign/poster/official/random/directional/north, -/turf/open/floor/iron, +/obj/structure/water_source/puddle, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "hHo" = ( /obj/structure/disposalpipe/trunk, @@ -59532,13 +59513,23 @@ /area/station/service/chapel) "oWp" = ( /obj/structure/window/spawner/directional/south, -/obj/structure/sink/directional/south, -/obj/structure/reagent_dispensers/watertank, -/obj/item/reagent_containers/cup/watering_can, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb, /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/closet/crate/hydroponics, +/obj/item/seeds/tower, +/obj/effect/spawner/random/contraband/prison, +/obj/item/seeds/pumpkin, +/obj/item/seeds/wheat, +/obj/item/seeds/ambrosia, +/obj/item/seeds/grass, +/obj/item/seeds/carrot, +/obj/item/seeds/tomato, +/obj/item/seeds/potato, +/obj/item/seeds/garlic, +/obj/item/seeds/onion, +/obj/item/paper/guides/jobs/hydroponics, /turf/open/floor/iron, /area/station/security/prison/garden) "oWt" = ( @@ -78609,11 +78600,9 @@ /area/station/command/corporate_showroom) "tGW" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/item/radio/intercom/directional/east, -/obj/effect/mapping_helpers/burnt_floor, /obj/machinery/light/small/directional/east, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "tHc" = ( /obj/structure/table/wood/fancy, @@ -79874,10 +79863,8 @@ dir = 1 }, /obj/machinery/firealarm/directional/west, -/obj/effect/turf_decal/tile/green{ - dir = 8 - }, -/turf/open/floor/iron, +/obj/structure/water_source/puddle, +/turf/open/misc/sandy_dirt, /area/station/service/hydroponics/garden) "tXe" = ( /obj/effect/turf_decal/loading_area/red{ @@ -84678,6 +84665,7 @@ /obj/machinery/hydroponics/constructable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/tile/green, +/obj/item/reagent_containers/cup/watering_can, /turf/open/floor/iron, /area/station/security/prison/garden) "veD" = ( @@ -90301,10 +90289,8 @@ "wAt" = ( /obj/machinery/hydroponics/soil, /obj/item/cultivator, -/obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm/directional/east, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "wAz" = ( /obj/structure/table/wood, @@ -91828,11 +91814,9 @@ /area/space) "wVy" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/west, -/obj/effect/mapping_helpers/burnt_floor, /obj/structure/sign/poster/contraband/ambrosia_vulgaris/directional/west, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "wVJ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 3737277c465..71b333277b0 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -9036,6 +9036,9 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 4 }, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "cBG" = ( @@ -43794,6 +43797,7 @@ /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/south, /obj/item/radio/intercom/directional/west, +/obj/structure/reagent_dispensers/watertank, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "nhT" = ( @@ -49552,6 +49556,10 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/maintenance/aft/lesser) +"oNW" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/station/security/prison/garden) "oNX" = ( /obj/machinery/airalarm/directional/west, /turf/open/floor/iron/dark, @@ -52423,6 +52431,9 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, /turf/open/floor/iron/dark, /area/station/service/hydroponics/garden) "pGJ" = ( @@ -54284,10 +54295,10 @@ /turf/open/floor/iron, /area/station/command/heads_quarters/qm) "qiT" = ( -/obj/structure/reagent_dispensers/watertank, /obj/effect/turf_decal/tile/green/anticorner/contrasted{ dir = 4 }, +/obj/item/kirbyplants/random, /turf/open/floor/iron/dark, /area/station/service/hydroponics/garden) "qjb" = ( @@ -73913,7 +73924,6 @@ /turf/open/floor/iron/large, /area/station/command/heads_quarters/ce) "wcz" = ( -/obj/structure/sink/directional/south, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/tile/green/half/contrasted{ dir = 1 @@ -77700,15 +77710,12 @@ /turf/open/floor/carpet/blue, /area/station/hallway/secondary/entry) "xhg" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, /obj/machinery/camera/directional/east{ c_tag = "Garden" }, -/obj/item/kirbyplants/random, /obj/machinery/status_display/ai/directional/east, -/turf/open/floor/iron/dark, +/obj/structure/water_source/puddle, +/turf/open/floor/grass, /area/station/service/hydroponics/garden) "xhk" = ( /turf/open/floor/iron/dark, @@ -167765,7 +167772,7 @@ jlF jNf dpC cGQ -whr +oNW nmr hVY gjq @@ -168280,7 +168287,7 @@ jNf qIo tau dWK -ozX +whr hVY gjq gjq diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index efec99c47fc..a719ae4c671 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -15537,13 +15537,10 @@ /turf/open/floor/plating/airless, /area/station/solars/port/fore) "fzr" = ( -/obj/structure/table, -/obj/effect/turf_decal/stripes/line, -/obj/effect/spawner/random/food_or_drink/seed{ - spawn_all_loot = 1; - spawn_random_offset = 1 - }, -/turf/open/floor/iron, +/obj/structure/window/spawner/directional/south, +/obj/structure/window/spawner/directional/west, +/obj/structure/water_source/puddle, +/turf/open/floor/grass, /area/station/service/hydroponics/garden) "fzE" = ( /obj/structure/sign/warning/vacuum/external/directional/north, @@ -38988,6 +38985,7 @@ /obj/effect/turf_decal/trimline/green/filled/line{ dir = 9 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison/garden) "nNw" = ( @@ -39526,6 +39524,10 @@ /obj/structure/table, /obj/structure/extinguisher_cabinet/directional/west, /obj/effect/turf_decal/stripes/line, +/obj/effect/spawner/random/food_or_drink/seed{ + spawn_all_loot = 1; + spawn_random_offset = 1 + }, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "nYU" = ( @@ -40407,7 +40409,6 @@ /obj/machinery/hydroponics/soil, /obj/item/cultivator, /obj/effect/decal/cleanable/dirt, -/obj/structure/cable, /turf/open/floor/grass, /area/station/security/prison/garden) "opG" = ( @@ -50757,8 +50758,6 @@ /turf/open/floor/iron/white, /area/station/medical/virology) "rVb" = ( -/obj/structure/sink/directional/west, -/obj/item/reagent_containers/cup/watering_can, /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 }, @@ -51191,7 +51190,6 @@ "sbX" = ( /obj/machinery/hydroponics/soil, /obj/effect/decal/cleanable/dirt, -/obj/structure/cable, /obj/item/plant_analyzer, /turf/open/floor/grass, /area/station/security/prison/garden) @@ -55372,6 +55370,7 @@ /obj/effect/turf_decal/trimline/green/filled/line{ dir = 8 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison/garden) "tCF" = ( @@ -63868,6 +63867,12 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/iron, /area/station/science/robotics/mechbay) +"wsG" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/water_source/puddle, +/obj/item/reagent_containers/cup/watering_can, +/turf/open/floor/grass, +/area/station/security/prison/garden) "wsI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -65136,7 +65141,6 @@ /turf/open/floor/iron/white, /area/station/science/robotics/lab) "wRF" = ( -/obj/structure/window/spawner/directional/west, /obj/structure/flora/rock/pile, /turf/open/floor/grass, /area/station/service/hydroponics/garden) @@ -87401,7 +87405,7 @@ aaa lMJ aaa aaa -aaa +cmB cmB cmB cmB @@ -87659,7 +87663,7 @@ lMJ aaa aaa cmB -cmB +wsG opF sbX jTi diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 4e9080ef499..b4168c7d54d 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -18356,6 +18356,18 @@ /obj/machinery/duct, /turf/open/floor/iron/dark, /area/station/hallway/floor3/fore) +"eJy" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/turf/open/floor/iron/dark/side{ + dir = 8 + }, +/area/station/security/prison/garden) "eJF" = ( /obj/machinery/airalarm/directional/south, /obj/item/kirbyplants/random, @@ -54107,7 +54119,9 @@ /area/station/maintenance/floor1/starboard) "nSz" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/sink/kitchen/directional/south, +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, /turf/open/floor/iron/dark/side{ dir = 5 }, @@ -59391,6 +59405,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/pod/light, /area/station/maintenance/floor1/starboard/aft) +"ppf" = ( +/obj/effect/turf_decal/weather/sand/light, +/turf/closed/wall/r_wall, +/area/station/security/execution/education) "ppi" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table, @@ -64263,15 +64281,9 @@ /turf/open/floor/iron/dark, /area/station/command/teleporter) "qzQ" = ( -/obj/effect/turf_decal/weather/dirt{ - dir = 8 - }, -/obj/item/reagent_containers/cup/watering_can, -/obj/effect/turf_decal/tile/dark_blue, /obj/machinery/newscaster/directional/north, -/turf/open/floor/iron/dark/side{ - dir = 9 - }, +/obj/structure/water_source/puddle, +/turf/open/misc/dirt/jungle, /area/station/security/prison/garden) "qzX" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, @@ -68264,6 +68276,7 @@ /obj/effect/mapping_helpers/broken_floor, /obj/effect/turf_decal/tile/dark_blue/opposingcorners, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/item/reagent_containers/cup/watering_can, /turf/open/floor/iron/dark/corner{ dir = 4 }, @@ -329837,7 +329850,7 @@ oyh oyh oyh fkA -fkA +ppf wmD fkA kUZ @@ -331381,7 +331394,7 @@ oyh wMF wMF qzQ -pfL +eJy pfL pfL yfr diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index b4d767bd2dd..469e5ec80fb 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -8387,6 +8387,10 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/engineering/atmos) +"bRl" = ( +/obj/structure/water_source/puddle, +/turf/open/misc/asteroid, +/area/station/security/prison/workout) "bRE" = ( /obj/structure/lattice/catwalk, /turf/open/floor/plating/airless, @@ -10804,14 +10808,13 @@ /turf/open/floor/iron, /area/station/security/brig) "cGm" = ( -/obj/effect/turf_decal/bot, -/obj/structure/reagent_dispensers/watertank, /obj/machinery/airalarm/directional/east, /obj/effect/turf_decal/trimline/neutral/line, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 4 }, -/turf/open/floor/iron, +/obj/structure/water_source/puddle, +/turf/open/floor/grass, /area/station/service/hydroponics/garden) "cGy" = ( /obj/structure/chair/stool/directional/north, @@ -46719,7 +46722,6 @@ /area/station/hallway/secondary/exit) "pzw" = ( /obj/effect/turf_decal/bot, -/obj/structure/reagent_dispensers/watertank, /obj/machinery/power/apc/auto_name/directional/east, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 4 @@ -47444,10 +47446,10 @@ /turf/open/floor/iron/white, /area/station/science/lower) "pMz" = ( -/obj/structure/table/glass, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 5 }, +/obj/structure/reagent_dispensers/watertank, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "pMG" = ( @@ -88126,7 +88128,7 @@ abM aal lPV kPC -lFk +bRl lFk lFk mAB diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 5673421142a..0c4222ee5e7 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -17276,6 +17276,7 @@ /area/station/science/research) "ggl" = ( /obj/machinery/camera/autoname/directional/west, +/obj/structure/water_source/puddle, /turf/open/floor/grass, /area/station/service/hydroponics/garden) "ggu" = ( @@ -39047,6 +39048,10 @@ /obj/effect/turf_decal/tile/dark_blue, /turf/open/floor/iron, /area/station/command/bridge) +"nPw" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/station/security/prison/garden) "nPM" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 4 @@ -82449,7 +82454,7 @@ iUF dUc xrb xrb -dEG +nPw dEG iqf cKn diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index 8f7483d9416..2fbf99446ab 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -46,3 +46,9 @@ /// From /obj/item/fish_analyzer/proc/analyze_status: (fish, user) #define COMSIG_FISH_ANALYZER_ANALYZE_STATUS "fish_analyzer_analyze_status" + +/// From /datum/component/fish_growth/on_fish_life: (seconds_per_tick) +#define COMSIG_FISH_BEFORE_GROWING "fish_before_growing" + #define COMPONENT_DONT_GROW (1 << 0) +/// From /datum/component/fish_growth/finish_growing: (result) +#define COMSIG_FISH_FINISH_GROWING "fish_finish_growing" diff --git a/code/datums/components/fish_growth.dm b/code/datums/components/fish_growth.dm new file mode 100644 index 00000000000..bc7c8a9869e --- /dev/null +++ b/code/datums/components/fish_growth.dm @@ -0,0 +1,57 @@ +///A simple component that manages raising things from aquarium fish. +/datum/component/fish_growth + dupe_mode = COMPONENT_DUPE_SELECTIVE + ///the type of the movable that's spawned when the fish grows up. + var/result_type + ///The progress, from 0 to 100 + var/maturation + ///How much maturation is gained per tick + var/growth_rate + ///Is the result moved on the nearest drop location? + var/use_drop_loc + ///Is the parent deleted once the result is spawned? + var/del_on_grow + +/datum/component/fish_growth/Initialize(result_type, growth_rate, use_drop_loc = TRUE, del_on_grow = TRUE) + . = ..() + if(!isfish(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_FISH_LIFE, PROC_REF(on_fish_life)) + src.result_type = result_type + src.growth_rate = growth_rate + src.use_drop_loc = use_drop_loc + src.del_on_grow = del_on_grow + +/datum/component/fish_growth/CheckDupeComponent(result_type, growth_rate, use_drop_loc = TRUE, del_on_grow = TRUE) + if(result_type == src.result_type) + src.growth_rate = growth_rate + return TRUE //copy the growth rate and kill the new component + return FALSE + +/datum/component/fish_growth/proc/on_fish_life(obj/item/fish/source, seconds_per_tick) + SIGNAL_HANDLER + if(SEND_SIGNAL(source, COMSIG_FISH_BEFORE_GROWING, seconds_per_tick) & COMPONENT_DONT_GROW) + return + maturation += growth_rate * seconds_per_tick + if(maturation >= 100) + finish_growing(source) + +/datum/component/fish_growth/proc/finish_growing(obj/item/fish/source) + var/atom/location = use_drop_loc ? source.drop_location() : source.loc + var/atom/movable/result = new result_type (location) + if(location != source.loc) + result.visible_message(span_boldnotice("\A [result] jumps out of [source.loc]!")) + playsound(result, 'sound/effects/fish_splash.ogg', 60) + if(isbasicmob(result)) + for(var/trait_type in source.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + trait.apply_to_mob(result) + + addtimer(CALLBACK(result, TYPE_PROC_REF(/mob/living/basic, hop_on_nearby_turf)), 0.1 SECONDS) + + SEND_SIGNAL(source, COMSIG_FISH_FINISH_GROWING, result) + + if(del_on_grow) + qdel(parent) + else + maturation = 0 diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm index b7ad26a65ea..e06cd8c6771 100644 --- a/code/game/objects/structures/water_structures/water_source.dm +++ b/code/game/objects/structures/water_structures/water_source.dm @@ -137,6 +137,15 @@ base_icon_state = "puddle" resistance_flags = UNACIDABLE +/obj/structure/water_source/puddle/Initialize(mapload) + . = ..() + register_context() + +/obj/structure/water_source/puddle/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_RMB] = "Scoop Tadpoles" + //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/structure/water_source/puddle/attack_hand(mob/user, list/modifiers) icon_state = "[base_icon_state]-splash" @@ -147,3 +156,20 @@ icon_state = "[base_icon_state]-splash" . = ..() icon_state = base_icon_state + +/obj/structure/water_source/puddle/attack_hand_secondary(mob/living/carbon/human/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(DOING_INTERACTION_WITH_TARGET(user, src)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + icon_state = "[base_icon_state]-splash" + balloon_alert(user, "scooping tadpoles...") + if(do_after(user, src, 5 SECONDS)) + playsound(loc, 'sound/effects/slosh.ogg', 15, TRUE) + balloon_alert(user, "got a tadpole") + var/obj/item/fish/tadpole/tadpole = new(loc) + tadpole.randomize_size_and_weight() + user.put_in_hands(tadpole) + icon_state = base_icon_state + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/code/modules/cargo/exports/fish.dm b/code/modules/cargo/exports/fish.dm index 3860dff904b..9c34fd3afca 100644 --- a/code/modules/cargo/exports/fish.dm +++ b/code/modules/cargo/exports/fish.dm @@ -6,8 +6,4 @@ /datum/export/fish/get_cost(obj/item/fish/fish, apply_elastic) var/elastic_cost = ..() var/elastic_percent = elastic_cost / init_cost - var/size_weight_exponentation = (fish.size * fish.weight * 0.01)^0.85 - var/new_cost = elastic_cost + size_weight_exponentation * elastic_percent - if(HAS_TRAIT(fish, TRAIT_FISH_FROM_CASE)) //Avoid printing money by simply ordering fish and sending it back. - new_cost *= 0.05 - return round(new_cost) + return fish.get_export_price(elastic_cost, elastic_percent) diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 081f7940290..19a20a40a81 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -627,6 +627,14 @@ fish_zap_flags |= (ZAP_GENERATES_POWER | ZAP_MOB_STUN) tesla_zap(source = get_turf(src), zap_range = fish_zap_range, power = fish_zap_power, cutoff = 1 MEGA JOULES, zap_flags = fish_zap_flags) +///Returns the price of this fish, for the fish export. +/obj/item/fish/proc/get_export_price(price, percent) + var/size_weight_exponentation = (size * weight * 0.01)^0.85 + var/calculated_price = price + size_weight_exponentation * percent + if(HAS_TRAIT(src, TRAIT_FISH_FROM_CASE)) //Avoid printing money by simply ordering fish and sending it back. + calculated_price *= 0.05 + return round(calculated_price) + /// Returns random fish, using random_case_rarity probabilities. /proc/random_fish_type(required_fluid) var/static/probability_table diff --git a/code/modules/fishing/fish/fish_types.dm b/code/modules/fishing/fish/fish_types.dm index 11f9ab317d2..ce9f36f0553 100644 --- a/code/modules/fishing/fish/fish_types.dm +++ b/code/modules/fishing/fish/fish_types.dm @@ -81,6 +81,55 @@ required_temperature_max = MIN_AQUARIUM_TEMP+30 beauty = FISH_BEAUTY_GOOD +/obj/item/fish/tadpole + name = "tadpole" + desc = "The larval spawn of an amphibian. A very minuscle, round creature with a long tail it uses to swim around." + icon_state = "tadpole" + dedicated_in_aquarium_icon_state = "tadpole small" + average_size = 3 + average_weight = 10 + sprite_width = 3 + sprite_height = 1 + health = 50 + feeding_frequency = 1.5 MINUTES + required_temperature_min = MIN_AQUARIUM_TEMP+15 + required_temperature_max = MIN_AQUARIUM_TEMP+20 + fillet_type = null + fish_traits = list(/datum/fish_trait/no_mating) //They grow into frogs and that's it. + beauty = FISH_BEAUTY_NULL + random_case_rarity = FISH_RARITY_NOPE //Why would you want generic frog tadpoles you get from ponds inside fish cases? + /// Once dead, tadpoles disappear after a dozen seconds, since you can get infinite tadpoles. + var/del_timerid + +/obj/item/fish/tadpole/Initialize(mapload, apply_qualities = TRUE) + . = ..() + AddComponent(/datum/component/fish_growth, /mob/living/basic/frog, 100 / rand(2.5, 3 MINUTES) * 10) + RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks)) + RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth)) + +/obj/item/fish/tadpole/set_status(new_status) + . = ..() + if(status == FISH_DEAD) + del_timerid = QDEL_IN_STOPPABLE(src, 12 SECONDS) + else + deltimer(del_timerid) + +/obj/item/fish/tadpole/proc/growth_checks(datum/source, seconds_per_tick) + SIGNAL_HANDLER + var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency) + if(hunger >= 0.7) //too hungry to grow + return COMPONENT_DONT_GROW + var/obj/structure/aquarium/aquarium = loc + if(!aquarium.allow_breeding) //the aquarium has breeding disabled + return COMPONENT_DONT_GROW + +/obj/item/fish/tadpole/proc/on_growth(datum/source, mob/living/basic/frog/result) + SIGNAL_HANDLER + playsound(result, result.attack_sound, 50, TRUE) // reeeeeeeeeeeeeee... + +/obj/item/fish/tadpole/get_export_price(price, percent) + return 2 //two credits. Tadpoles aren't really that valueable. + // Saltwater fish below /obj/item/fish/clownfish @@ -270,8 +319,6 @@ evolution_types = list(/datum/fish_evolution/ice_chrab) compatible_types = list(/obj/item/fish/chasm_crab/ice) beauty = FISH_BEAUTY_GOOD - ///Chasm crabs mature into juveline lobstrositiess with time. This is the progess from 0 to 100 - var/maturation = 0 ///This value represents how much the crab needs aren't being met. Higher values translate to a more likely hostile lobstrosity. var/anger = 0 ///The lobstrosity type this matures into @@ -279,6 +326,11 @@ ///at which rate the crab gains maturation var/growth_rate = 100 / (10 MINUTES) * 10 +/obj/item/fish/chasm_crab/Initialize(mapload, apply_qualities = TRUE) + . = ..() + RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks)) + RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth)) + ///A chasm crab growth speed is determined by its initial weight and size, ergo bigger crabs for faster lobstrosities /obj/item/fish/chasm_crab/update_size_and_weight(new_size = average_size, new_weight = average_weight) . = ..() @@ -298,62 +350,41 @@ else if(weight >= 1500) multiplier += min(0.1 * round((weight - 1000) / 500), 2) - growth_rate = initial(growth_rate) * multiplier + AddComponent(/datum/component/fish_growth, lob_type, initial(growth_rate) * multiplier) -/obj/item/fish/chasm_crab/process(seconds_per_tick) - . = ..() - grow_up(seconds_per_tick) - -///Slowly grow up each process tick (in an aquarium). This is its own proc so that it can be used in the unit test. -/obj/item/fish/chasm_crab/proc/grow_up(seconds_per_tick) +/obj/item/fish/chasm_crab/proc/growth_checks(datum/source, seconds_per_tick) + SIGNAL_HANDLER var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency) if(health <= initial(health) * 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow. anger += growth_rate * 2 * seconds_per_tick - return + return COMPONENT_DONT_GROW - if(!isaquarium(loc)) //can't grow outside an aquarium. + if(hunger >= 0.4) //I'm hungry and angry + anger += growth_rate * 0.6 * seconds_per_tick + + if(!isaquarium(loc)) return var/obj/structure/aquarium/aquarium = loc if(!aquarium.allow_breeding) //the aquarium has breeding disabled - return - if(hunger >= 0.4) //I'm hungry and angry - anger += growth_rate * 0.6 * seconds_per_tick + return COMPONENT_DONT_GROW if(!locate(/obj/item/aquarium_prop) in aquarium) //the aquarium deco is quite barren anger += growth_rate * 0.25 * seconds_per_tick var/fish_count = length(aquarium.get_fishes()) if(!ISINRANGE(fish_count, 3, AQUARIUM_MAX_BREEDING_POPULATION * 0.5)) //too lonely or overcrowded anger += growth_rate * 0.3 * seconds_per_tick - if(fish_count <= AQUARIUM_MAX_BREEDING_POPULATION * 0.5) //check if there's enough room to maturate. - maturation += growth_rate * seconds_per_tick + if(fish_count > AQUARIUM_MAX_BREEDING_POPULATION * 0.5) //check if there's enough room to maturate. + return COMPONENT_DONT_GROW - if(maturation >= 100) - return finish_growing() - -///spawn a juvenile lobstrosity on the aquarium turf -/obj/item/fish/chasm_crab/proc/finish_growing() - var/mob/living/basic/mining/lobstrosity/juvenile/lob = new lob_type(get_turf(src)) - for(var/trait_type in fish_traits) - var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] - trait.apply_to_mob(lob) +/obj/item/fish/chasm_crab/proc/on_growth(datum/source, mob/living/basic/mining/lobstrosity/juvenile/result) + SIGNAL_HANDLER if(!prob(anger)) - lob.AddElement(/datum/element/ai_retaliate) - qdel(lob.ai_controller) - lob.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/calm(lob) + result.AddElement(/datum/element/ai_retaliate) + qdel(result.ai_controller) + result.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/calm(result) else if(anger < 30) //not really that mad, just a bit unstable. - qdel(lob.ai_controller) - lob.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/capricious(lob) - - animate(lob, pixel_y = 18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_OUT) - animate(pixel_y = -18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_IN) - loc.visible_message(span_boldnotice("\A [lob] jumps out of [loc]!")) - playsound(loc, 'sound/effects/fish_splash.ogg', 60) - - ///make sure it moves the next tick so that it properly glides to the next location after jumping off the aquarium. - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(random_step), lob, 1, 100), 0.1 SECONDS) - - qdel(src) - return lob + qdel(result.ai_controller) + result.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/capricious(result) /obj/item/fish/chasm_crab/ice name = "arctic chrab" @@ -434,7 +465,7 @@ ) beauty = FISH_BEAUTY_DISGUSTING -/obj/item/fish/ratfish/Initialize(mapload) +/obj/item/fish/ratfish/Initialize(mapload, apply_qualities = TRUE) . = ..() //stable pop reflects the config for how many mice migrate. powerful... stable_population = CONFIG_GET(number/mice_roundstart) @@ -566,7 +597,7 @@ fish_traits = list(/datum/fish_trait/no_mating) //just to be sure, these shouldn't reproduce experisci_scannable = FALSE -/obj/item/fish/holo/Initialize(mapload) +/obj/item/fish/holo/Initialize(mapload, apply_qualities = TRUE) . = ..() var/area/station/holodeck/holo_area = get_area(src) if(!istype(holo_area)) @@ -655,7 +686,7 @@ fish_traits = list(/datum/fish_trait/antigrav, /datum/fish_trait/mixotroph) beauty = FISH_BEAUTY_GREAT -/obj/item/fish/starfish/Initialize(mapload) +/obj/item/fish/starfish/Initialize(mapload, apply_qualities = TRUE) . = ..() update_appearance(UPDATE_OVERLAYS) @@ -693,7 +724,7 @@ ///maximum bonus damage when winded up var/maximum_bonus = 25 -/obj/item/fish/lavaloop/Initialize(mapload) +/obj/item/fish/lavaloop/Initialize(mapload, apply_qualities = TRUE) . = ..() ADD_TRAIT(src, TRAIT_BYPASS_RANGED_ARMOR, INNATE_TRAIT) AddComponent(/datum/component/boomerang, throw_range, TRUE) diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 98a771a06a9..582af27c316 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -318,3 +318,9 @@ /mob/living/basic/get_body_temp_cold_damage_limit() return minimum_survivable_temperature + +/mob/living/basic/proc/hop_on_nearby_turf() + var/dir = pick(GLOB.cardinals) + Move(get_step(src, dir), dir) + animate(src, pixel_y = 18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_OUT) + animate(pixel_y = -18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_IN) diff --git a/code/modules/unit_tests/fish_unit_tests.dm b/code/modules/unit_tests/fish_unit_tests.dm index 1db534c5e07..5cb582ca969 100644 --- a/code/modules/unit_tests/fish_unit_tests.dm +++ b/code/modules/unit_tests/fish_unit_tests.dm @@ -226,10 +226,11 @@ /datum/unit_test/raise_a_chasm_crab/Run() var/obj/structure/aquarium/crab/aquarium = allocate(/obj/structure/aquarium/crab) - var/mob/living/basic/mining/lobstrosity/juvenile/lobster = aquarium.crabbie.grow_up(1) //one stands for a second - TEST_ASSERT(lobster, "The test aquarium's chasm crab didn't grow up into a lobstrosity.[aquarium.crabbie ? " The aquarium crab is still here and at about [aquarium.crabbie.maturation]% maturation" : ""]") - allocated |= lobster //make sure it's allocated and thus properly deleted when the test is over + SEND_SIGNAL(aquarium.crabbie, COMSIG_FISH_LIFE, 1) //give the fish growth component a small push. + var/mob/living/basic/mining/lobstrosity/juvenile/lobster = locate() in aquarium.loc TEST_ASSERT_EQUAL(lobster.loc, get_turf(aquarium), "The lobstrosity didn't spawn on the aquarium's turf") + TEST_ASSERT(QDELETED(aquarium.crabbie), "The test aquarium's chasm crab didn't delete itself.") + allocated |= lobster //make sure it's allocated and thus properly deleted when the test is over //While ideally impossible to have all traits because of incompatible ones, I want to be sure they don't error out. for(var/trait_type in GLOB.fish_traits) var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] diff --git a/icons/obj/aquarium/fish.dmi b/icons/obj/aquarium/fish.dmi index ab282e1681b..638c8300f30 100644 Binary files a/icons/obj/aquarium/fish.dmi and b/icons/obj/aquarium/fish.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 9304f051da0..988f95e1fb9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1101,6 +1101,7 @@ #include "code\datums\components\explode_on_attack.dm" #include "code\datums\components\faction_granter.dm" #include "code\datums\components\fertile_egg.dm" +#include "code\datums\components\fish_growth.dm" #include "code\datums\components\fishing_spot.dm" #include "code\datums\components\focused_attacker.dm" #include "code\datums\components\food_storage.dm" diff --git a/tgui/packages/tgui/interfaces/Aquarium.tsx b/tgui/packages/tgui/interfaces/Aquarium.tsx index caa0c65d75f..6f29920fc0b 100644 --- a/tgui/packages/tgui/interfaces/Aquarium.tsx +++ b/tgui/packages/tgui/interfaces/Aquarium.tsx @@ -71,10 +71,10 @@ export const Aquarium = (props) => { ))} - +