diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_hotsprings.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_hotsprings.dmm
index 967d02ffbe4..cf9130ffeb5 100644
--- a/_maps/RandomRuins/IceRuins/icemoon_underground_hotsprings.dmm
+++ b/_maps/RandomRuins/IceRuins/icemoon_underground_hotsprings.dmm
@@ -6,7 +6,7 @@
/turf/closed/mineral/random/snow,
/area/icemoon/surface/outdoors/unexplored)
"c" = (
-/turf/open/water/cursed_spring,
+/turf/open/water/hot_spring/cursed,
/area/icemoon/surface/outdoors/noteleport)
"d" = (
/obj/item/paper/crumpled{
@@ -14,6 +14,14 @@
},
/turf/open/misc/asteroid/snow/icemoon,
/area/icemoon/surface/outdoors)
+"l" = (
+/obj/structure/chair/plastic,
+/turf/open/misc/asteroid/snow/icemoon,
+/area/icemoon/surface/outdoors)
+"G" = (
+/obj/item/storage/toolbox/fishing,
+/turf/open/misc/asteroid/snow/icemoon,
+/area/icemoon/surface/outdoors)
(1,1,1) = {"
b
@@ -70,7 +78,7 @@ b
(5,1,1) = {"
b
a
-a
+G
c
c
c
@@ -83,7 +91,7 @@ b
(6,1,1) = {"
b
a
-a
+l
c
c
c
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm
index 828e7b7f743..579e6342b92 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm
@@ -62,7 +62,7 @@
/turf/open/floor/plating/lavaland_atmos,
/area/ruin/unpowered)
"l" = (
-/turf/open/water/lavaland_atmos,
+/turf/open/water/hot_spring,
/area/lavaland/surface)
"m" = (
/obj/machinery/door/airlock/survival_pod/glass,
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 1f658de43c2..68433b52785 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -358,16 +358,6 @@
/obj/machinery/light/directional/east,
/turf/open/floor/iron/white/corner,
/area/station/hallway/secondary/entry)
-"ahg" = (
-/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible,
-/obj/machinery/duct,
-/obj/effect/turf_decal/trimline/blue/filled/line{
- dir = 10
- },
-/obj/structure/cable,
-/obj/structure/sign/eyechart/directional/west,
-/turf/open/floor/iron/white,
-/area/station/medical/cryo)
"ahj" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable,
@@ -3477,16 +3467,6 @@
/obj/structure/disposalpipe/segment,
/turf/open/floor/iron/white,
/area/station/science/research)
-"bjK" = (
-/obj/structure/tank_holder/extinguisher,
-/obj/machinery/camera/directional/east{
- c_tag = "Medbay Cryogenics";
- network = list("ss13","medbay")
- },
-/obj/effect/turf_decal/tile/blue/fourcorners,
-/obj/machinery/airalarm/directional/north,
-/turf/open/floor/iron/white,
-/area/station/medical/cryo)
"bjP" = (
/turf/closed/wall/r_wall,
/area/station/ai_monitored/turret_protected/aisat/foyer)
@@ -6639,6 +6619,16 @@
/obj/effect/mapping_helpers/airlock/access/all/service/lawyer,
/turf/open/floor/wood,
/area/station/service/lawoffice)
+"ctg" = (
+/obj/item/radio/intercom/directional/east,
+/obj/effect/turf_decal/siding/white{
+ dir = 5
+ },
+/obj/structure/railing{
+ dir = 4
+ },
+/turf/open/water/no_planet_atmos,
+/area/station/service/hydroponics/garden)
"ctn" = (
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/iron,
@@ -15267,15 +15257,6 @@
/obj/structure/sign/warning/pods,
/turf/closed/wall,
/area/station/commons/locker)
-"ftQ" = (
-/obj/effect/turf_decal/siding/white{
- dir = 4
- },
-/obj/structure/railing{
- dir = 4
- },
-/turf/open/water,
-/area/station/service/hydroponics/garden)
"fuc" = (
/obj/structure/frame/machine{
anchored = 1
@@ -16048,6 +16029,12 @@
/obj/effect/mapping_helpers/airlock/access/all/medical/general,
/turf/open/floor/plating,
/area/station/maintenance/port/aft)
+"fLo" = (
+/obj/effect/turf_decal/siding/white{
+ dir = 8
+ },
+/turf/open/water/no_planet_atmos,
+/area/station/service/hydroponics/garden)
"fLq" = (
/obj/machinery/door/window/left/directional/north{
name = "Inner Pipe Access";
@@ -23814,6 +23801,14 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/dark,
/area/station/security/courtroom)
+"izs" = (
+/obj/structure/cable,
+/obj/structure/sink/directional/east,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible,
+/obj/effect/turf_decal/tile/blue/fourcorners,
+/obj/structure/mirror/directional/west,
+/turf/open/floor/iron/white,
+/area/station/medical/cryo)
"izv" = (
/obj/item/flashlight/lantern{
pixel_y = 7
@@ -25350,17 +25345,6 @@
},
/turf/open/floor/iron/white,
/area/station/medical/medbay/central)
-"iZS" = (
-/obj/machinery/atmospherics/components/unary/portables_connector/visible{
- dir = 1
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
-/obj/machinery/portable_atmospherics/canister/anesthetic_mix,
-/obj/machinery/light_switch/directional/south,
-/turf/open/floor/iron/dark,
-/area/station/medical/cryo)
"jaj" = (
/obj/structure/chair,
/obj/structure/cable,
@@ -26613,34 +26597,6 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
/turf/open/floor/iron/dark,
/area/station/science/ordnance)
-"jwp" = (
-/obj/structure/table/glass,
-/obj/machinery/power/apc/auto_name/directional/north,
-/obj/structure/cable,
-/obj/item/reagent_containers/cup/beaker/cryoxadone{
- pixel_x = -6;
- pixel_y = 10
- },
-/obj/item/reagent_containers/cup/beaker/cryoxadone{
- pixel_x = 6;
- pixel_y = 10
- },
-/obj/item/reagent_containers/cup/beaker/cryoxadone{
- pixel_x = -6;
- pixel_y = 6
- },
-/obj/item/reagent_containers/cup/beaker/cryoxadone{
- pixel_x = 6;
- pixel_y = 6
- },
-/obj/item/storage/pill_bottle/mannitol,
-/obj/item/reagent_containers/dropper{
- pixel_y = 6
- },
-/obj/effect/turf_decal/tile/blue/fourcorners,
-/obj/item/radio/intercom/directional/west,
-/turf/open/floor/iron/white,
-/area/station/medical/cryo)
"jws" = (
/obj/structure/table,
/obj/item/storage/toolbox/mechanical{
@@ -26930,6 +26886,15 @@
/obj/machinery/holopad,
/turf/open/floor/iron,
/area/station/science/robotics/lab)
+"jAE" = (
+/obj/effect/turf_decal/siding/white{
+ dir = 4
+ },
+/obj/structure/railing{
+ dir = 4
+ },
+/turf/open/water/no_planet_atmos,
+/area/station/service/hydroponics/garden)
"jAN" = (
/obj/machinery/airalarm/directional/north,
/obj/effect/turf_decal/tile/red/half/contrasted,
@@ -28342,12 +28307,6 @@
/obj/machinery/status_display/evac/directional/east,
/turf/open/floor/iron/dark,
/area/station/command/gateway)
-"jYu" = (
-/obj/effect/turf_decal/siding/white{
- dir = 9
- },
-/turf/open/water,
-/area/station/service/hydroponics/garden)
"jYv" = (
/obj/machinery/meter,
/obj/machinery/atmospherics/pipe/smart/simple/green/visible,
@@ -30517,6 +30476,16 @@
/obj/effect/turf_decal/tile/purple,
/turf/open/floor/iron,
/area/station/hallway/primary/central)
+"kMo" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible,
+/obj/machinery/duct,
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 10
+ },
+/obj/structure/cable,
+/obj/structure/sign/eyechart/directional/west,
+/turf/open/floor/iron/white,
+/area/station/medical/cryo)
"kMr" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
/obj/effect/turf_decal/siding/wood{
@@ -34545,6 +34514,34 @@
},
/turf/open/floor/iron/white,
/area/station/science/research)
+"mpV" = (
+/obj/structure/table/glass,
+/obj/machinery/power/apc/auto_name/directional/north,
+/obj/structure/cable,
+/obj/item/reagent_containers/cup/beaker/cryoxadone{
+ pixel_x = -6;
+ pixel_y = 10
+ },
+/obj/item/reagent_containers/cup/beaker/cryoxadone{
+ pixel_x = 6;
+ pixel_y = 10
+ },
+/obj/item/reagent_containers/cup/beaker/cryoxadone{
+ pixel_x = -6;
+ pixel_y = 6
+ },
+/obj/item/reagent_containers/cup/beaker/cryoxadone{
+ pixel_x = 6;
+ pixel_y = 6
+ },
+/obj/item/storage/pill_bottle/mannitol,
+/obj/item/reagent_containers/dropper{
+ pixel_y = 6
+ },
+/obj/effect/turf_decal/tile/blue/fourcorners,
+/obj/item/radio/intercom/directional/west,
+/turf/open/floor/iron/white,
+/area/station/medical/cryo)
"mqe" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -38569,6 +38566,12 @@
/obj/structure/easel,
/turf/open/floor/plating,
/area/station/maintenance/disposal)
+"nIy" = (
+/obj/effect/turf_decal/siding/white{
+ dir = 9
+ },
+/turf/open/water/no_planet_atmos,
+/area/station/service/hydroponics/garden)
"nIP" = (
/obj/structure/table/glass,
/obj/item/paper_bin{
@@ -40506,16 +40509,6 @@
},
/turf/open/floor/iron,
/area/station/science/lab)
-"otG" = (
-/obj/item/radio/intercom/directional/east,
-/obj/effect/turf_decal/siding/white{
- dir = 5
- },
-/obj/structure/railing{
- dir = 4
- },
-/turf/open/water,
-/area/station/service/hydroponics/garden)
"otI" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -43475,6 +43468,15 @@
/obj/machinery/telecomms/processor/preset_four,
/turf/open/floor/circuit/telecomms/mainframe,
/area/station/tcommsat/server)
+"pwp" = (
+/obj/effect/turf_decal/siding/white{
+ dir = 6
+ },
+/obj/structure/railing{
+ dir = 4
+ },
+/turf/open/water/no_planet_atmos,
+/area/station/service/hydroponics/garden)
"pwx" = (
/obj/structure/chair{
dir = 4
@@ -46581,14 +46583,6 @@
},
/turf/open/floor/iron,
/area/station/maintenance/port/aft)
-"qCL" = (
-/obj/structure/cable,
-/obj/structure/sink/directional/east,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible,
-/obj/effect/turf_decal/tile/blue/fourcorners,
-/obj/structure/mirror/directional/west,
-/turf/open/floor/iron/white,
-/area/station/medical/cryo)
"qCM" = (
/obj/structure/cable,
/obj/machinery/door/airlock/external{
@@ -50123,6 +50117,16 @@
/obj/machinery/firealarm/directional/west,
/turf/open/floor/plating,
/area/station/command/teleporter)
+"rKN" = (
+/obj/effect/turf_decal/siding/white{
+ dir = 10
+ },
+/obj/structure/railing{
+ dir = 8
+ },
+/obj/structure/sign/clock/directional/south,
+/turf/open/water/no_planet_atmos,
+/area/station/service/hydroponics/garden)
"rKQ" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable,
@@ -56895,6 +56899,16 @@
/obj/machinery/newscaster/directional/south,
/turf/open/floor/iron/white,
/area/station/medical/chemistry)
+"ubP" = (
+/obj/structure/tank_holder/extinguisher,
+/obj/machinery/camera/directional/east{
+ c_tag = "Medbay Cryogenics";
+ network = list("ss13","medbay")
+ },
+/obj/effect/turf_decal/tile/blue/fourcorners,
+/obj/machinery/airalarm/directional/north,
+/turf/open/floor/iron/white,
+/area/station/medical/cryo)
"ubQ" = (
/obj/effect/turf_decal/tile/neutral{
dir = 8
@@ -60404,12 +60418,6 @@
/obj/structure/cable,
/turf/open/floor/iron/dark,
/area/station/engineering/atmospherics_engine)
-"vmU" = (
-/obj/effect/turf_decal/siding/white{
- dir = 8
- },
-/turf/open/water,
-/area/station/service/hydroponics/garden)
"vmX" = (
/obj/machinery/light/directional/west,
/obj/structure/disposalpipe/segment,
@@ -61078,6 +61086,17 @@
/obj/effect/turf_decal/tile/purple/opposingcorners,
/turf/open/floor/iron,
/area/station/science/research)
+"vxW" = (
+/obj/machinery/atmospherics/components/unary/portables_connector/visible{
+ dir = 1
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/portable_atmospherics/canister/anesthetic_mix,
+/obj/machinery/light_switch/directional/south,
+/turf/open/floor/iron/dark,
+/area/station/medical/cryo)
"vye" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/rack,
@@ -66765,15 +66784,6 @@
"xww" = (
/turf/closed/wall/r_wall,
/area/station/engineering/storage/tech)
-"xwB" = (
-/obj/effect/turf_decal/siding/white{
- dir = 6
- },
-/obj/structure/railing{
- dir = 4
- },
-/turf/open/water,
-/area/station/service/hydroponics/garden)
"xwD" = (
/obj/effect/turf_decal/trimline/yellow/filled/corner,
/turf/open/floor/iron/white,
@@ -66920,16 +66930,6 @@
},
/turf/open/floor/iron/white,
/area/station/medical/chemistry)
-"xyI" = (
-/obj/effect/turf_decal/siding/white{
- dir = 10
- },
-/obj/structure/railing{
- dir = 8
- },
-/obj/structure/sign/clock/directional/south,
-/turf/open/water,
-/area/station/service/hydroponics/garden)
"xyM" = (
/obj/structure/cable,
/turf/open/floor/plating,
@@ -89498,10 +89498,10 @@ pOa
shl
cIW
pOa
-jwp
-qCL
+mpV
+izs
uIM
-ahg
+kMo
grm
sSp
wvP
@@ -90526,11 +90526,11 @@ clp
etn
ayH
pOa
-bjK
+ubP
jqQ
mbV
hEA
-iZS
+vxW
sSp
jFB
bHE
@@ -106420,9 +106420,9 @@ wRF
jzC
oCO
xUE
-jYu
-vmU
-xyI
+nIy
+fLo
+rKN
qXB
kbo
qXB
@@ -106677,9 +106677,9 @@ lbH
mie
pRM
ivb
-otG
-ftQ
-xwB
+ctg
+jAE
+pwp
qXB
psZ
qXB
diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm
index 0fa17fa43bf..973b6209da8 100644
--- a/_maps/map_files/NorthStar/north_star.dmm
+++ b/_maps/map_files/NorthStar/north_star.dmm
@@ -3330,10 +3330,9 @@
/obj/effect/turf_decal/siding/thinplating_new/dark{
dir = 1
},
-/turf/open/water/jungle{
+/turf/open/water/no_planet_atmos{
desc = "Filthy.";
- name = "untreated water";
- planetary_atmos = 0
+ name = "untreated water"
},
/area/station/maintenance/floor1/port/aft)
"aSq" = (
@@ -11244,10 +11243,9 @@
/obj/effect/turf_decal/siding/thinplating_new/dark{
dir = 5
},
-/turf/open/water/jungle{
+/turf/open/water/no_planet_atmos{
desc = "Filthy.";
- name = "untreated water";
- planetary_atmos = 0
+ name = "untreated water"
},
/area/station/maintenance/floor1/port/aft)
"cPR" = (
@@ -43703,10 +43701,9 @@
/obj/effect/turf_decal/siding/thinplating_new/dark{
dir = 4
},
-/turf/open/water/jungle{
+/turf/open/water/no_planet_atmos{
desc = "Filthy.";
- name = "untreated water";
- planetary_atmos = 0
+ name = "untreated water"
},
/area/station/maintenance/floor1/port/aft)
"loa" = (
@@ -51275,10 +51272,9 @@
desc = "This is in our water? Gross!";
name = "algae mass"
},
-/turf/open/water/jungle{
+/turf/open/water/no_planet_atmos{
desc = "Filthy.";
- name = "untreated water";
- planetary_atmos = 0
+ name = "untreated water"
},
/area/station/maintenance/floor1/port/aft)
"nhV" = (
@@ -86666,10 +86662,9 @@
/area/station/maintenance/department/engine/atmos)
"wor" = (
/obj/machinery/light/red/dim/directional/south,
-/turf/open/water/jungle{
+/turf/open/water/no_planet_atmos{
desc = "Filthy.";
- name = "untreated water";
- planetary_atmos = 0
+ name = "untreated water"
},
/area/station/maintenance/floor1/port/aft)
"wot" = (
diff --git a/_maps/templates/fishing_freshwater.dmm b/_maps/templates/fishing_freshwater.dmm
new file mode 100644
index 00000000000..8bb12fdbe54
--- /dev/null
+++ b/_maps/templates/fishing_freshwater.dmm
@@ -0,0 +1,98 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/effect/turf_decal/siding/blue/corner{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/obj/effect/turf_decal/siding/blue,
+/turf/template_noop,
+/area/template_noop)
+"c" = (
+/obj/effect/turf_decal/siding/blue/corner{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+"d" = (
+/turf/template_noop,
+/area/template_noop)
+"e" = (
+/obj/structure/chair/plastic,
+/obj/item/reagent_containers/cup/soda_cans/beer{
+ pixel_x = 12;
+ pixel_y = -5
+ },
+/obj/effect/turf_decal/siding/blue/inner_corner{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"f" = (
+/obj/effect/turf_decal/siding/blue{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"g" = (
+/obj/effect/turf_decal/siding/blue/corner{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"i" = (
+/turf/open/water/no_planet_atmos,
+/area/template_noop)
+"j" = (
+/obj/effect/turf_decal/siding/blue{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"m" = (
+/obj/effect/turf_decal/siding/blue/corner,
+/turf/template_noop,
+/area/template_noop)
+"o" = (
+/obj/effect/turf_decal/siding/blue{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+
+(1,1,1) = {"
+m
+f
+f
+f
+g
+"}
+(2,1,1) = {"
+b
+i
+i
+i
+o
+"}
+(3,1,1) = {"
+b
+i
+i
+i
+o
+"}
+(4,1,1) = {"
+a
+e
+i
+i
+o
+"}
+(5,1,1) = {"
+d
+a
+j
+j
+c
+"}
diff --git a/_maps/templates/fishing_hot_spring.dmm b/_maps/templates/fishing_hot_spring.dmm
new file mode 100644
index 00000000000..702abf8da31
--- /dev/null
+++ b/_maps/templates/fishing_hot_spring.dmm
@@ -0,0 +1,74 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/effect/turf_decal/weather/dirt,
+/turf/open/water/hot_spring,
+/area/template_noop)
+"b" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 4
+ },
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+"e" = (
+/turf/open/water/hot_spring,
+/area/template_noop)
+"o" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 4
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+"p" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+"v" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+"J" = (
+/obj/effect/turf_decal/weather/dirt,
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+"U" = (
+/obj/effect/turf_decal/weather/dirt,
+/obj/effect/turf_decal/weather/dirt{
+ dir = 4
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+"W" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/turf/open/water/hot_spring,
+/area/template_noop)
+
+(1,1,1) = {"
+p
+W
+J
+"}
+(2,1,1) = {"
+v
+e
+a
+"}
+(3,1,1) = {"
+b
+o
+U
+"}
diff --git a/_maps/templates/fishing_ice.dmm b/_maps/templates/fishing_ice.dmm
new file mode 100644
index 00000000000..bcd43fc8737
--- /dev/null
+++ b/_maps/templates/fishing_ice.dmm
@@ -0,0 +1,68 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/effect/turf_decal/siding/dark_blue{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/turf/open/misc/ice/icemoon/no_planet_atmos/holed,
+/area/template_noop)
+"d" = (
+/obj/effect/turf_decal/siding/dark_blue/corner{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"i" = (
+/obj/effect/turf_decal/siding/dark_blue/corner,
+/turf/template_noop,
+/area/template_noop)
+"o" = (
+/obj/effect/turf_decal/siding/dark_blue/corner{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"q" = (
+/obj/effect/turf_decal/siding/dark_blue,
+/obj/item/clothing/suit/caution,
+/turf/template_noop,
+/area/template_noop)
+"E" = (
+/obj/effect/turf_decal/siding/dark_blue{
+ dir = 4
+ },
+/obj/structure/chair/plastic{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"R" = (
+/obj/effect/turf_decal/siding/dark_blue{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"X" = (
+/obj/effect/turf_decal/siding/dark_blue/corner{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+
+(1,1,1) = {"
+i
+E
+d
+"}
+(2,1,1) = {"
+q
+b
+a
+"}
+(3,1,1) = {"
+o
+R
+X
+"}
diff --git a/_maps/templates/fishing_lava.dmm b/_maps/templates/fishing_lava.dmm
new file mode 100644
index 00000000000..d6e9495fd19
--- /dev/null
+++ b/_maps/templates/fishing_lava.dmm
@@ -0,0 +1,13 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/open/lava/smooth,
+/area/template_noop)
+
+(1,1,1) = {"
+a
+a
+"}
+(2,1,1) = {"
+a
+a
+"}
diff --git a/_maps/templates/fishing_plasma.dmm b/_maps/templates/fishing_plasma.dmm
new file mode 100644
index 00000000000..92ac56cebf3
--- /dev/null
+++ b/_maps/templates/fishing_plasma.dmm
@@ -0,0 +1,13 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/open/lava/plasma,
+/area/template_noop)
+
+(1,1,1) = {"
+a
+a
+"}
+(2,1,1) = {"
+a
+a
+"}
diff --git a/_maps/templates/fishing_saltwater.dmm b/_maps/templates/fishing_saltwater.dmm
new file mode 100644
index 00000000000..53ec8fe4903
--- /dev/null
+++ b/_maps/templates/fishing_saltwater.dmm
@@ -0,0 +1,107 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/effect/turf_decal/siding/yellow/corner{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/obj/effect/turf_decal/siding/yellow,
+/turf/template_noop,
+/area/template_noop)
+"c" = (
+/obj/effect/turf_decal/siding/yellow/corner{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+"d" = (
+/turf/template_noop,
+/area/template_noop)
+"e" = (
+/obj/structure/chair/plastic,
+/obj/item/reagent_containers/cup/glass/bottle/beer/light{
+ pixel_x = 13;
+ pixel_y = -2
+ },
+/obj/effect/turf_decal/siding/yellow/inner_corner{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"f" = (
+/obj/effect/turf_decal/siding/yellow{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"g" = (
+/obj/effect/turf_decal/siding/yellow/corner{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"i" = (
+/turf/open/water/beach,
+/area/template_noop)
+"j" = (
+/obj/effect/turf_decal/siding/yellow{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"m" = (
+/obj/effect/turf_decal/siding/yellow/corner{
+ dir = 2
+ },
+/turf/template_noop,
+/area/template_noop)
+"o" = (
+/obj/effect/turf_decal/siding/yellow{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+"N" = (
+/obj/item/toy/seashell{
+ pixel_x = 9;
+ pixel_y = 9
+ },
+/turf/open/water/beach,
+/area/template_noop)
+
+(1,1,1) = {"
+m
+f
+f
+f
+g
+"}
+(2,1,1) = {"
+b
+N
+i
+i
+o
+"}
+(3,1,1) = {"
+b
+i
+i
+i
+o
+"}
+(4,1,1) = {"
+a
+e
+i
+i
+o
+"}
+(5,1,1) = {"
+d
+a
+j
+j
+c
+"}
diff --git a/_maps/templates/fishing_tizira.dmm b/_maps/templates/fishing_tizira.dmm
new file mode 100644
index 00000000000..f742cf22b70
--- /dev/null
+++ b/_maps/templates/fishing_tizira.dmm
@@ -0,0 +1,98 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/effect/turf_decal/siding/green/corner{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/obj/effect/turf_decal/siding/green,
+/turf/template_noop,
+/area/template_noop)
+"c" = (
+/obj/effect/turf_decal/siding/green/corner{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+"d" = (
+/turf/template_noop,
+/area/template_noop)
+"e" = (
+/obj/structure/chair/plastic,
+/obj/effect/turf_decal/siding/green/inner_corner{
+ dir = 8
+ },
+/obj/item/food/canned/desert_snails{
+ pixel_x = 14;
+ pixel_y = -3
+ },
+/turf/template_noop,
+/area/template_noop)
+"f" = (
+/obj/effect/turf_decal/siding/green{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"g" = (
+/obj/effect/turf_decal/siding/green/corner{
+ dir = 4
+ },
+/turf/template_noop,
+/area/template_noop)
+"i" = (
+/turf/open/water/beach/tizira,
+/area/template_noop)
+"j" = (
+/obj/effect/turf_decal/siding/green{
+ dir = 8
+ },
+/turf/template_noop,
+/area/template_noop)
+"m" = (
+/obj/effect/turf_decal/siding/green/corner,
+/turf/template_noop,
+/area/template_noop)
+"o" = (
+/obj/effect/turf_decal/siding/green{
+ dir = 1
+ },
+/turf/template_noop,
+/area/template_noop)
+
+(1,1,1) = {"
+m
+f
+f
+f
+g
+"}
+(2,1,1) = {"
+b
+i
+i
+i
+o
+"}
+(3,1,1) = {"
+b
+i
+i
+i
+o
+"}
+(4,1,1) = {"
+a
+e
+i
+i
+o
+"}
+(5,1,1) = {"
+d
+a
+j
+j
+c
+"}
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 8005787676a..086851c7197 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -137,25 +137,28 @@
// NOTICE: we break from the pattern of increasing in steps of like 0.01 here
// Because TOPDOWN_LAYER is 10000 and that's enough to floating point our modifications away
-#define LOW_FLOOR_LAYER (1 + TOPDOWN_LAYER)
-#define TURF_PLATING_DECAL_LAYER (2 + TOPDOWN_LAYER)
-#define TURF_DECAL_LAYER (3 + TOPDOWN_LAYER) //Makes turf decals appear in DM how they will look inworld.
-#define CULT_OVERLAY_LAYER (4 + TOPDOWN_LAYER)
-#define MID_TURF_LAYER (5 + TOPDOWN_LAYER)
-#define HIGH_TURF_LAYER (6 + TOPDOWN_LAYER)
-#define LATTICE_LAYER (7 + TOPDOWN_LAYER)
-#define DISPOSAL_PIPE_LAYER (8 + TOPDOWN_LAYER)
-#define WIRE_LAYER (9 + TOPDOWN_LAYER)
-#define GLASS_FLOOR_LAYER (10 + TOPDOWN_LAYER)
-#define TRAM_RAIL_LAYER (11 + TOPDOWN_LAYER)
-#define ABOVE_OPEN_TURF_LAYER (12 + TOPDOWN_LAYER)
+
+//lower than LOW_FLOOR_LAYER, for turfs with stuff on the edge that should be covered by other turfs
+#define LOWER_FLOOR_LAYER (1 + TOPDOWN_LAYER)
+#define LOW_FLOOR_LAYER (2 + TOPDOWN_LAYER)
+#define TURF_PLATING_DECAL_LAYER (3 + TOPDOWN_LAYER)
+#define TURF_DECAL_LAYER (4 + TOPDOWN_LAYER) //Makes turf decals appear in DM how they will look inworld.
+#define CULT_OVERLAY_LAYER (5 + TOPDOWN_LAYER)
+#define MID_TURF_LAYER (6 + TOPDOWN_LAYER)
+#define HIGH_TURF_LAYER (7 + TOPDOWN_LAYER)
+#define LATTICE_LAYER (8 + TOPDOWN_LAYER)
+#define DISPOSAL_PIPE_LAYER (9 + TOPDOWN_LAYER)
+#define WIRE_LAYER (10 + TOPDOWN_LAYER)
+#define GLASS_FLOOR_LAYER (11 + TOPDOWN_LAYER)
+#define TRAM_RAIL_LAYER (12 + TOPDOWN_LAYER)
+#define ABOVE_OPEN_TURF_LAYER (13 + TOPDOWN_LAYER)
///catwalk overlay of /turf/open/floor/plating/catwalk_floor
-#define CATWALK_LAYER (13 + TOPDOWN_LAYER)
-#define LOWER_RUNE_LAYER (14 + TOPDOWN_LAYER)
-#define RUNE_LAYER (15 + TOPDOWN_LAYER)
+#define CATWALK_LAYER (14 + TOPDOWN_LAYER)
+#define LOWER_RUNE_LAYER (15 + TOPDOWN_LAYER)
+#define RUNE_LAYER (16 + TOPDOWN_LAYER)
/// [GAME_CLEAN_LAYER] but for floors.
/// Basically any layer below this (numerically) is "on" a floor for the purposes of washing
-#define FLOOR_CLEAN_LAYER (20 + TOPDOWN_LAYER)
+#define FLOOR_CLEAN_LAYER (21 + TOPDOWN_LAYER)
//WALL_PLANE layers
#define BELOW_CLOSED_TURF_LAYER 2.053
diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
index 33147916f4e..0d22eaf8e32 100644
--- a/code/__DEFINES/maps.dm
+++ b/code/__DEFINES/maps.dm
@@ -195,9 +195,17 @@ Always compile, always use that verb, and always make sure that it works for wha
#define SHELTER_DEPLOY_BAD_AREA "bad area"
/// Shelter spot has anchored objects that restrict deployment
#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects"
+/// Sheter spot has banned objects that restrict deployment
+#define SHELTER_DEPLOY_BANNED_OBJECTS "banned objects"
/// Shelter spot is out of bounds from the maps x/y coordinates
#define SHELTER_DEPLOY_OUTSIDE_MAP "outside map"
+//Flags for survival capsules to ignore some deploy checks
+///Ignore anchored, dense objects in the area
+#define CAPSULE_IGNORE_ANCHORED_OBJECTS (1<<0)
+///Ignore banned objects in the area
+#define CAPSULE_IGNORE_BANNED_OBJECTS (1<<1)
+
/// A map key that corresponds to being one exclusively for Space.
#define SPACE_KEY "space"
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index fe28ec63969..b596ad3bc36 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -210,6 +210,7 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items
/obj/item/storage/box/clown = 1,
/obj/item/weaponcrafting/receiver = 1,
/obj/item/book/granter/crafting_recipe/death_sandwich = 1,
+ /obj/item/survivalcapsule/fishing = 1,
) = 8,
list(//medical and chemicals
diff --git a/code/datums/components/fish_growth.dm b/code/datums/components/fish_growth.dm
index 7f1e411ed3a..f4c835045e8 100644
--- a/code/datums/components/fish_growth.dm
+++ b/code/datums/components/fish_growth.dm
@@ -56,7 +56,7 @@
var/growth = growth_rate * deciseconds_elapsed
if(HAS_TRAIT(source, TRAIT_FISH_QUICK_GROWTH))
growth *= 2
- if(SEND_SIGNAL(source, COMSIG_FISH_BEFORE_GROWING, seconds_per_tick, growth) & COMPONENT_DONT_GROW)
+ if(SEND_SIGNAL(source, COMSIG_FISH_BEFORE_GROWING, seconds_per_tick, growth, result_type) & COMPONENT_DONT_GROW)
return
maturation += growth
if(maturation >= 100)
@@ -87,7 +87,7 @@
addtimer(CALLBACK(result, TYPE_PROC_REF(/mob/living/basic, hop_on_nearby_turf)), 0.1 SECONDS)
if(is_evo || location == source.loc)
- var/message_verb = del_on_grow ? "grows into" : "generates"
+ var/message_verb = del_on_grow ? "grows into" : "lays"
location.visible_message(span_notice("[source] [message_verb] \a [result]."), vision_distance = 3)
if(inherit_name && HAS_TRAIT(source, TRAIT_WAS_RENAMED))
diff --git a/code/datums/mood_events/needs_events.dm b/code/datums/mood_events/needs_events.dm
index 93a8f186da6..434110ff27c 100644
--- a/code/datums/mood_events/needs_events.dm
+++ b/code/datums/mood_events/needs_events.dm
@@ -81,6 +81,24 @@
mood_change = -2
timeout = 3 MINUTES
+/datum/mood_event/hot_spring
+ description = "It's so relaxing to bathe in steamy water..."
+ mood_change = 5
+
+/datum/mood_event/hot_spring_hater
+ description = "No, no, no, no, I don't want to take a bath!"
+ mood_change = -2
+
+/datum/mood_event/hot_spring_left
+ description = "That was an enjoyable bath."
+ mood_change = 4
+ timeout = 4 MINUTES
+
+/datum/mood_event/hot_spring_hater_left
+ description = "I hate baths! And I hate how cold it's once you step out of it!"
+ mood_change = -3
+ timeout = 2 MINUTES
+
/datum/mood_event/fresh_laundry
description = "There's nothing like the feeling of a freshly laundered jumpsuit."
mood_change = 2
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index 0056c55a7f6..d7bc350ffbd 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -610,40 +610,71 @@
SIGNAL_HANDLER
qdel(src)
-/atom/movable/screen/alert/status_effect/shower_regen
+/datum/status_effect/washing_regen
+ id = "shower_regen"
+ duration = -1
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /atom/movable/screen/alert/status_effect/washing_regen
+ ///The screen alert shown if you hate water
+ var/hater_alert = /atom/movable/screen/alert/status_effect/washing_regen/hater
+ /// How much stamina we regain from washing
+ var/stamina_heal_per_tick = -4
+ /// How much brute, tox and fie damage we heal from this
+ var/heal_per_tick = 0
+
+/datum/status_effect/washing_regen/on_apply()
+ . = ..()
+ if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
+ alert_type = hater_alert
+
+/datum/status_effect/washing_regen/tick(seconds_between_ticks)
+ . = ..()
+ var/water_adaptation = HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION)
+ var/water_hater = HAS_TRAIT(owner, TRAIT_WATER_HATER)
+ var/stam_recovery = (water_hater && !water_adaptation ? -stamina_heal_per_tick : stamina_heal_per_tick) * seconds_between_ticks
+ var/recovery = heal_per_tick
+ if(water_adaptation)
+ recovery -= 1
+ stam_recovery *= 1.5
+ else if(water_hater)
+ recovery *= 0
+ recovery *= seconds_between_ticks
+
+ var/healed = 0
+ if(recovery) //very mild healing for those with the water adaptation trait (fish infusion)
+ healed += owner.adjustOxyLoss(recovery * (water_adaptation ? 1.5 : 1), updating_health = FALSE, required_biotype = MOB_ORGANIC)
+ healed += owner.adjustFireLoss(recovery, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
+ healed += owner.adjustToxLoss(recovery, updating_health = FALSE, required_biotype = MOB_ORGANIC)
+ healed += owner.adjustBruteLoss(recovery, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
+ healed += owner.adjustStaminaLoss(stam_recovery, updating_stamina = FALSE)
+ if(healed)
+ owner.updatehealth()
+
+/atom/movable/screen/alert/status_effect/washing_regen
name = "Washing"
desc = "A good wash fills me with energy!"
icon_state = "shower_regen"
-/atom/movable/screen/alert/status_effect/shower_regen/hater
- name = "Washing"
+/atom/movable/screen/alert/status_effect/washing_regen/hater
desc = "Waaater... Fuck this WATER!!"
icon_state = "shower_regen_catgirl"
-/datum/status_effect/shower_regen
- id = "shower_regen"
- duration = -1
- status_type = STATUS_EFFECT_UNIQUE
- alert_type = /atom/movable/screen/alert/status_effect/shower_regen
- /// How many heals from washing.
- var/stamina_heal_per_tick = 4
+/datum/status_effect/washing_regen/hot_spring
+ alert_type = /atom/movable/screen/alert/status_effect/washing_regen/hotspring
+ hater_alert = /atom/movable/screen/alert/status_effect/washing_regen/hotspring/hater
+ stamina_heal_per_tick = -4.5
+ heal_per_tick = -0.4
-/datum/status_effect/shower_regen/on_apply()
+/datum/status_effect/washing_regen/hot_spring/tick(seconds_between_ticks)
. = ..()
- if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
- alert_type = /atom/movable/screen/alert/status_effect/shower_regen/hater
+ owner.adjust_bodytemperature(10 * seconds_between_ticks, 0, T0C + 45)
-/datum/status_effect/shower_regen/tick(seconds_between_ticks)
- . = ..()
- var/water_adaptation = HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION)
- var/heal_or_deal = HAS_TRAIT(owner, TRAIT_WATER_HATER) && !water_adaptation ? 1 : -1
- var/healed = 0
- if(water_adaptation) //very mild healing for those with the water adaptation trait (fish infusion)
- healed += owner.adjustOxyLoss(-1.5 * seconds_between_ticks, updating_health = FALSE, required_biotype = MOB_ORGANIC)
- healed += owner.adjustFireLoss(-1 * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
- healed += owner.adjustToxLoss(-1 * seconds_between_ticks, updating_health = FALSE, required_biotype = MOB_ORGANIC)
- healed += owner.adjustBruteLoss(-1 * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
- heal_or_deal *= 1.5
- healed += owner.adjustStaminaLoss(stamina_heal_per_tick * heal_or_deal * seconds_between_ticks, updating_stamina = FALSE)
- if(healed)
- owner.updatehealth()
+/atom/movable/screen/alert/status_effect/washing_regen/hotspring
+ name = "Hotspring"
+ desc = "Hot Springs are so relaxing..."
+ icon_state = "hotspring_regen"
+
+/atom/movable/screen/alert/status_effect/washing_regen/hotspring/hater
+ name = "Hotspring"
+ desc = "Waaater... FUCK THIS HOT WATER!!"
+ icon_state = "hotspring_regen_catgirl"
diff --git a/code/game/objects/effects/decals/turfdecal/markings.dm b/code/game/objects/effects/decals/turfdecal/markings.dm
index 0fe434d0db1..c49fdde9b18 100644
--- a/code/game/objects/effects/decals/turfdecal/markings.dm
+++ b/code/game/objects/effects/decals/turfdecal/markings.dm
@@ -231,6 +231,9 @@
/obj/effect/turf_decal/siding/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/end
icon_state = "siding_plain_end"
@@ -240,6 +243,9 @@
/obj/effect/turf_decal/siding/white/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/white/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/white/end
icon_state = "siding_plain_end"
@@ -249,6 +255,9 @@
/obj/effect/turf_decal/siding/red/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/red/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/red/end
icon_state = "siding_plain_end"
@@ -258,6 +267,9 @@
/obj/effect/turf_decal/siding/dark_red/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/dark_red/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/dark_red/end
icon_state = "siding_plain_end"
@@ -267,6 +279,9 @@
/obj/effect/turf_decal/siding/green/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/green/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/green/end
icon_state = "siding_plain_end"
@@ -276,6 +291,9 @@
/obj/effect/turf_decal/siding/dark_green/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/dark_green/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/dark_green/end
icon_state = "siding_plain_end"
@@ -285,6 +303,9 @@
/obj/effect/turf_decal/siding/blue/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/blue/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/blue/end
icon_state = "siding_plain_end"
@@ -294,6 +315,9 @@
/obj/effect/turf_decal/siding/dark_blue/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/dark_blue/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/dark_blue/end
icon_state = "siding_plain_end"
@@ -303,6 +327,9 @@
/obj/effect/turf_decal/siding/yellow/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/yellow/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/yellow/end
icon_state = "siding_plain_end"
@@ -312,6 +339,9 @@
/obj/effect/turf_decal/siding/purple/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/purple/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/purple/end
icon_state = "siding_plain_end"
@@ -321,6 +351,9 @@
/obj/effect/turf_decal/siding/brown/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/brown/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/brown/end
icon_state = "siding_plain_end"
@@ -330,6 +363,9 @@
/obj/effect/turf_decal/siding/dark/corner
icon_state = "siding_plain_corner"
+/obj/effect/turf_decal/siding/dark/inner_corner
+ icon_state = "siding_plain_corner_inner"
+
/obj/effect/turf_decal/siding/dark/end
icon_state = "siding_plain_end"
diff --git a/code/game/objects/effects/particle_holder.dm b/code/game/objects/effects/particle_holder.dm
index b5b4fa47108..00a99ea967c 100644
--- a/code/game/objects/effects/particle_holder.dm
+++ b/code/game/objects/effects/particle_holder.dm
@@ -26,7 +26,7 @@
// Mouse opacity can get set to opaque by some objects when placed into the object's contents (storage containers).
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
src.particle_flags = particle_flags
- particles = new particle_path()
+ particles = get_particle_effect(particle_path)
// /atom doesn't have vis_contents, /turf and /atom/movable do
var/atom/movable/lie_about_areas = parent
lie_about_areas.vis_contents += src
@@ -36,6 +36,9 @@
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
on_move(parent, null, NORTH)
+/obj/effect/abstract/particle_holder/proc/get_particle_effect(particle_path)
+ return new particle_path()
+
/obj/effect/abstract/particle_holder/Destroy(force)
QDEL_NULL(particles)
parent = null
@@ -67,3 +70,44 @@
/// Sets the particles position to the passed coordinates
/obj/effect/abstract/particle_holder/proc/set_particle_position(x = 0, y = 0, z = 0)
particles.position = list(x, y, z)
+
+/**
+ * A subtype of particle holder that reuses the same particles to reduce client lag
+ * when rendering certain atoms, usually found in large quantities and close together.
+ * Since it reuses the same instances, modifying an instance of particles will affect all atoms
+ * that show it, therefore procs like set_particle_position() shouldn't be used here.
+ */
+/obj/effect/abstract/particle_holder/cached
+ ///A static list meant to contain the availables instances of a particle path to use.
+ var/static/list/particles_by_type
+ /**
+ * The length of the pool of particles from which the chosen instance will be picked
+ * This provides an ever-so-lightly variety to the particles, so they don't all jarringly look EXACTLY the same
+ */
+ var/max_particle_index = 4
+
+/obj/effect/abstract/particle_holder/cached/Initialize(mapload, particle_path = /particles/smoke, particle_flags = NONE, max_particle_index)
+ src.max_particle_index = max_particle_index
+ return ..()
+
+/obj/effect/abstract/particle_holder/cached/Destroy(force)
+ particles = null
+ return ..()
+
+/obj/effect/abstract/particle_holder/cached/get_particle_effect(particle_path)
+ LAZYINITLIST(particles_by_type)
+ LAZYINITLIST(particles_by_type[particle_path])
+
+ var/list/particles_list = particles_by_type[particle_path]
+ var/index = rand(1, max_particle_index)
+ var/particles/chosen
+ if(length(particles_list) < index)
+ chosen = new particle_path()
+ particles_list += chosen
+ else
+ chosen = particles_list[index]
+
+ return chosen
+
+/obj/effect/abstract/particle_holder/cached/set_particle_position(x = 0, y = 0, z = 0)
+ CRASH("[type] doesn't support set_particle_position()")
diff --git a/code/game/objects/effects/particles/smoke.dm b/code/game/objects/effects/particles/smoke.dm
index 776c90534a9..f7c07231cf2 100644
--- a/code/game/objects/effects/particles/smoke.dm
+++ b/code/game/objects/effects/particles/smoke.dm
@@ -97,3 +97,26 @@
/particles/smoke/cyborg/heavy_damage
lifespan = 0.8 SECONDS
fade = 0.8 SECONDS
+
+/particles/hotspring_steam
+ icon = 'icons/effects/particles/smoke.dmi'
+ icon_state = list(
+ "steam_cloud_1" = 1,
+ "steam_cloud_2" = 1,
+ "steam_cloud_3" = 1,
+ "steam_cloud_4" = 1,
+ "steam_cloud_5" = 1,
+ )
+ color = "#FFFFFFAA"
+ count = 6
+ spawning = 0.5
+ lifespan = 3 SECONDS
+ fade = 1.2 SECONDS
+ fadein = 0.4 SECONDS
+ position = generator(GEN_BOX, list(-17,-15,0), list(24,15,0), NORMAL_RAND)
+ scale = generator(GEN_VECTOR, list(0.9,0.9), list(1.1,1.1), NORMAL_RAND)
+ drift = generator(GEN_SPHERE, list(-0.01,0), list(0.01,0.01), UNIFORM_RAND)
+ spin = generator(GEN_NUM, list(-3,3), NORMAL_RAND)
+ gravity = list(0.05, 0.28)
+ friction = 0.3
+ grow = 0.037
diff --git a/code/game/objects/effects/spawners/random/contraband.dm b/code/game/objects/effects/spawners/random/contraband.dm
index c32d46125c0..5b0c78659d5 100644
--- a/code/game/objects/effects/spawners/random/contraband.dm
+++ b/code/game/objects/effects/spawners/random/contraband.dm
@@ -23,6 +23,7 @@
/obj/item/storage/box/donkpockets = 10,
/obj/effect/spawner/random/contraband/plus = 10,
/obj/item/reagent_containers/pill/maintenance = 5,
+ /obj/item/survivalcapsule/fishing = 5,
)
@@ -42,6 +43,7 @@
/obj/item/reagent_containers/cup/blastoff_ampoule = 5,
/obj/item/food/drug/moon_rock = 5,
/obj/item/grenade/empgrenade = 5,
+ /obj/item/survivalcapsule/fishing/hacked = 1,
/obj/effect/spawner/random/contraband/armory = 1,
)
diff --git a/code/game/objects/items/food/lizard.dm b/code/game/objects/items/food/lizard.dm
index 2048c997ef9..e0e005502d8 100644
--- a/code/game/objects/items/food/lizard.dm
+++ b/code/game/objects/items/food/lizard.dm
@@ -125,7 +125,8 @@
/obj/item/food/moonfish_eggs
name = "moonfish eggs"
- desc = "The moonfish lays large, transparent white eggs which are prized in lizard cooking. Their flavour is similar to caviar, but generally is described as deeper and more complex."
+ gender = PLURAL
+ desc = "The moonfish lays large, translucent blue eggs which are prized in lizard cooking. Their flavour is similar to caviar, but generally is described as deeper and more complex."
icon = 'icons/obj/food/lizard.dmi'
icon_state = "moonfish_eggs"
food_reagents = list(
@@ -137,6 +138,29 @@
w_class = WEIGHT_CLASS_SMALL
crafting_complexity = FOOD_COMPLEXITY_1
+/obj/item/food/moonfish_eggs/Initialize(mapload)
+ . = ..()
+ //Moonfish can lay eggs (unaffected by breeding, so think of them as unfertilizard)
+ RegisterSignal(src, COMSIG_AQUARIUM_CONTENT_GENERATE_APPEARANCE, PROC_REF(generate_aquarium_appearance))
+ RegisterSignal(src, AQUARIUM_CONTENT_RANDOMIZE_POSITION, PROC_REF(randomize_aquarium_position))
+ AddComponent(/datum/component/aquarium_content, beauty = 100)
+
+/obj/item/food/moonfish_eggs/proc/generate_aquarium_appearance(datum/source, obj/effect/aquarium/visual)
+ SIGNAL_HANDLER
+ visual.icon = icon
+ visual.icon_state = "moonfish_eggs_aquarium"
+ visual.layer_mode = AQUARIUM_LAYER_MODE_BOTTOM
+
+/obj/item/food/moonfish_eggs/proc/randomize_aquarium_position(datum/source, obj/structure/aquarium/current_aquarium, obj/effect/aquarium/visual)
+ SIGNAL_HANDLER
+ var/list/aq_properties = current_aquarium.get_surface_properties()
+ var/sprite_width = 5
+ var/px_min = aq_properties[AQUARIUM_PROPERTIES_PX_MIN]
+ var/px_max = aq_properties[AQUARIUM_PROPERTIES_PX_MAX] - sprite_width
+
+ visual.pixel_x = rand(px_min,px_max)
+ visual.pixel_y = rand(-1, 1)
+
/obj/item/food/moonfish_caviar
name = "moonfish caviar paste"
desc = "A rich paste made from moonfish eggs. Generally the only way most lizards can get them, and used fairly heavily in coastal cooking."
diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm
index 6cae493e57b..65a23c9a88b 100644
--- a/code/game/objects/structures/shower.dm
+++ b/code/game/objects/structures/shower.dm
@@ -250,7 +250,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
if(locate_new_shower && isturf(exiter.loc))
return
var/mob/living/take_his_status_effect = exiter
- take_his_status_effect.remove_status_effect(/datum/status_effect/shower_regen)
+ take_his_status_effect.remove_status_effect(/datum/status_effect/washing_regen)
/obj/machinery/shower/proc/wash_atom(atom/target)
target.wash(CLEAN_RAD | CLEAN_WASH)
@@ -259,7 +259,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
return
var/mob/living/living_target = target
check_heat(living_target)
- living_target.apply_status_effect(/datum/status_effect/shower_regen)
+ living_target.apply_status_effect(/datum/status_effect/washing_regen)
if(!HAS_TRAIT(target, TRAIT_WATER_HATER) || HAS_TRAIT(target, TRAIT_WATER_ADAPTATION))
living_target.add_mood_event("shower", /datum/mood_event/nice_shower)
else
@@ -294,7 +294,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
if(isopenturf(loc))
var/turf/open/tile = loc
tile.MakeSlippery(TURF_WET_WATER, min_wet_time = 5 SECONDS, wet_time_to_add = 1 SECONDS)
-
+ for(var/mob/living/showerer in loc)
+ showerer.remove_status_effect(/datum/status_effect/washing_regen)
return TRUE
/obj/machinery/shower/process(seconds_per_tick)
@@ -336,18 +337,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
if(has_water_reclaimer)
new /obj/item/stock_parts/water_recycler(drop_location())
-/obj/machinery/shower/proc/check_heat(mob/living/L)
- var/mob/living/carbon/C = L
+/obj/machinery/shower/proc/check_heat(mob/living/living)
if(current_temperature == SHOWER_FREEZING)
- if(iscarbon(L))
- C.adjust_bodytemperature(-80, 80)
- to_chat(L, span_warning("[src] is freezing!"))
+ living.adjust_bodytemperature(-80, 80)
+ to_chat(living, span_warning("[src] is freezing!"))
else if(current_temperature == SHOWER_BOILING)
- if(iscarbon(L))
- C.adjust_bodytemperature(35, 0, 500)
- L.adjustFireLoss(5)
- to_chat(L, span_danger("[src] is searing!"))
+ living.adjust_bodytemperature(35, 0, 500)
+ living.adjustFireLoss(5)
+ to_chat(living, span_danger("[src] is searing!"))
/obj/structure/showerframe
diff --git a/code/game/turfs/open/ice.dm b/code/game/turfs/open/ice.dm
index 39abe6ebfee..7d0a37ff847 100644
--- a/code/game/turfs/open/ice.dm
+++ b/code/game/turfs/open/ice.dm
@@ -60,13 +60,16 @@
if(!do_after(user, 5 SECONDS, src))
return FALSE
balloon_alert(user, "dug hole")
+ spawn_hole()
+ return TRUE
+
+/turf/open/misc/ice/proc/spawn_hole()
AddComponent(/datum/component/fishing_spot, GLOB.preset_fish_sources[/datum/fish_source/ice_fishing])
ADD_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT)
add_overlay(mutable_appearance('icons/turf/overlays.dmi', "ice_hole"))
can_make_hole = FALSE
RemoveElement(/datum/element/contextual_screentip_tools, tool_screentips)
flags_1 &= ~HAS_CONTEXTUAL_SCREENTIPS_1
- return TRUE
/turf/open/misc/ice/smooth
icon_state = "ice_turf-255"
@@ -82,13 +85,18 @@
/turf/open/misc/ice/icemoon/no_planet_atmos
planetary_atmos = FALSE
- can_make_hole = FALSE
+
+///Ice turf with a fishing spot already dug
+/turf/open/misc/ice/icemoon/no_planet_atmos/holed
+
+/turf/open/misc/ice/icemoon/no_planet_atmos/holed/Initialize(mapload)
+ . = ..()
+ spawn_hole()
/turf/open/misc/ice/temperate
baseturfs = /turf/open/misc/ice/temperate
desc = "Somehow, it is not melting under these conditions. Must be some very thick ice. Just as slippery too."
initial_gas_mix = COLD_ATMOS //it works with /turf/open/misc/asteroid/snow/temperatre
- can_make_hole = FALSE
//For when you want real, genuine ice in your kitchen's cold room.
/turf/open/misc/ice/coldroom
diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm
index 835d2908918..77709818f00 100644
--- a/code/game/turfs/open/water.dm
+++ b/code/game/turfs/open/water.dm
@@ -4,7 +4,7 @@
desc = "Shallow water."
icon = 'icons/turf/floors.dmi'
icon_state = "riverwater_motion"
- baseturfs = /turf/open/chasm/lavaland
+ baseturfs = /turf/open/water
planetary_atmos = TRUE
slowdown = 1
bullet_sizzle = TRUE
@@ -14,19 +14,22 @@
barefootstep = FOOTSTEP_WATER
clawfootstep = FOOTSTEP_WATER
heavyfootstep = FOOTSTEP_WATER
+ underfloor_accessibility = UNDERFLOOR_INTERACTABLE
/**
* Used as the color arg/var for the immerse element. It should be kept more or less in line with
* the hue of the turf, as semi-transparent vis overlays can opacify the semi-transparent bits of an icon,
* and we're kinda trying to offset that issue.
*/
var/immerse_overlay_color = "#5AAA88"
+ ///The transparency of the immerse element's overlay
+ var/immerse_overlay_alpha = 180
/// Fishing element for this specific water tile
var/datum/fish_source/fishing_datum = /datum/fish_source/river
/turf/open/water/Initialize(mapload)
. = ..()
- AddElement(/datum/element/immerse, icon, icon_state, "immerse", immerse_overlay_color)
+ AddElement(/datum/element/immerse, icon, icon_state, "immerse", immerse_overlay_color, alpha = immerse_overlay_alpha)
AddElement(/datum/element/watery_tile)
if(!isnull(fishing_datum))
AddElement(/datum/element/lazy_fishing_spot, fishing_datum)
@@ -34,6 +37,10 @@
/turf/open/water/jungle
+/turf/open/water/no_planet_atmos
+ baseturfs = /turf/open/water/no_planet_atmos
+ planetary_atmos = FALSE
+
/turf/open/water/beach
planetary_atmos = FALSE
gender = PLURAL
@@ -51,4 +58,112 @@
/turf/open/water/lavaland_atmos
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
- planetary_atmos = TRUE
+
+/turf/open/water/beach/tizira
+ desc = "Shallow water. It somehow reminds you of lizardfolk."
+ icon_state = "tizira_water"
+ base_icon_state = "tizira_water"
+ baseturfs = /turf/open/water/beach/tizira
+
+/**
+ * A special subtype of water with steam particles and a status effect similar to showers, that's however only applied if
+ * the living mob inside the turf is actually immersed in it (eg. not flying, not floating).
+ */
+/turf/open/water/hot_spring
+ name = "hot spring"
+ icon_state = "pool_1"
+ desc = "Water kept warm through some unknown heat source, possibly a geothermal heat source far underground. \
+ Whatever it is, it feels pretty damn nice to swim, and you can even catch a glimpse of \
+ the odd fish darting through the water."
+ baseturfs = /turf/open/water/hot_spring
+ planetary_atmos = FALSE
+ immerse_overlay_color = "#A0E2DE"
+ immerse_overlay_alpha = 190
+ fishing_datum = /datum/fish_source/hot_spring
+ /// Holder for the steam particles
+ var/obj/effect/abstract/particle_holder/cached/particle_effect
+
+/turf/open/water/hot_spring/Initialize(mapload)
+ . = ..()
+ icon_state = "pool_[rand(1, 4)]"
+ particle_effect = new(src, /particles/hotspring_steam, 4)
+ //render the steam over mobs and objects on the game plane
+ particle_effect.vis_flags &= ~VIS_INHERIT_PLANE
+ //And be unaffected by ambient occlusions, which would render the steam grey
+ particle_effect.plane = MUTATE_PLANE(MASSIVE_OBJ_PLANE, src)
+ add_filter("hot_spring_waves", 1, wave_filter(y = 1, size = 1, offset = 0, flags = WAVE_BOUNDED))
+ var/filter = get_filter("hot_spring_waves")
+ animate(filter, offset = 1, time = 3 SECONDS, loop = -1, easing = SINE_EASING|EASE_IN|EASE_OUT)
+ animate(offset = -1, time = 3 SECONDS, easing = SINE_EASING|EASE_IN|EASE_OUT)
+
+ /**
+ * turf/Initialize() calls Entered on its contents, however
+ * we need to wait for movables that still need to be initialized.
+ */
+ RegisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(enter_initialized_movable))
+
+/turf/open/water/hot_spring/Destroy()
+ QDEL_NULL(particle_effect)
+ remove_filter("hot_spring_waves")
+ for(var/atom/movable/movable as anything in contents)
+ exit_hot_spring(movable)
+ UnregisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON)
+ return ..()
+
+/turf/open/water/hot_spring/Entered(atom/movable/arrived, atom/old_loc)
+ . = ..()
+ if(!(flags_1 & INITIALIZED_1))
+ return
+ enter_hot_spring(arrived)
+
+/turf/open/water/hot_spring/proc/enter_initialized_movable(datum/source, atom/movable/movable)
+ SIGNAL_HANDLER
+ enter_hot_spring(movable)
+
+///Registers the signals from the immerse element and calls dip_in if the movable has the required trait.
+/turf/open/water/hot_spring/proc/enter_hot_spring(atom/movable/movable)
+ RegisterSignal(movable, SIGNAL_ADDTRAIT(TRAIT_IMMERSED), PROC_REF(dip_in))
+ if(isliving(movable)) //so far, exiting a hot spring only has effects on living mobs.
+ RegisterSignal(movable, SIGNAL_REMOVETRAIT(TRAIT_IMMERSED), PROC_REF(dip_out))
+
+ if(HAS_TRAIT(movable, TRAIT_IMMERSED))
+ dip_in(movable)
+
+///Handles washing the movable and adding a status effect plus mood event to living mobs.
+/turf/open/water/hot_spring/proc/dip_in(atom/movable/movable)
+ SIGNAL_HANDLER
+ movable.wash(CLEAN_RAD | CLEAN_WASH)
+ if(!isliving(movable))
+ return
+
+ var/mob/living/living = movable
+ if(living.has_status_effect(/datum/status_effect/washing_regen/hot_spring))
+ return
+ living.apply_status_effect(/datum/status_effect/washing_regen/hot_spring)
+ if(!HAS_TRAIT(living, TRAIT_WATER_HATER) || HAS_TRAIT(living, TRAIT_WATER_ADAPTATION))
+ living.add_mood_event("hot_spring", /datum/mood_event/hot_spring)
+ else
+ living.add_mood_event("hot_spring", /datum/mood_event/hot_spring_hater)
+
+/turf/open/water/hot_spring/Exited(atom/movable/gone, atom/new_loc)
+ . = ..()
+ exit_hot_spring(gone)
+
+//Unregister the signals and remove the status effect from mobs unless they're moving to another hot spring turf.
+/turf/open/water/hot_spring/proc/exit_hot_spring(atom/movable/movable)
+ UnregisterSignal(movable, list(SIGNAL_ADDTRAIT(TRAIT_IMMERSED), SIGNAL_REMOVETRAIT(TRAIT_IMMERSED)))
+ if(!isliving(movable))
+ return
+ var/mob/living/living = movable
+ if(!living.has_status_effect(/datum/status_effect/washing_regen/hot_spring) || istype(living.loc, /turf/open/water/hot_spring))
+ return
+ dip_out(living)
+
+///Handles removing the status effect from mobs.
+/turf/open/water/hot_spring/proc/dip_out(mob/living/living)
+ SIGNAL_HANDLER
+ living.remove_status_effect(/datum/status_effect/washing_regen/hot_spring)
+ if(!HAS_TRAIT(living, TRAIT_WATER_HATER) || HAS_TRAIT(living, TRAIT_WATER_ADAPTATION))
+ living.add_mood_event("hot_spring", /datum/mood_event/hot_spring_left)
+ else
+ living.add_mood_event("hot_spring", /datum/mood_event/hot_spring_hater_left)
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 9d46a73e16c..99e014d564b 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -661,7 +661,7 @@
continue
var/turf/node_turf = get_turf(node)
- if(isplatingturf(node_turf) || iscatwalkturf(node_turf))
+ if(node_turf.underfloor_accessibility > UNDERFLOOR_HIDDEN)
continue
var/connected_dir = get_dir(src, node)
diff --git a/code/modules/cargo/markets/market_items/misc.dm b/code/modules/cargo/markets/market_items/misc.dm
index c53076f737c..bb8d3da04d8 100644
--- a/code/modules/cargo/markets/market_items/misc.dm
+++ b/code/modules/cargo/markets/market_items/misc.dm
@@ -125,6 +125,17 @@
stock_max = 1
availability_prob = 15
+/datum/market_item/misc/fishing_capsule
+ name = "Fishing Spot Capsule"
+ //IUU stands for Illegal Unreported and Unregulated fishing. Ironic.
+ desc = "A repurposed mining capsule connected to a selection of exclusive fishing spots. Approved by the Intergalactic IUU Fishing Association."
+ price_min = CARGO_CRATE_VALUE * 1.125
+ price_max = CARGO_CRATE_VALUE * 2.125
+ item = /obj/item/survivalcapsule/fishing
+ stock_min = 1
+ stock_max = 4
+ availability_prob = 80
+
/datum/market_item/misc/fish
name = "Fish"
desc = "Fish! Fresh fish! Fish you can cut, grind and even keep in aquarium if you want to! Get some before the next fight at my village breaks out!"
diff --git a/code/modules/fishing/aquarium/aquarium_kit.dm b/code/modules/fishing/aquarium/aquarium_kit.dm
index ffa5e45c014..17dd518710d 100644
--- a/code/modules/fishing/aquarium/aquarium_kit.dm
+++ b/code/modules/fishing/aquarium/aquarium_kit.dm
@@ -72,7 +72,13 @@
name = "imported fish case"
/obj/item/storage/fish_case/tiziran/get_fish_type()
- return pick(/obj/item/fish/dwarf_moonfish, /obj/item/fish/gunner_jellyfish, /obj/item/fish/needlefish, /obj/item/fish/armorfish)
+ return pick_weight(list(
+ /obj/item/fish/moonfish/dwarf = 2,
+ /obj/item/fish/gunner_jellyfish = 2,
+ /obj/item/fish/needlefish = 2,
+ /obj/item/fish/armorfish = 2,
+ /obj/item/fish/moonfish = 1,
+ ))
///Subtype bought from the blackmarket at a gratuitously cheap price. The catch? The fish inside it is dead.
/obj/item/storage/fish_case/blackmarket
diff --git a/code/modules/fishing/fish/fish_evolution.dm b/code/modules/fishing/fish/fish_evolution.dm
index 52708add566..a9261b091c9 100644
--- a/code/modules/fishing/fish/fish_evolution.dm
+++ b/code/modules/fishing/fish/fish_evolution.dm
@@ -169,3 +169,28 @@ GLOBAL_LIST_EMPTY(fishes_by_fish_evolution)
if(source.size >= (/obj/item/fish/fryish/fritterish::average_size * 1.5) && source.size >= (/obj/item/fish/fryish/fritterish::average_weight * 1.5))
return ..()
return FALSE
+
+/datum/fish_evolution/moonfish
+ probability = 200 //guaranteed if the conditions are met
+ new_fish_type = /obj/item/fish/moonfish
+ conditions_note = "Requires the dwarf moonfish to be big enough."
+
+/datum/fish_evolution/moonfish/check_conditions(obj/item/fish/source, obj/item/fish/mate, obj/structure/aquarium/aquarium)
+ if(source.size < (/obj/item/fish/moonfish/dwarf::average_size * 1.5) && source.size < (/obj/item/fish/moonfish/dwarf::average_weight * 1.5))
+ return ..()
+ if(mate && (mate.size < (/obj/item/fish/moonfish::average_size * 1.3) && mate.size < (/obj/item/fish/moonfish::average_weight * 1.3)))
+ return FALSE
+ return FALSE
+
+/datum/fish_evolution/dwarf_moonfish
+ probability = 200 //guaranteed if the conditions are met
+ new_fish_type = /obj/item/fish/moonfish/dwarf
+ conditions_note = "Requires the moonfish to be small enough."
+
+/datum/fish_evolution/dwarf_moonfish/check_conditions(obj/item/fish/source, obj/item/fish/mate, obj/structure/aquarium/aquarium)
+ if(source.size > (/obj/item/fish/moonfish::average_size * 0.66) && source.size > (/obj/item/fish/moonfish::average_weight * 0.66))
+ return FALSE
+ if(mate && (mate.size > (/obj/item/fish/moonfish::average_size * 0.7) && mate.size > (/obj/item/fish/moonfish::average_weight * 0.7)))
+ return FALSE
+ return ..()
+
diff --git a/code/modules/fishing/fish/types/air_space.dm b/code/modules/fishing/fish/types/air_space.dm
index 73c7b82c29d..c60fc7a36ef 100644
--- a/code/modules/fishing/fish/types/air_space.dm
+++ b/code/modules/fishing/fish/types/air_space.dm
@@ -167,7 +167,7 @@
AddComponent(/datum/component/fish_growth, /mob/living/basic/carp/advanced, growth_rate)
-/obj/item/fish/baby_carp/proc/growth_checks(datum/source, seconds_per_tick)
+/obj/item/fish/baby_carp/proc/growth_checks(datum/source, seconds_per_tick, growth, result_path)
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.
diff --git a/code/modules/fishing/fish/types/freshwater.dm b/code/modules/fishing/fish/types/freshwater.dm
index d11b7cb2219..660a406183c 100644
--- a/code/modules/fishing/fish/types/freshwater.dm
+++ b/code/modules/fishing/fish/types/freshwater.dm
@@ -196,7 +196,7 @@
else
deltimer(del_timerid)
-/obj/item/fish/tadpole/proc/growth_checks(datum/source, seconds_per_tick, growth)
+/obj/item/fish/tadpole/proc/growth_checks(datum/source, seconds_per_tick, growth, result_path)
SIGNAL_HANDLER
var/hunger = get_hunger()
if(hunger >= 0.7) //too hungry to grow
@@ -234,3 +234,23 @@
/obj/item/fish,
/obj/item/fishing_lure, //they love lures in general.
)
+
+///Memetic fish from a paleontologically inaccurate, goofy replica of a specimen. Sells decently for its size.
+/obj/item/fish/sacabambaspis
+ name = "sacabambaspis"
+ fish_id = "sacabambaspis"
+ desc = "A jawless fish ought to be extinct by the end of the Ordovician period. Some speculate alien intervention may have been behind its survival and inevitable evolution as a dweller of hot springs."
+ icon_state = "sacabambaspis"
+ sprite_width = 5
+ sprite_height = 3
+ stable_population = 7
+ average_size = 27
+ average_weight = 500
+ required_temperature_min = MIN_AQUARIUM_TEMP+20
+ required_temperature_max = MIN_AQUARIUM_TEMP+45
+ random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
+ beauty = FISH_BEAUTY_GOOD
+ fish_traits = list(/datum/fish_trait/necrophage, /datum/fish_trait/wary)
+
+/obj/item/fish/sacabambaspis/get_export_price(price, percent)
+ return ..() * 4.5
diff --git a/code/modules/fishing/fish/types/mining.dm b/code/modules/fishing/fish/types/mining.dm
index 41e240889da..53c1b89673c 100644
--- a/code/modules/fishing/fish/types/mining.dm
+++ b/code/modules/fishing/fish/types/mining.dm
@@ -68,7 +68,7 @@
if(.)
anger -= min(anger, 6.5)
-/obj/item/fish/chasm_crab/proc/growth_checks(datum/source, seconds_per_tick, growth)
+/obj/item/fish/chasm_crab/proc/growth_checks(datum/source, seconds_per_tick, growth, result_path)
SIGNAL_HANDLER
var/hunger = get_hunger()
if(health <= initial(health) * 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow.
diff --git a/code/modules/fishing/fish/types/tiziran.dm b/code/modules/fishing/fish/types/tiziran.dm
index 5f90cedc63d..7cc3ea94e68 100644
--- a/code/modules/fishing/fish/types/tiziran.dm
+++ b/code/modules/fishing/fish/types/tiziran.dm
@@ -1,20 +1,71 @@
//Tiziran Fish.
-/obj/item/fish/dwarf_moonfish
+/obj/item/fish/moonfish
+ name = "zagoskian moonfish"
+ fish_id = "moonfish"
+ desc = "A disc-shaped fish native of the less shallow areas of Tizira's oceans, roughly the size of a tuna. Highly prized in lizard cuisine for their large eggs."
+ icon_state = "tizira_moonfish"
+ sprite_height = 7
+ sprite_width = 7
+ fillet_type = /obj/item/food/fishmeat/moonfish
+ required_fluid_type = AQUARIUM_FLUID_SALTWATER
+ stable_population = 2
+ average_size = 95
+ average_weight = 2000
+ required_temperature_min = MIN_AQUARIUM_TEMP+20
+ required_temperature_max = MIN_AQUARIUM_TEMP+30
+ beauty = FISH_BEAUTY_GOOD
+ weight_size_deviation = 0.1
+ fishing_difficulty_modifier = 10
+ random_case_rarity = FISH_RARITY_RARE
+ fish_traits = list(/datum/fish_trait/predator)
+ compatible_types = list(/obj/item/fish/moonfish, /obj/item/fish/moonfish/dwarf)
+ evolution_types = list(/datum/fish_evolution/dwarf_moonfish)
+ favorite_bait = list(
+ /obj/item/fish/armorfish,
+ /obj/item/fish/needlefish,
+ /obj/item/fish/gunner_jellyfish,
+ )
+ var/egg_laying_time = 2.75 MINUTES
+
+/obj/item/fish/moonfish/Initialize(mapload, apply_qualities = TRUE)
+ . = ..()
+ AddComponent(/datum/component/fish_growth, /obj/item/food/moonfish_eggs, egg_laying_time, use_drop_loc = FALSE, del_on_grow = FALSE, inherit_name = FALSE)
+ RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(egg_checks))
+
+///Stop laying eggs if we're in an unsafe environment, starving of if there are simply too many eggs already.
+/obj/item/fish/moonfish/proc/egg_checks(datum/source, seconds_per_tick, growth, result_path)
+ if(result_path != /obj/item/food/moonfish_eggs) //Don't stop the growth of the dwarf subtype.
+ return
+ if(!proper_environment() || is_starving())
+ return COMPONENT_DONT_GROW
+ var/count = 0
+ for(var/obj/item/food/moonfish_eggs/egg in loc)
+ count ++
+ if(count > 10)
+ return COMPONENT_DONT_GROW
+
+/obj/item/fish/moonfish/dwarf
name = "dwarf moonfish"
fish_id = "dwarf_moonfish"
desc = "Ordinarily in the wild, the Zagoskian moonfish is around the size of a tuna, however through selective breeding a smaller breed suitable for being kept as an aquarium pet has been created."
icon_state = "dwarf_moonfish"
sprite_height = 6
sprite_width = 6
- required_fluid_type = AQUARIUM_FLUID_SALTWATER
- stable_population = 2
- fillet_type = /obj/item/food/fishmeat/moonfish
- average_size = 60
- average_weight = 1000
- required_temperature_min = MIN_AQUARIUM_TEMP+20
- required_temperature_max = MIN_AQUARIUM_TEMP+30
- beauty = FISH_BEAUTY_GOOD
+ stable_population = 3
+ average_size = 50
+ average_weight = 950
+ fishing_difficulty_modifier = 0
+ egg_laying_time = 4.25 MINUTES
+ random_case_rarity = FISH_RARITY_BASIC
+ fish_traits = list()
+ evolution_types = list(/datum/fish_evolution/moonfish)
+
+/obj/item/fish/moonfish/dwarf/update_size_and_weight(new_size = average_size, new_weight = average_weight, update_materials = TRUE)
+ . = ..()
+ var/multiplier = (size / (average_size * 1.5)) * (weight / (average_weight * 1.5))
+
+ AddComponent(/datum/component/fish_growth, /datum/fish_evolution/moonfish, 2.5 MINUTES * multiplier, use_drop_loc = FALSE)
/obj/item/fish/gunner_jellyfish
name = "gunner jellyfish"
@@ -30,6 +81,10 @@
required_temperature_min = MIN_AQUARIUM_TEMP+24
required_temperature_max = MIN_AQUARIUM_TEMP+32
beauty = FISH_BEAUTY_GOOD
+ favorite_bait = list(
+ /obj/item/fish/armorfish,
+ /obj/item/fish/needlefish,
+ )
/obj/item/fish/gunner_jellyfish/Initialize(mapload, apply_qualities = TRUE)
. = ..()
diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm
index 6ab8ca26962..24aec7c8195 100644
--- a/code/modules/fishing/fishing_equipment.dm
+++ b/code/modules/fishing/fishing_equipment.dm
@@ -477,5 +477,101 @@
Do not spin while the light is still red.
\
That's all, best of luck to your angling journey."
+///A modified mining capsule from the black market and sometimes random loot.
+/obj/item/survivalcapsule/fishing
+ name = "fishing spot capsule"
+ desc = "An illegally modified mining capsule containing a small fishing spot connected to some faraway place."
+ icon_state = "capsule_fishing"
+ initial_language_holder = /datum/language_holder/speaking_machine
+ verb_say = "beeps"
+ verb_yell = "blares"
+ voice_filter = "alimiter=0.9,acompressor=threshold=0.3:ratio=40:attack=15:release=350:makeup=1.5,highpass=f=1000,rubberband=pitch=1.5"
+ template_id = "fishing_default"
+ yeet_back = FALSE
+
+/obj/item/survivalcapsule/fishing/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_CONTRABAND, INNATE_TRAIT)
+ register_context()
+
+ if(SStts.tts_enabled) //This capsule informs you on why it cannot be deployed in a sliiiiightly different way.
+ voice = pick(SStts.available_speakers)
+
+/obj/item/survivalcapsule/fishing/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ if(!held_item || held_item == src)
+ context[SCREENTIP_CONTEXT_RMB] = "Change fishing spot"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/item/survivalcapsule/fishing/examine(mob/user)
+ . = ..()
+ . += span_info("[EXAMINE_HINT("Right-Click")] to change the selected fishing spot when held.")
+
+/obj/item/survivalcapsule/fishing/examine_more(mob/user)
+ . = ..()
+ . += span_tinynotice("A tiny print on the side reads: \"Use a cryptographic sequencer to disable safeties\".")
+
+/obj/item/survivalcapsule/fishing/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
+ obj_flags |= EMAGGED
+ balloon_alert(user, "safeties disabled")
+ playsound(src, SFX_SPARKS, 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ return TRUE
+
+/obj/item/survivalcapsule/fishing/attack_self_secondary(mob/living/user)
+ . = ..()
+ if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
+ return
+ . = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ if(used)
+ return
+ var/list/choices = list()
+ var/list/spot_ids_by_name = list()
+ for(var/datum/map_template/shelter/fishing/spot as anything in typesof(/datum/map_template/shelter/fishing))
+ if(!spot::safe && !(obj_flags & EMAGGED))
+ continue
+ choices[spot::name] = image('icons/hud/radial_fishing.dmi', spot::radial_icon)
+ spot_ids_by_name[spot::name] = spot::shelter_id
+ var/choice = show_radial_menu(user, src, choices, radius = 38, custom_check = CALLBACK(src, TYPE_PROC_REF(/atom, can_interact), user), tooltips = TRUE)
+ if(!choice || used || !can_interact(user))
+ return
+ template_id = spot_ids_by_name[choice]
+ template = SSmapping.shelter_templates[template_id]
+ to_chat(user, span_notice("You change [src]'s selected fishing spot to [choice]."))
+ playsound(src, 'sound/items/pen_click.ogg', 20, TRUE, -3)
+ return
+
+/obj/item/survivalcapsule/fishing/get_ignore_flags()
+ . = ..()
+ if(obj_flags & EMAGGED)
+ . += CAPSULE_IGNORE_ANCHORED_OBJECTS|CAPSULE_IGNORE_BANNED_OBJECTS
+
+/obj/item/survivalcapsule/fishing/fail_feedback(status)
+ switch(status)
+ if(SHELTER_DEPLOY_BAD_AREA)
+ say("I refuse to deploy in this area.")
+ if(SHELTER_DEPLOY_BAD_TURFS)
+ say("The walls are too close! I need [template.width]x[template.height] area to deploy.")
+ if(SHELTER_DEPLOY_ANCHORED_OBJECTS)
+ say("Get these anchored objects out of the way! I need [template.width]x[template.height] area to deploy.")
+ if(SHELTER_DEPLOY_BANNED_OBJECTS)
+ say("Remove all cables and pipes around me in a [template.width]x[template.height] area or I won't deploy.")
+ if(SHELTER_DEPLOY_OUTSIDE_MAP)
+ say("For fucks sake, deploy me somewhere less far fatched!")
+
+/obj/item/survivalcapsule/fishing/trigger_admin_alert(mob/triggerer, turf/trigger_loc)
+ var/datum/map_template/shelter/fishing/spot = template
+ if(spot.safe) //Don't log if the fishing spot is safe
+ return
+
+ var/area/area = get_area(src)
+
+ if(!area.outdoors)
+ message_admins("[ADMIN_LOOKUPFLW(triggerer)] activated an unsafe fishing capsule at [ADMIN_VERBOSEJMP(trigger_loc)]")
+ log_admin("[key_name(triggerer)] activated an unsafe fishing capsule at [AREACOORD(trigger_loc)]")
+
+/obj/item/survivalcapsule/fishing/hacked
+ obj_flags = parent_type::obj_flags | EMAGGED
+
#undef MAGNET_HOOK_BONUS_MULTIPLIER
#undef RESCUE_HOOK_FISH_MULTIPLIER
diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm
index 71780e76f11..3ea4d1dffd8 100644
--- a/code/modules/fishing/sources/_fish_source.dm
+++ b/code/modules/fishing/sources/_fish_source.dm
@@ -43,6 +43,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/obj/item/fish/stingray = FISH_ICON_WEAPON,
/obj/item/fish/swordfish = FISH_ICON_WEAPON,
/obj/item/fish/zipzap = FISH_ICON_ELECTRIC,
+ /obj/item/fishing_rod = FISH_ICON_COIN,
/obj/item/instrument/trumpet/spectral = FISH_ICON_BONE,
/obj/item/instrument/saxophone/spectral = FISH_ICON_BONE,
/obj/item/instrument/trombone/spectral = FISH_ICON_BONE,
@@ -53,6 +54,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/obj/item/stack/sheet/bone = FISH_ICON_BONE,
/obj/item/stack/sheet/mineral = FISH_ICON_GEM,
/obj/item/stack/ore = FISH_ICON_GEM,
+ /obj/item/survivalcapsule/fishing = FISH_ICON_COIN,
/obj/structure/closet/crate = FISH_ICON_COIN,
/obj/structure/mystery_box = FISH_ICON_COIN,
))
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index a21f3f008e8..3830266b5bb 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -128,6 +128,10 @@
/obj/item/fish/greenchromis = 10,
/obj/item/fish/squid = 8,
/obj/item/fish/plaice = 8,
+ /obj/item/survivalcapsule/fishing = 1,
+ )
+ fish_counts = list(
+ /obj/item/survivalcapsule/fishing = 1,
)
catalog_description = "Beach dimension (Fishing portal generator)"
radial_name = "Beach"
@@ -160,14 +164,15 @@
/obj/effect/spawner/message_in_a_bottle = 2,
/obj/item/fish/lanternfish = 5,
/obj/item/fish/firefish = 5,
- /obj/item/fish/dwarf_moonfish = 5,
/obj/item/fish/gunner_jellyfish = 5,
+ /obj/item/fish/moonfish/dwarf = 4,
/obj/item/fish/needlefish = 5,
/obj/item/fish/armorfish = 5,
/obj/item/fish/zipzap = 5,
/obj/item/fish/stingray = 4,
/obj/item/fish/monkfish = 4,
/obj/item/fish/swordfish = 3,
+ /obj/item/fish/moonfish = 1,
)
fish_counts = list(
/obj/item/fish/swordfish = 2,
@@ -358,6 +363,7 @@
/datum/fish_source/lavaland/icemoon
catalog_description = "Liquid plasma vents"
+ radial_state = "plasma"
fish_table = list(
FISHING_DUD = 5,
/obj/item/fish/chasm_crab/ice = 30,
@@ -397,9 +403,11 @@
/obj/item/fish/sludgefish = 18,
/obj/item/fish/slimefish = 4,
/obj/item/storage/wallet/money = 2,
+ /obj/item/survivalcapsule/fishing = 1,
)
fish_counts = list(
/obj/item/storage/wallet/money = 2,
+ /obj/item/survivalcapsule/fishing = 1,
)
fishing_difficulty = FISHING_EASY_DIFFICULTY //For beginners
@@ -623,3 +631,39 @@
/obj/item/fish/fryish/fritterish = 6 MINUTES,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 13
+
+/datum/fish_source/hot_spring
+ catalog_description = "Hot Springs"
+ radial_state = "onsen"
+ overlay_state = "portal_ocean"
+ fish_table = list(
+ FISHING_DUD = 20,
+ /obj/item/fish/bumpy = 10,
+ /obj/item/fish/sacabambaspis = 10,
+ /mob/living/basic/frog = 2,
+ /obj/item/fishing_rod/telescopic/master = 1,
+ )
+ fish_counts = list(
+ /obj/item/fish/sacabambaspis = 5,
+ /obj/item/fishing_rod/telescopic/master = 2,
+ )
+ fish_count_regen = list(
+ /obj/item/fish/sacabambaspis = 4 MINUTES,
+ )
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
+
+/datum/fish_source/tizira
+ catalog_description = "Tiziran Sea"
+ radial_state = "planet"
+ overlay_state = "portal_beach"
+ fish_table = list(
+ FISHING_DUD = 10,
+ /obj/item/fish/needlefish = 5,
+ /obj/item/fish/armorfish = 5,
+ /obj/item/fish/gunner_jellyfish = 4,
+ /obj/item/fish/moonfish/dwarf = 2,
+ /obj/item/fish/moonfish = 2,
+ )
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
diff --git a/code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm b/code/modules/mapfluff/ruins/icemoonruin_code/cursed_spring.dm
similarity index 52%
rename from code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm
rename to code/modules/mapfluff/ruins/icemoonruin_code/cursed_spring.dm
index 6952dd0af58..c9ee307e423 100644
--- a/code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm
+++ b/code/modules/mapfluff/ruins/icemoonruin_code/cursed_spring.dm
@@ -10,33 +10,30 @@
*
*/
-/turf/open/water/cursed_spring
- name = "cursed spring"
- baseturfs = /turf/open/water/cursed_spring
+/turf/open/water/hot_spring/cursed
+ baseturfs = /turf/open/water/hot_spring/cursed
planetary_atmos = TRUE
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
fishing_datum = /datum/fish_source/cursed_spring
-/turf/open/water/cursed_spring/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
- . = ..()
- if(!isliving(arrived))
- return
- var/mob/living/to_transform = arrived
- var/datum/mind/transforming_mind = to_transform.mind
- if(!to_transform.client || to_transform.incorporeal_move || !transforming_mind)
- return
- if(HAS_TRAIT(transforming_mind, TRAIT_HOT_SPRING_CURSED)) // no double dipping
- return
+/turf/open/water/hot_spring/cursed/dip_in(atom/movable/movable)
+ if(!isliving(movable))
+ return ..()
+ var/mob/living/living = movable
+ if(!living.client || living.incorporeal_move || !living.mind)
+ return ..()
+ if(HAS_MIND_TRAIT(living, TRAIT_HOT_SPRING_CURSED)) // no double dipping
+ return ..()
- ADD_TRAIT(transforming_mind, TRAIT_HOT_SPRING_CURSED, TRAIT_GENERIC)
- var/mob/living/transformed_mob = to_transform.wabbajack(pick(WABBAJACK_HUMAN, WABBAJACK_ANIMAL), change_flags = RACE_SWAP)
+ ADD_TRAIT(living.mind, TRAIT_HOT_SPRING_CURSED, TRAIT_GENERIC)
+ var/mob/living/transformed_mob = living.wabbajack(pick(WABBAJACK_HUMAN, WABBAJACK_ANIMAL), change_flags = RACE_SWAP)
if(!transformed_mob)
// Wabbajack failed, maybe the mob had godmode or something.
- if(!QDELETED(to_transform))
- to_chat(to_transform, span_notice("The water seems to have no effect on you."))
+ if(!QDELETED(living))
+ to_chat(living, span_notice("The water seems to have no effect on you."))
// because it failed, let's allow them to try again in a lil' bit
- addtimer(TRAIT_CALLBACK_REMOVE(transforming_mind, TRAIT_HOT_SPRING_CURSED, TRAIT_GENERIC), 10 SECONDS)
- return
+ addtimer(TRAIT_CALLBACK_REMOVE(living.mind, TRAIT_HOT_SPRING_CURSED, TRAIT_GENERIC), 10 SECONDS)
+ return ..()
var/turf/return_turf = find_safe_turf(extended_safety_checks = TRUE, dense_atoms = FALSE)
transformed_mob.forceMove(return_turf)
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index b22603f52d9..ce0c2d923a4 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -15,9 +15,14 @@
icon_state = "capsule"
icon = 'icons/obj/mining.dmi'
w_class = WEIGHT_CLASS_TINY
+ ///The id we use to fetch the template datum
var/template_id = "shelter_alpha"
+ ///The template datum we use to load the shelter
var/datum/map_template/shelter/template
+ ///If true, this capsule is active and will deploy the area if conditions are met.
var/used = FALSE
+ ///Will this capsule yeet mobs back once the area is deployed?
+ var/yeet_back = TRUE
/obj/item/survivalcapsule/proc/get_template()
if(template)
@@ -37,7 +42,7 @@
. += "This capsule has the [template.name] stored."
. += template.description
-/obj/item/survivalcapsule/interact(mob/user)
+/obj/item/survivalcapsule/interact(mob/living/user)
. = ..()
if(.)
return .
@@ -50,6 +55,9 @@
loc.visible_message(span_warning("[src] begins to shake. Stand back!"))
used = TRUE
addtimer(CALLBACK(src, PROC_REF(expand), user), 5 SECONDS)
+ if(iscarbon(user))
+ var/mob/living/carbon/carbon = user
+ carbon.throw_mode_on(THROW_MODE_TOGGLE)
return TRUE
/// Expands the capsule into a full shelter, placing the template at the item's location (NOT triggerer's location)
@@ -58,24 +66,32 @@
return
var/turf/deploy_location = get_turf(src)
- var/status = template.check_deploy(deploy_location)
- switch(status)
- if(SHELTER_DEPLOY_BAD_AREA)
- loc.visible_message(span_warning("[src] will not function in this area."))
- if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS, SHELTER_DEPLOY_OUTSIDE_MAP)
- loc.visible_message(span_warning("[src] doesn't have room to deploy! You need to clear a [template.width]x[template.height] area!"))
-
+ var/status = template.check_deploy(deploy_location, src, get_ignore_flags())
if(status != SHELTER_DEPLOY_ALLOWED)
+ fail_feedback(status)
used = FALSE
return
- yote_nearby(deploy_location)
+ if(yeet_back)
+ yote_nearby(deploy_location)
template.load(deploy_location, centered = TRUE)
trigger_admin_alert(triggerer, deploy_location)
playsound(src, 'sound/effects/phasein.ogg', 100, TRUE)
new /obj/effect/particle_effect/fluid/smoke(get_turf(src))
qdel(src)
+/// Returns a bitfield used to ignore some checks in template.check_deploy()
+/obj/item/survivalcapsule/proc/get_ignore_flags()
+ return NONE
+
+///Returns a message including the reason why it couldn't be deployed
+/obj/item/survivalcapsule/proc/fail_feedback(status)
+ switch(status)
+ if(SHELTER_DEPLOY_BAD_AREA)
+ loc.visible_message(span_warning("[src] will not function in this area."))
+ if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS, SHELTER_DEPLOY_OUTSIDE_MAP, SHELTER_DEPLOY_BANNED_OBJECTS)
+ loc.visible_message(span_warning("[src] doesn't have room to deploy! You need to clear a [template.width]x[template.height] area!"))
+
/// Throws any mobs near the deployed location away from the item / shelter
/// Does some math to make closer mobs get thrown further
/obj/item/survivalcapsule/proc/yote_nearby(turf/deploy_location)
diff --git a/code/modules/mining/shelters.dm b/code/modules/mining/shelters.dm
index c3fdc820bef..539854a3947 100644
--- a/code/modules/mining/shelters.dm
+++ b/code/modules/mining/shelters.dm
@@ -1,36 +1,39 @@
+///Map templates used for bluespace survival capsules.
/datum/map_template/shelter
- var/shelter_id
- var/description
- var/list/blacklisted_turfs
- var/list/whitelisted_turfs
- var/list/banned_areas
- var/list/banned_objects
has_ceiling = TRUE
ceiling_turf = /turf/open/floor/engine/hull
ceiling_baseturfs = list(/turf/open/floor/plating)
+ ///The id of the shelter template in the relative list from the mapping subsystem
+ var/shelter_id
+ ///The description of the shelter, shown when examining survival capsule.
+ var/description
+ ///If turf in the affected turfs is in this list, the survival capsule cannot be deployed.
+ var/list/blacklisted_turfs
+ ///Areas where the capsule cannot be deployed.
+ var/list/banned_areas
+ ///If any object in this list is found in the affected turfs, the capsule cannot deploy.
+ var/list/banned_objects = list()
/datum/map_template/shelter/New()
. = ..()
blacklisted_turfs = typecacheof(/turf/closed)
- whitelisted_turfs = list()
banned_areas = typecacheof(/area/shuttle)
- banned_objects = list()
-/datum/map_template/shelter/proc/check_deploy(turf/deploy_location)
+/datum/map_template/shelter/proc/check_deploy(turf/deploy_location, obj/item/survivalcapsule/capsule, ignore_flags = NONE)
var/affected = get_affected_turfs(deploy_location, centered=TRUE)
- for(var/turf/T in affected)
- var/area/A = get_area(T)
- if(is_type_in_typecache(A, banned_areas))
+ for(var/turf/turf in affected)
+ var/area/area = get_area(turf)
+ if(is_type_in_typecache(area, banned_areas))
return SHELTER_DEPLOY_BAD_AREA
- var/banned = is_type_in_typecache(T, blacklisted_turfs)
- var/permitted = is_type_in_typecache(T, whitelisted_turfs)
- if(banned && !permitted)
+ if(is_type_in_typecache(turf, blacklisted_turfs))
return SHELTER_DEPLOY_BAD_TURFS
- for(var/obj/O in T)
- if((O.density && O.anchored) || is_type_in_typecache(O, banned_objects))
+ for(var/obj/object in turf)
+ if(!(ignore_flags & CAPSULE_IGNORE_ANCHORED_OBJECTS) && object.density && object.anchored)
return SHELTER_DEPLOY_ANCHORED_OBJECTS
+ if(!(ignore_flags & CAPSULE_IGNORE_BANNED_OBJECTS) && is_type_in_typecache(object, banned_objects))
+ return SHELTER_DEPLOY_BANNED_OBJECTS
// Check if the shelter sticks out of map borders
var/shelter_origin_x = deploy_location.x - round(width/2)
@@ -53,7 +56,7 @@
/datum/map_template/shelter/alpha/New()
. = ..()
- whitelisted_turfs = typecacheof(/turf/closed/mineral)
+ blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
/datum/map_template/shelter/beta
@@ -68,7 +71,7 @@
/datum/map_template/shelter/beta/New()
. = ..()
- whitelisted_turfs = typecacheof(/turf/closed/mineral)
+ blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
/datum/map_template/shelter/charlie
@@ -83,7 +86,7 @@
/datum/map_template/shelter/charlie/New()
. = ..()
- whitelisted_turfs = typecacheof(/turf/closed/mineral)
+ blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
/datum/map_template/shelter/toilet
@@ -96,5 +99,76 @@
/datum/map_template/shelter/toilet/New()
. = ..()
- whitelisted_turfs = typecacheof(/turf/closed/mineral)
+ blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
+
+///Not exactly mining shelters, but they make use of survival capsules code.
+/datum/map_template/shelter/fishing
+ name = "Freshwater Spring"
+ shelter_id = "fishing_default"
+ description = "A spring from which you can fish several freshwater fish, including goldfish, catfish and pikes."
+ mappath = "_maps/templates/fishing_freshwater.dmm"
+ has_ceiling = FALSE
+ ///The icon shown in the radial menu
+ var/radial_icon = "river"
+ /**
+ * If FALSE, the capsule needs to be emagged for this template to be selectable.
+ * its usage will also be logged, and admins warned if used indoors.
+ */
+ var/safe = TRUE
+
+/datum/map_template/shelter/fishing/New()
+ . = ..()
+ blacklisted_turfs -= typesof(/turf/closed/mineral)
+ blacklisted_turfs += typecacheof(/turf/open/openspace)
+ // Stop the capsule from being used around pipes and cables (if not emagged) cuz it'd look bad and a bit disruptive.
+ banned_objects = typecacheof(list(
+ /obj/structure/disposalpipe,
+ /obj/machinery/atmospherics/pipe,
+ /obj/structure/cable,
+ /obj/structure/transit_tube,
+ ))
+
+/datum/map_template/shelter/fishing/beach
+ name = "Saltwater Spring"
+ shelter_id = "fishing_beach"
+ mappath = "_maps/templates/fishing_saltwater.dmm"
+ description = "A spring from which you can fish several saltwater fish, including clownfish, pufferfish and stingrays."
+ radial_icon = "seaboat"
+
+/datum/map_template/shelter/fishing/tizira
+ name = "Tiziran Spring"
+ shelter_id = "fishing_tizira"
+ mappath = "_maps/templates/fishing_tizira.dmm"
+ description = "A spring from which you can fish several fish native to the lizardfolk's native planet, Tizira."
+ radial_icon = "planet"
+
+/datum/map_template/shelter/fishing/hot_spring
+ name = "Hot Spring"
+ shelter_id = "fishing_hot_spring"
+ mappath = "_maps/templates/fishing_hot_spring.dmm"
+ description = "A hot spring. Its purposes as a fishing spot is limited, but at least you get to have a relaxing bath."
+ radial_icon = "onsen"
+
+/datum/map_template/shelter/fishing/ice
+ name = "Ice Fishing Spot"
+ shelter_id = "fishing_ice"
+ mappath = "_maps/templates/fishing_ice.dmm"
+ description = "A small, already dug ice hole surrounded by snow. You can catch salmon and arctic char here."
+ radial_icon = "ice"
+
+/datum/map_template/shelter/fishing/lava
+ name = "Lava Fishing Spot"
+ shelter_id = "fishing_lava"
+ mappath = "_maps/templates/fishing_lava.dmm"
+ description = "A small 2x2 puddle of not-safe-for-live lava. You can catch lava loops here, and maybe a chest."
+ radial_icon = "lava"
+ safe = FALSE
+
+/datum/map_template/shelter/fishing/plasma
+ name = "Plasma Fishing Spot"
+ shelter_id = "fishing_plasma"
+ mappath = "_maps/templates/fishing_plasma.dmm"
+ description = "A small 2x2 puddle of not-safe-for-live plasma. You can catch lava loops and arctic chrabs here."
+ radial_icon = "plasma"
+ safe = FALSE
diff --git a/icons/effects/particles/smoke.dmi b/icons/effects/particles/smoke.dmi
index 99123beeb59..7e271e51f09 100644
Binary files a/icons/effects/particles/smoke.dmi and b/icons/effects/particles/smoke.dmi differ
diff --git a/icons/hud/radial_fishing.dmi b/icons/hud/radial_fishing.dmi
index d77d9064882..8b914f32613 100644
Binary files a/icons/hud/radial_fishing.dmi and b/icons/hud/radial_fishing.dmi differ
diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi
index e0206b97533..d540a55d344 100644
Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ
diff --git a/icons/obj/aquarium/fish.dmi b/icons/obj/aquarium/fish.dmi
index 5c6a3203dba..53a218bc780 100644
Binary files a/icons/obj/aquarium/fish.dmi and b/icons/obj/aquarium/fish.dmi differ
diff --git a/icons/obj/food/lizard.dmi b/icons/obj/food/lizard.dmi
index 29b35cd8a96..9e60c814a2e 100644
Binary files a/icons/obj/food/lizard.dmi and b/icons/obj/food/lizard.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index 48d01c3371b..5f850703d19 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/turf/beach.dmi b/icons/turf/beach.dmi
index aeb18a4fe61..183ed04f453 100644
Binary files a/icons/turf/beach.dmi and b/icons/turf/beach.dmi differ
diff --git a/icons/turf/decals.dmi b/icons/turf/decals.dmi
index 2c113e27d2c..c5664199ef5 100644
Binary files a/icons/turf/decals.dmi and b/icons/turf/decals.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 09e08985946..ff9d1e62e9b 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 6cb0db19d3c..b56c935d531 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4642,7 +4642,7 @@
#include "code\modules\mapfluff\ruins\generic.dm"
#include "code\modules\mapfluff\ruins\lavaland_ruin_code.dm"
#include "code\modules\mapfluff\ruins\icemoonruin_code\commsagent.dm"
-#include "code\modules\mapfluff\ruins\icemoonruin_code\hotsprings.dm"
+#include "code\modules\mapfluff\ruins\icemoonruin_code\cursed_spring.dm"
#include "code\modules\mapfluff\ruins\icemoonruin_code\lavaland_incursion.dm"
#include "code\modules\mapfluff\ruins\icemoonruin_code\library.dm"
#include "code\modules\mapfluff\ruins\icemoonruin_code\mailroom.dm"
diff --git a/tools/UpdatePaths/Scripts/87639_hot_springs.txt b/tools/UpdatePaths/Scripts/87639_hot_springs.txt
new file mode 100644
index 00000000000..293f0898895
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/87639_hot_springs.txt
@@ -0,0 +1 @@
+/turf/open/water/cursed_spring : /turf/open/water/hot_spring/cursed{@OLD}