From 73081bcff0e3de2b8760cb3d16e4f6510933d8de Mon Sep 17 00:00:00 2001
From: Ghom <42542238+Ghommie@users.noreply.github.com>
Date: Sat, 24 Aug 2024 07:31:38 +0200
Subject: [PATCH] Add messages (paper, photos, cash) in bottles. (#85703)
## About The Pull Request
This PR adds a new persistent feature: message inside bottles. These are
basically glass bottles with inside a piece of paper, a photo or space
cash (no holocredits, and most bills rarely go over 1000 credits anyway)
from a previous round, which can be fished at the beach, or from the
relative fishing portals.
Each piece of written paper or photo that isn't map-loaded has a roughly
a 0.2% chance to be added to the message bottles database at the end of
the round. However, you can also manually toss a glass bottle with
inside a paper/photo/bill into the ocean (or a fishing portal generator
with the ocean/beach module loaded) for guaranteed results.
The bottles are removed from the database once fished up by the by,
unless tossed back into the ocean.
I've also offset a couple bottle sprites that weren't properly aligned
(for the message overlays).
TODO:
- [x] add a couple (20 prob or less) message bottle spawners to the
beach away mission or something.
- [x] add a few sounds for adding and removing the message from the
bottle. (pickup/drop sounds already handle that)
- [x] test it properly.
## Why It's Good For The Game
I think it'd be neat to have a way to send photos, snarky "seek grass"
messages, as well as the occasional financial aid to future players, and
furthermore, another thing to tie fishing to.
## Changelog
:cl:
add: You can place papers, photos and cash bills (no holochips) inside
bottles and then toss them into the ocean (or fishing portal gen with
relative settings) with right-click, for others to fish them up on
future rounds.
/:cl:
---
.../LavaRuins/lavaland_biodome_beach.dmm | 7 +-
_maps/RandomZLevels/TheBeach.dmm | 212 +++++++++++-------
code/__DEFINES/database.dm | 3 +
code/__DEFINES/fish.dm | 1 +
code/__DEFINES/paper.dm | 26 +++
code/__DEFINES/traits/declarations.dm | 2 +
code/_globalvars/traits/_traits.dm | 1 +
.../subsystem/persistence/_persistence.dm | 13 ++
.../subsystem/persistence/message_bottles.dm | 54 +++++
code/datums/components/fishing_spot.dm | 3 +-
code/datums/json_database.dm | 10 +
.../effects/spawners/message_in_a_bottle.dm | 25 +++
code/game/objects/items/food/misc.dm | 8 +
code/game/turfs/open/sand.dm | 4 +
code/game/turfs/open/water.dm | 4 +
code/modules/cargo/order.dm | 6 +-
code/modules/cargo/orderconsole.dm | 2 +-
code/modules/fishing/fishing_minigame.dm | 6 +-
code/modules/fishing/sources/_fish_source.dm | 7 +-
code/modules/fishing/sources/source_types.dm | 23 +-
.../recipes/tablecraft/recipes_drink.dm | 26 ++-
code/modules/paperwork/paper.dm | 84 ++++---
code/modules/photography/photos/photo.dm | 9 +
.../reagent_containers/cups/glassbottle.dm | 134 +++++++++--
icons/effects/random_spawners.dmi | Bin 96755 -> 97084 bytes
icons/hud/fishing_hud.dmi | Bin 4454 -> 4735 bytes
icons/obj/drinks/bottles.dmi | Bin 28099 -> 27819 bytes
tgstation.dme | 2 +
28 files changed, 527 insertions(+), 145 deletions(-)
create mode 100644 code/controllers/subsystem/persistence/message_bottles.dm
create mode 100644 code/game/objects/effects/spawners/message_in_a_bottle.dm
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm
index 82f4d367780..85b662d04aa 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm
@@ -406,6 +406,10 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4,
/turf/open/floor/plating,
/area/ruin/powered/beach)
+"mv" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast,
+/area/ruin/powered/beach)
"mw" = (
/obj/structure/flora/coconuts,
/turf/open/misc/beach/sand,
@@ -985,6 +989,7 @@
dir = 1
},
/obj/machinery/light/directional/south,
+/obj/effect/spawner/message_in_a_bottle/low_prob,
/turf/open/misc/beach/coast/corner{
dir = 8
},
@@ -1990,7 +1995,7 @@ bG
bL
VI
VI
-yT
+mv
pz
Eu
pz
diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm
index 602e11e3f33..ea38a0cc477 100644
--- a/_maps/RandomZLevels/TheBeach.dmm
+++ b/_maps/RandomZLevels/TheBeach.dmm
@@ -92,6 +92,10 @@
/obj/structure/sign/clock/directional/north,
/turf/open/floor/wood,
/area/awaymission/beach)
+"aY" = (
+/obj/item/broken_bottle,
+/turf/open/misc/beach/sand,
+/area/awaymission/beach)
"bg" = (
/obj/structure/no_effect_signpost{
pixel_y = 6;
@@ -174,6 +178,11 @@
/obj/machinery/light/directional/west,
/turf/open/floor/carpet/cyan,
/area/awaymission/beach)
+"cu" = (
+/obj/effect/mob_spawn/corpse/human/old_pirate_captain,
+/obj/structure/bed/maint,
+/turf/open/misc/beach/sand,
+/area/awaymission/beach)
"cv" = (
/obj/structure/table/wood,
/obj/item/food/grown/watermelon{
@@ -207,6 +216,12 @@
dir = 4
},
/area/awaymission/beach)
+"cL" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast{
+ dir = 1
+ },
+/area/awaymission/beach)
"cR" = (
/turf/open/floor/iron/freezer,
/area/awaymission/beach)
@@ -278,16 +293,6 @@
/obj/structure/musician/piano,
/turf/open/floor/wood,
/area/awaymission/beach)
-"dx" = (
-/obj/structure/sign/directions/dorms/north_arrow{
- pixel_y = 35
- },
-/obj/structure/sign/directions/medical/north_arrow{
- pixel_y = 29
- },
-/obj/machinery/computer/slot_machine,
-/turf/open/floor/wood/large,
-/area/awaymission/beach)
"dL" = (
/obj/machinery/door/airlock/public/glass{
name = "Locker Room"
@@ -505,10 +510,6 @@
},
/turf/closed/wall/mineral/wood,
/area/awaymission/beach)
-"gq" = (
-/obj/item/broken_bottle,
-/turf/open/misc/beach/sand,
-/area/awaymission/beach)
"gw" = (
/obj/item/stack/sheet/mineral/sandstone{
pixel_x = -8
@@ -575,6 +576,10 @@
},
/turf/open/floor/wood,
/area/awaymission/beach)
+"hr" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast,
+/area/awaymission/beach)
"hC" = (
/obj/structure/railing{
dir = 8
@@ -898,17 +903,6 @@
/obj/structure/table/wood,
/turf/open/floor/wood/large,
/area/awaymission/beach)
-"lk" = (
-/obj/effect/turf_decal/siding/wood{
- dir = 9
- },
-/obj/effect/turf_decal/tile/dark/half{
- pixel_y = -1;
- pixel_x = 5;
- dir = 8
- },
-/turf/open/water/beach,
-/area/awaymission/beach)
"ll" = (
/obj/machinery/door/airlock/wood{
name = "Room 11";
@@ -1195,10 +1189,6 @@
},
/turf/open/misc/beach/sand,
/area/awaymission/beach)
-"pq" = (
-/obj/effect/spawner/random/trash/cigbutt,
-/turf/open/misc/beach/sand,
-/area/awaymission/beach)
"pr" = (
/obj/item/reagent_containers/cup/soda_cans/space_mountain_wind{
pixel_x = -17;
@@ -1284,6 +1274,11 @@
/obj/structure/sink/kitchen/directional/south,
/turf/open/floor/wood/large,
/area/awaymission/beach)
+"qb" = (
+/obj/structure/closet/crate/bin,
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/floor/wood,
+/area/awaymission/beach)
"qf" = (
/obj/structure/table/bronze,
/obj/item/pai_card{
@@ -1710,6 +1705,12 @@
},
/turf/open/water/beach,
/area/awaymission/beach)
+"vC" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast{
+ dir = 4
+ },
+/area/awaymission/beach)
"vF" = (
/obj/structure/table/bronze,
/obj/structure/sign/poster/random/directional/east,
@@ -1840,6 +1841,18 @@
},
/turf/open/floor/wood/large,
/area/awaymission/beach)
+"xt" = (
+/obj/effect/turf_decal/siding/wood{
+ dir = 9
+ },
+/obj/effect/turf_decal/tile/dark/half{
+ pixel_y = -1;
+ pixel_x = 5;
+ dir = 8
+ },
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/water/beach,
+/area/awaymission/beach)
"xv" = (
/turf/closed/wall/mineral/wood,
/area/awaymission/beach)
@@ -2581,13 +2594,6 @@
},
/turf/open/misc/beach/sand,
/area/awaymission/beach)
-"FJ" = (
-/obj/item/instrument/guitar{
- pixel_y = 4;
- pixel_x = -1
- },
-/turf/open/misc/beach/coast,
-/area/awaymission/beach)
"FK" = (
/obj/item/toy/seashell{
pixel_x = 12;
@@ -2629,6 +2635,17 @@
},
/turf/open/floor/wood/parquet,
/area/awaymission/beach)
+"FX" = (
+/obj/item/paper/fluff/old_pirate_note{
+ pixel_x = -5;
+ pixel_y = -7
+ },
+/obj/item/pen/fountain{
+ pixel_y = -11;
+ pixel_x = -8
+ },
+/turf/open/misc/beach/sand,
+/area/awaymission/beach)
"FY" = (
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/siding/wood/corner{
@@ -2681,6 +2698,12 @@
/obj/machinery/light/directional/north,
/turf/open/floor/wood/large,
/area/awaymission/beach)
+"Gy" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast/corner{
+ dir = 4
+ },
+/area/awaymission/beach)
"GC" = (
/turf/open/floor/carpet,
/area/awaymission/beach)
@@ -2864,17 +2887,6 @@
/obj/machinery/light/directional/west,
/turf/open/floor/wood/large,
/area/awaymission/beach)
-"Jv" = (
-/obj/item/paper/fluff/old_pirate_note{
- pixel_x = -5;
- pixel_y = -7
- },
-/obj/item/pen/fountain{
- pixel_y = -11;
- pixel_x = -8
- },
-/turf/open/misc/beach/sand,
-/area/awaymission/beach)
"JF" = (
/obj/structure/marker_beacon/burgundy,
/turf/open/water/beach,
@@ -3070,6 +3082,14 @@
/obj/machinery/light/directional/north,
/turf/open/floor/wood,
/area/awaymission/beach)
+"LT" = (
+/obj/item/instrument/guitar{
+ pixel_y = 4;
+ pixel_x = -1
+ },
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast,
+/area/awaymission/beach)
"Mm" = (
/obj/structure/table/bronze,
/turf/open/floor/wood/large,
@@ -3349,12 +3369,6 @@
},
/turf/open/misc/beach/sand,
/area/awaymission/beach)
-"Pb" = (
-/obj/item/fishing_rod,
-/obj/structure/closet/crate/trashcart,
-/obj/item/reagent_containers/cup/glass/bottle/rum/aged,
-/turf/open/misc/beach/sand,
-/area/awaymission/beach)
"Pe" = (
/turf/open/misc/beach/coast{
dir = 5
@@ -3403,11 +3417,6 @@
},
/turf/open/misc/beach/sand,
/area/awaymission/beach)
-"PU" = (
-/obj/effect/mob_spawn/corpse/human/old_pirate_captain,
-/obj/structure/bed/maint,
-/turf/open/misc/beach/sand,
-/area/awaymission/beach)
"Qe" = (
/obj/effect/turf_decal/sand,
/obj/machinery/door/airlock/wood{
@@ -3424,6 +3433,10 @@
"Qg" = (
/turf/open/floor/wood/parquet,
/area/awaymission/beach)
+"Qi" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast/corner,
+/area/awaymission/beach)
"Qk" = (
/obj/structure/closet/secure_closet/personal/cabinet,
/obj/item/clothing/suit/jacket/miljacket,
@@ -3550,6 +3563,12 @@
},
/turf/open/floor/wood/large,
/area/awaymission/beach)
+"RH" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/misc/beach/coast/corner{
+ dir = 8
+ },
+/area/awaymission/beach)
"RI" = (
/obj/machinery/door/airlock/medical/glass{
name = "Medbay Clinic"
@@ -3750,6 +3769,10 @@
/obj/machinery/light/directional/east,
/turf/open/floor/wood/large,
/area/awaymission/beach)
+"UV" = (
+/obj/effect/spawner/random/trash/cigbutt,
+/turf/open/misc/beach/sand,
+/area/awaymission/beach)
"UX" = (
/obj/structure/flora/tree/palm/style_2{
pixel_y = 12;
@@ -3897,6 +3920,10 @@
},
/turf/open/misc/beach/sand,
/area/awaymission/beach)
+"WD" = (
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/water/beach,
+/area/awaymission/beach)
"WM" = (
/obj/item/reagent_containers/cup/soda_cans/starkist{
pixel_x = -6
@@ -3911,6 +3938,12 @@
/obj/item/clothing/head/soft/black,
/turf/open/floor/wood/parquet,
/area/awaymission/beach)
+"WU" = (
+/obj/item/fishing_rod,
+/obj/structure/closet/crate/trashcart,
+/obj/item/reagent_containers/cup/glass/bottle/rum/aged,
+/turf/open/misc/beach/sand,
+/area/awaymission/beach)
"Xd" = (
/obj/structure/table/optable,
/turf/open/floor/wood/large,
@@ -3979,6 +4012,11 @@
},
/turf/open/misc/beach/sand,
/area/awaymission/beach)
+"Yp" = (
+/obj/structure/closet/crate/trashcart/filled,
+/obj/effect/spawner/message_in_a_bottle/low_prob,
+/turf/open/floor/wood/large,
+/area/awaymission/beach)
"Yq" = (
/obj/item/reagent_containers/cup/watering_can{
pixel_y = 19;
@@ -4026,6 +4064,16 @@
"Zp" = (
/turf/open/floor/wood/large,
/area/awaymission/beach)
+"Zq" = (
+/obj/structure/sign/directions/dorms/north_arrow{
+ pixel_y = 35
+ },
+/obj/structure/sign/directions/medical/north_arrow{
+ pixel_y = 29
+ },
+/obj/machinery/computer/slot_machine,
+/turf/open/floor/wood/large,
+/area/awaymission/beach)
"Zt" = (
/obj/structure/table/bronze,
/obj/item/storage/toolbox/fishing{
@@ -7443,10 +7491,10 @@ XB
XB
XB
XB
-Vf
+cL
YV
-Pb
-gq
+WU
+aY
hL
ni
XB
@@ -7700,10 +7748,10 @@ XB
XB
XB
XB
-Vf
+cL
VY
-pq
-PU
+UV
+cu
Er
BK
XB
@@ -7959,7 +8007,7 @@ XB
XB
Vf
VY
-Jv
+FX
VY
VY
BK
@@ -8217,7 +8265,7 @@ XB
Vf
IZ
VY
-pq
+UV
VY
BK
XB
@@ -8473,7 +8521,7 @@ XB
XB
Pe
Fb
-tJ
+RH
zr
VY
BK
@@ -11423,7 +11471,7 @@ FM
LJ
Gn
kI
-cp
+qb
xv
Zp
xv
@@ -11441,7 +11489,7 @@ VP
vM
Zt
xv
-MF
+Gy
Wb
It
VY
@@ -12190,7 +12238,7 @@ XB
XB
XB
XB
-XB
+WD
xv
xv
xv
@@ -13240,7 +13288,7 @@ xv
xv
xv
xv
-dx
+Zq
Zp
Zp
mb
@@ -13780,7 +13828,7 @@ hL
Le
Le
Le
-MF
+Gy
VY
VY
VY
@@ -14760,7 +14808,7 @@ XB
XB
HV
mi
-uV
+Yp
xv
eE
un
@@ -15073,7 +15121,7 @@ VY
VY
ls
VY
-BK
+hr
XB
XB
XB
@@ -16314,7 +16362,7 @@ vx
Bq
Xd
Ej
-lk
+xt
LC
XB
XB
@@ -17609,7 +17657,7 @@ xv
xv
xv
xv
-Fb
+vC
mf
VY
KL
@@ -22783,7 +22831,7 @@ VY
EC
VY
VY
-Kh
+Qi
Rj
XB
XB
@@ -25323,7 +25371,7 @@ XB
XB
XB
MZ
-MF
+Gy
VY
xv
xv
@@ -25611,7 +25659,7 @@ VY
VY
Ff
VY
-BK
+hr
XB
XB
XB
@@ -28665,7 +28713,7 @@ XB
XB
XB
XB
-Vf
+cL
wA
VY
xi
@@ -29450,7 +29498,7 @@ VY
VY
Rn
VY
-FJ
+LT
xv
CG
Gh
@@ -29696,7 +29744,7 @@ XB
XB
XB
XB
-Vf
+cL
VY
VY
IZ
diff --git a/code/__DEFINES/database.dm b/code/__DEFINES/database.dm
index 3d20b3b9a3c..22351b5052d 100644
--- a/code/__DEFINES/database.dm
+++ b/code/__DEFINES/database.dm
@@ -4,3 +4,6 @@
#define DB_QUERY_FINISHED 1
/// When there was a problem with the execution of a query.
#define DB_QUERY_BROKEN 2
+
+///The probability of non-maploaded photos and papers being saved as bottle messages at the end of the round.
+#define MESSAGE_BOTTLE_CHANCE 0.2
diff --git a/code/__DEFINES/fish.dm b/code/__DEFINES/fish.dm
index ec991b713ec..d6bcc2ec796 100644
--- a/code/__DEFINES/fish.dm
+++ b/code/__DEFINES/fish.dm
@@ -86,6 +86,7 @@
#define FISH_ICON_GEM "gem"
#define FISH_ICON_CRAB "crab"
#define FISH_ICON_JELLYFISH "jellyfish"
+#define FISH_ICON_BOTTLE "bottle"
#define FISH_ICON_BONE "bone"
#define FISH_ICON_ELECTRIC "electric"
#define FISH_ICON_WEAPON "weapon"
diff --git a/code/__DEFINES/paper.dm b/code/__DEFINES/paper.dm
index 0d70a2f3ca4..9cede4214bd 100644
--- a/code/__DEFINES/paper.dm
+++ b/code/__DEFINES/paper.dm
@@ -18,3 +18,29 @@
#define BARCODE_SCANNER_INVENTORY "inventory"
#define IS_WRITING_UTENSIL(thing) (thing?.get_writing_implement_details()?["interaction_mode"] == MODE_WRITING)
+
+/**
+ * key defines used when converting a paper to and fro' a data/json list. It's really important that they stay the same
+ * lest we break persistence.
+ */
+#define LIST_PAPER_COLOR "paper_color"
+#define LIST_PAPER_NAME "paper_name"
+
+#define LIST_PAPER_RAW_TEXT_INPUT "raw_text_input"
+#define LIST_PAPER_RAW_FIELD_INPUT "raw_field_input"
+#define LIST_PAPER_RAW_STAMP_INPUT "raw_stamp_input"
+
+#define LIST_PAPER_RAW_TEXT "raw_text"
+#define LIST_PAPER_FONT "font"
+#define LIST_PAPER_FIELD_COLOR "color"
+#define LIST_PAPER_BOLD "bold"
+#define LIST_PAPER_ADVANCED_HTML "advanced_html"
+
+#define LIST_PAPER_FIELD_INDEX "field_index"
+#define LIST_PAPER_FIELD_DATA "field_data"
+#define LIST_PAPER_IS_SIGNATURE "is_signature"
+
+#define LIST_PAPER_CLASS "class"
+#define LIST_PAPER_STAMP_X "x"
+#define LIST_PAPER_STAMP_Y "y"
+#define LIST_PAPER_ROTATION "rotation"
diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index eee89e7d3ca..c82b54491eb 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -233,6 +233,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_FISHING_SPOT "fishing_spot"
///Trait given to mobs that can fish without a rod
#define TRAIT_PROFOUND_FISHER "profound_fisher"
+/// If an atom has this trait, then you can toss a bottle with a message in it.
+#define TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION "message_in_a_bottle_location"
/// This trait lets you evaluate someone's fitness level against your own
#define TRAIT_EXAMINE_FITNESS "reveal_power_level"
/// These mobs have particularly hygienic tongues
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 2cf71438e82..6bf5bba956c 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -23,6 +23,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_FOOD_SILVER" = TRAIT_FOOD_SILVER,
"TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER,
"TRAIT_LIGHTING_DEBUGGED" = TRAIT_LIGHTING_DEBUGGED,
+ "TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION" = TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION,
"TRAIT_RECENTLY_COINED" = TRAIT_RECENTLY_COINED,
"TRAIT_RUSTY" = TRAIT_RUSTY,
"TRAIT_SPINNING" = TRAIT_SPINNING,
diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm
index a8c42631488..6438015d11d 100644
--- a/code/controllers/subsystem/persistence/_persistence.dm
+++ b/code/controllers/subsystem/persistence/_persistence.dm
@@ -48,6 +48,17 @@ SUBSYSTEM_DEF(persistence)
var/tram_hits_this_round = 0
var/tram_hits_last_round = 0
+ /// A json database to data/message_bottles.json
+ var/datum/json_database/message_bottles_database
+ /// An index used to create unique ids for the message bottles database
+ var/message_bottles_index = 0
+ /**
+ * A list of non-maploaded photos or papers that met the 0.2% chance to be saved in the message bottles database
+ * because I don't want the database to feel empty unless there's someone constantly throwing bottles in the
+ * sea or beach/ocean fishing portals.
+ */
+ var/list/queued_message_bottles
+
/datum/controller/subsystem/persistence/Initialize()
load_poly()
load_wall_engravings()
@@ -72,11 +83,13 @@ SUBSYSTEM_DEF(persistence)
save_scars()
save_custom_outfits()
save_delamination_counter()
+ save_queued_message_bottles()
if(SStransport.can_fire)
for(var/datum/transport_controller/linear/tram/transport as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
save_tram_history(transport.specific_transport_id)
save_tram_counter()
+
///Loads up Poly's speech buffer.
/datum/controller/subsystem/persistence/proc/load_poly()
for(var/mob/living/basic/parrot/poly/bird in GLOB.alive_mob_list)
diff --git a/code/controllers/subsystem/persistence/message_bottles.dm b/code/controllers/subsystem/persistence/message_bottles.dm
new file mode 100644
index 00000000000..ce1efe5e59c
--- /dev/null
+++ b/code/controllers/subsystem/persistence/message_bottles.dm
@@ -0,0 +1,54 @@
+///This proc is used to save photos, papers and cash stored inside a bottle when tossed into the ocean.
+/datum/controller/subsystem/persistence/proc/save_message_bottle(obj/item/message, bottle_type = /obj/item/reagent_containers/cup/glass/bottle)
+ if(isnull(message_bottles_database))
+ message_bottles_database = new("data/message_bottles.json")
+
+ var/list/data = list()
+ data["bottle_type"] = text2path(bottle_type)
+ if(istype(message, /obj/item/paper))
+ var/obj/item/paper/paper = message
+ if(!length(paper.raw_text_inputs) && !length(paper.raw_stamp_data) && !length(paper.raw_field_input_data))
+ return
+ data["paper"] = paper.convert_to_data()
+ else if(istype(message, /obj/item/photo))
+ var/obj/item/photo/photo = message
+ if(!photo.picture?.id)
+ return
+ data["photo_id"] = photo.picture.id
+ else if(istype(message, /obj/item/stack/spacecash))
+ var/obj/item/stack/spacecash/cash = message
+ data["cash"] = text2path(cash.type)
+ data["amount"] = cash.amount
+ message_bottles_index++
+ message_bottles_database.set_key("message-[GLOB.round_id]-[message_bottles_index]", data)
+
+/datum/controller/subsystem/persistence/proc/load_message_bottle(atom/loc)
+ if(isnull(message_bottles_database))
+ message_bottles_database = new("data/message_bottles.json")
+
+ var/list/data = message_bottles_database.pick_and_take_key()
+ if(!data)
+ var/obj/item/reagent_containers/cup/glass/bottle/bottle = new(loc)
+ return bottle
+
+ var/bottle_type = text2path(data["bottle_type"]) || /obj/item/reagent_containers/cup/glass/bottle
+ var/obj/item/reagent_containers/cup/glass/bottle/bottle = new bottle_type(loc)
+ bottle.reagents.remove_all(bottle.reagents.maximum_volume)
+ if(data["photo_id"])
+ var/obj/item/photo/old/photo = load_photo_from_disk(data["photo_id"], bottle)
+ bottle.message_in_a_bottle = photo
+ else if(data["cash"])
+ var/cash_type = text2path(data["cash"]) || /obj/item/stack/spacecash/c10
+ var/obj/item/stack/spacecash/cash = new cash_type(bottle, data["amount"])
+ bottle.message_in_a_bottle = cash
+ else if(data["paper"])
+ var/obj/item/paper/paper = new(bottle)
+ paper.write_from_data(data["paper"])
+ bottle.message_in_a_bottle = paper
+
+ bottle.update_icon(UPDATE_OVERLAYS)
+
+/datum/controller/subsystem/persistence/proc/save_queued_message_bottles()
+ for(var/item in queued_message_bottles)
+ save_message_bottle(item)
+ queued_message_bottles = null
diff --git a/code/datums/components/fishing_spot.dm b/code/datums/components/fishing_spot.dm
index 6638c822ff6..cc21f22eb4b 100644
--- a/code/datums/components/fishing_spot.dm
+++ b/code/datums/components/fishing_spot.dm
@@ -12,7 +12,7 @@
fish_source = configuration
else
return COMPONENT_INCOMPATIBLE
- fish_source.on_fishing_spot_init()
+ fish_source.on_fishing_spot_init(src)
RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(handle_attackby))
RegisterSignal(parent, COMSIG_FISHING_ROD_CAST, PROC_REF(handle_cast))
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined))
@@ -22,6 +22,7 @@
ADD_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src))
/datum/component/fishing_spot/Destroy()
+ fish_source.on_fishing_spot_del(src)
fish_source = null
return ..()
diff --git a/code/datums/json_database.dm b/code/datums/json_database.dm
index ea3ff354b48..6baeb44ab09 100644
--- a/code/datums/json_database.dm
+++ b/code/datums/json_database.dm
@@ -61,6 +61,16 @@
/datum/json_database/proc/get_key(key)
return cached_data[key]
+/// Picks the data of a random key and then removes that key from the database.
+/// Since the list is no longer inside the database, you can mutate and use it as you like.
+/datum/json_database/proc/pick_and_take_key()
+ if(!length(cached_data))
+ return null
+ var/key = pick(cached_data)
+ . = cached_data[key]
+ cached_data -= key
+ queue_save()
+
/// Sets the data at the key to the value, and queues a save.
/datum/json_database/proc/set_key(key, value)
cached_data[key] = value
diff --git a/code/game/objects/effects/spawners/message_in_a_bottle.dm b/code/game/objects/effects/spawners/message_in_a_bottle.dm
new file mode 100644
index 00000000000..c4ac63ad0be
--- /dev/null
+++ b/code/game/objects/effects/spawners/message_in_a_bottle.dm
@@ -0,0 +1,25 @@
+/obj/effect/spawner/message_in_a_bottle
+ name = "message in a bottle"
+ desc = "Sending out an SOS"
+ icon = 'icons/effects/random_spawners.dmi'
+ icon_state = "message_bottle"
+ var/probability = 100
+
+/obj/effect/spawner/message_in_a_bottle/Initialize(mapload)
+ . = ..()
+ if(!prob(probability))
+ return INITIALIZE_HINT_QDEL
+ if(!SSpersistence.initialized)
+ RegisterSignal(SSpersistence, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(on_persistence_init))
+ else
+ SSpersistence.load_message_bottle(loc)
+ return INITIALIZE_HINT_QDEL
+
+/obj/effect/spawner/message_in_a_bottle/proc/on_persistence_init(datum/source)
+ SIGNAL_HANDLER
+ UnregisterSignal(SSpersistence, COMSIG_SUBSYSTEM_POST_INITIALIZE)
+ SSpersistence.load_message_bottle(loc)
+ qdel(src)
+
+/obj/effect/spawner/message_in_a_bottle/low_prob
+ probability = 1.5
diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm
index 26852066bae..53781e8a1ea 100644
--- a/code/game/objects/items/food/misc.dm
+++ b/code/game/objects/items/food/misc.dm
@@ -292,6 +292,14 @@
foodtypes = FRUIT | ALCOHOL
crafting_complexity = FOOD_COMPLEXITY_2
+/obj/item/food/melonkeg/CheckParts(list/parts_list)
+ . = ..()
+ var/obj/item/reagent_containers/cup/glass/bottle/bottle = locate() in contents
+ if(!bottle)
+ return
+ if(bottle.message_in_a_bottle)
+ bottle.message_in_a_bottle.forceMove(drop_location())
+
/obj/item/food/honeybar
name = "honey nut bar"
desc = "Oats and nuts compressed together into a bar, held together with a honey glaze."
diff --git a/code/game/turfs/open/sand.dm b/code/game/turfs/open/sand.dm
index fb10d297e18..254c595fcbd 100644
--- a/code/game/turfs/open/sand.dm
+++ b/code/game/turfs/open/sand.dm
@@ -41,6 +41,10 @@
clawfootstep = FOOTSTEP_WATER
heavyfootstep = FOOTSTEP_WATER
+/turf/open/misc/beach/coast/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION, INNATE_TRAIT)
+
/turf/open/misc/beach/coast/break_tile()
. = ..()
icon_state = "beach"
diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm
index 20c6215209a..de895754d03 100644
--- a/code/game/turfs/open/water.dm
+++ b/code/game/turfs/open/water.dm
@@ -43,6 +43,10 @@
immerse_overlay_color = "#7799AA"
fishing_datum = /datum/fish_source/ocean/beach
+/turf/open/water/beach/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION, INNATE_TRAIT)
+
/turf/open/water/lavaland_atmos
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
planetary_atmos = TRUE
diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm
index c675352d024..a10bb3da5c0 100644
--- a/code/modules/cargo/order.dm
+++ b/code/modules/cargo/order.dm
@@ -10,10 +10,14 @@
#define MANIFEST_ERROR_ITEM (1 << 2)
/obj/item/paper/fluff/jobs/cargo/manifest
+ can_become_message_in_bottle = FALSE //A lot of these are spawned each round, they'd only dilute the pool and make it boring.
var/order_cost = 0
var/order_id = 0
var/errors = 0
+/obj/item/paper/requisition
+ can_become_message_in_bottle = FALSE //A lot of these are spawned each round, they'd only dilute the pool and make it boring.
+
/obj/item/paper/fluff/jobs/cargo/manifest/Initialize(mapload, id, cost, manifest_can_fail = TRUE)
. = ..()
order_id = id
@@ -99,7 +103,7 @@
return round(cost)
/datum/supply_order/proc/generateRequisition(turf/T)
- var/obj/item/paper/requisition_paper = new(T)
+ var/obj/item/paper/requisition/requisition_paper = new(T)
requisition_paper.name = "requisition form - #[id] ([pack.name])"
var/requisition_text = "
[station_name()] Supply Requisition
"
diff --git a/code/modules/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm
index d835c52f1e8..ae46d994381 100644
--- a/code/modules/cargo/orderconsole.dm
+++ b/code/modules/cargo/orderconsole.dm
@@ -329,7 +329,7 @@
else
//create the paper from the SSshuttle.shopping_list
if(length(SSshuttle.shopping_list))
- var/obj/item/paper/requisition_paper = new(get_turf(src))
+ var/obj/item/paper/requisition/requisition_paper = new(get_turf(src))
requisition_paper.name = "requisition form - [station_time_timestamp()]"
var/requisition_text = "[station_name()] Supply Requisition
"
requisition_text += "
"
diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm
index 93a86ff82a9..5db1ee6458b 100644
--- a/code/modules/fishing/fishing_minigame.dm
+++ b/code/modules/fishing/fishing_minigame.dm
@@ -62,7 +62,7 @@
/// Background icon state from fishing_hud.dmi
var/background = "background_default"
/// Fish icon state from fishing_hud.dmi
- var/fish_icon = "fish"
+ var/fish_icon = FISH_ICON_DEF
/// Fishing line visual
var/datum/beam/fishing_line
@@ -164,7 +164,7 @@
completion -= MAX_FISH_COMPLETION_MALUS * (difficulty * 0.01)
if(HAS_MIND_TRAIT(user, TRAIT_REVEAL_FISH))
- fish_icon = GLOB.specific_fish_icons[reward_path] || "fish"
+ fish_icon = GLOB.specific_fish_icons[reward_path] || FISH_ICON_DEF
mover.adjust_to_difficulty()
@@ -352,6 +352,8 @@
send_alert("critter!!!")
if(FISH_ICON_SEED)
send_alert("seed!!!")
+ if(FISH_ICON_BOTTLE)
+ send_alert("bottle!!!")
else
send_alert("!!!")
animate(lure, pixel_y = 3, time = 5, loop = -1, flags = ANIMATION_RELATIVE)
diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm
index dc9b910ad8f..5aa03ae8c0c 100644
--- a/code/modules/fishing/sources/_fish_source.dm
+++ b/code/modules/fishing/sources/_fish_source.dm
@@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/mob/living/basic/mining = FISH_ICON_HOSTILE,
/obj/effect/decal/remains = FISH_ICON_BONE,
/obj/effect/mob_spawn/corpse = FISH_ICON_BONE,
+ /obj/effect/spawner/message_in_a_bottle = FISH_ICON_BOTTLE,
/obj/item/coin = FISH_ICON_COIN,
/obj/item/fish = FISH_ICON_DEF,
/obj/item/fish/armorfish = FISH_ICON_CRAB,
@@ -46,6 +47,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/obj/item/stack/sheet/mineral = FISH_ICON_GEM,
/obj/item/stack/ore = FISH_ICON_GEM,
/obj/structure/closet/crate = FISH_ICON_COIN,
+ /obj/structure/mystery_box = FISH_ICON_COIN,
))
return_list[FISHING_RANDOM_SEED] = FISH_ICON_SEED
@@ -97,9 +99,12 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
return ..()
///Called when src is set as the fish source of a fishing spot component
-/datum/fish_source/proc/on_fishing_spot_init(/datum/component/fishing_spot/spot)
+/datum/fish_source/proc/on_fishing_spot_init(datum/component/fishing_spot/spot)
return
+///Called whenever a fishing spot with this fish source attached is deleted
+/datum/fish_source/proc/on_fishing_spot_del(datum/component/fishing_spot/spot)
+
/// Can we fish in this spot at all. Returns DENIAL_REASON or null if we're good to go
/datum/fish_source/proc/reason_we_cant_fish(obj/item/fishing_rod/rod, mob/fisherman, atom/parent)
return rod.reason_we_cant_fish(src)
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index 5b4b6fe3624..6a7c8d3e1ef 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -1,6 +1,7 @@
/datum/fish_source/ocean
fish_table = list(
- FISHING_DUD = 15,
+ FISHING_DUD = 11,
+ /obj/effect/spawner/message_in_a_bottle = 4,
/obj/item/coin/gold = 7,
/obj/item/fish/clownfish = 15,
/obj/item/fish/pufferfish = 15,
@@ -11,7 +12,7 @@
/obj/item/fish/zipzap = 7,
/obj/item/fish/clownfish/lube = 5,
/obj/item/fish/swordfish = 5,
- /obj/structure/mystery_box/fishing = 1,
+ /obj/structure/mystery_box/fishing = 2,
)
fish_counts = list(
/obj/item/fish/clownfish/lube = 2,
@@ -96,7 +97,8 @@
/datum/fish_source/portal/beach
fish_table = list(
- FISHING_DUD = 10,
+ FISHING_DUD = 7,
+ /obj/effect/spawner/message_in_a_bottle = 3,
/obj/item/fish/clownfish = 10,
/obj/item/fish/pufferfish = 10,
/obj/item/fish/cardinal = 10,
@@ -107,6 +109,12 @@
radial_state = "palm_beach"
overlay_state = "portal_beach"
+/datum/fish_source/portal/beach/on_fishing_spot_init(datum/component/fishing_spot/spot)
+ ADD_TRAIT(spot.parent, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION, INNATE_TRAIT)
+
+/datum/fish_source/portal/beach/on_fishing_spot_del(datum/component/fishing_spot/spot)
+ REMOVE_TRAIT(spot.parent, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION, INNATE_TRAIT)
+
/datum/fish_source/portal/chasm
background = "background_lavaland"
fish_table = list(
@@ -123,7 +131,8 @@
/datum/fish_source/portal/ocean
fish_table = list(
- FISHING_DUD = 5,
+ FISHING_DUD = 3,
+ /obj/effect/spawner/message_in_a_bottle = 2,
/obj/item/fish/lanternfish = 5,
/obj/item/fish/firefish = 5,
/obj/item/fish/dwarf_moonfish = 5,
@@ -146,6 +155,12 @@
overlay_state = "portal_ocean"
radial_state = "seaboat"
+/datum/fish_source/portal/ocean/on_fishing_spot_init(datum/component/fishing_spot/spot)
+ ADD_TRAIT(spot.parent, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION, INNATE_TRAIT)
+
+/datum/fish_source/portal/ocean/on_fishing_spot_del(datum/component/fishing_spot/spot)
+ REMOVE_TRAIT(spot.parent, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION, INNATE_TRAIT)
+
/datum/fish_source/portal/hyperspace
fish_table = list(
FISHING_DUD = 5,
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm
index e5589fcc42d..5a754361ffb 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm
@@ -1,6 +1,10 @@
// This is the home of drink related tablecrafting recipes, I have opted to only let players bottle fancy boozes to reduce the number of entries.
+///Abstract types for all drink recipes that use bottles and result in another bottle, so that the message_in_a_bottle item is properly transferred.
+/datum/crafting_recipe/bottled
+ parts = list(/obj/item/reagent_containers/cup/glass/bottle = 1)
+
///////////////// Booze & Bottles ///////////////////
/datum/crafting_recipe/lizardwine
@@ -14,7 +18,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/lizardwine
category = CAT_DRINK
-/datum/crafting_recipe/moonshinejug
+/datum/crafting_recipe/bottled/moonshinejug
name = "Moonshine Jug"
time = 30
reqs = list(
@@ -24,7 +28,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/moonshine
category = CAT_DRINK
-/datum/crafting_recipe/hoochbottle
+/datum/crafting_recipe/bottled/hoochbottle
name = "Hooch Bottle"
time = 30
reqs = list(
@@ -35,7 +39,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/hooch
category = CAT_DRINK
-/datum/crafting_recipe/blazaambottle
+/datum/crafting_recipe/bottled/blazaambottle
name = "Blazaam Bottle"
time = 20
reqs = list(
@@ -45,7 +49,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/blazaam
category = CAT_DRINK
-/datum/crafting_recipe/champagnebottle
+/datum/crafting_recipe/bottled/champagnebottle
name = "Champagne Bottle"
time = 30
reqs = list(
@@ -55,7 +59,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/champagne
category = CAT_DRINK
-/datum/crafting_recipe/trappistbottle
+/datum/crafting_recipe/bottled/trappistbottle
name = "Trappist Bottle"
time = 15
reqs = list(
@@ -65,7 +69,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/trappist
category = CAT_DRINK
-/datum/crafting_recipe/goldschlagerbottle
+/datum/crafting_recipe/bottled/goldschlagerbottle
name = "Goldschlager Bottle"
time = 30
reqs = list(
@@ -75,7 +79,7 @@
result = /obj/item/reagent_containers/cup/glass/bottle/goldschlager
category = CAT_DRINK
-/datum/crafting_recipe/patronbottle
+/datum/crafting_recipe/bottled/patronbottle
name = "Patron Bottle"
time = 30
reqs = list(
@@ -87,7 +91,7 @@
////////////////////// Non-alcoholic recipes ///////////////////
-/datum/crafting_recipe/holybottle
+/datum/crafting_recipe/bottled/holybottle
name = "Holy Water Flask"
time = 30
reqs = list(
@@ -99,7 +103,7 @@
//flask of unholy water is a beaker for some reason, I will try making it a bottle and add it here once the antag freeze is over. t. kryson
-/datum/crafting_recipe/nothingbottle
+/datum/crafting_recipe/bottled/nothingbottle
name = "Nothing Bottle"
time = 30
reqs = list(
@@ -116,7 +120,7 @@
reqs = list(/obj/item/stack/sheet/cardboard = 1)
category = CAT_CONTAINERS
-/datum/crafting_recipe/candycornliquor
+/datum/crafting_recipe/bottled/candycornliquor
name = "candy corn liquor"
result = /obj/item/reagent_containers/cup/glass/bottle/candycornliquor
time = 30
@@ -125,7 +129,7 @@
/obj/item/reagent_containers/cup/glass/bottle = 1)
category = CAT_DRINK
-/datum/crafting_recipe/kong
+/datum/crafting_recipe/bottled/kong
name = "Kong"
result = /obj/item/reagent_containers/cup/glass/bottle/kong
time = 30
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index fe2de7e7520..403d6d269ed 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -64,6 +64,9 @@
///If TRUE, staff can read paper everywhere, but usually from requests panel.
var/request_state = FALSE
+ ///If this paper can be selected as a candidate for a future message in a bottle when spawned outside of mapload. Doesn't affect manually doing that.
+ var/can_become_message_in_bottle = TRUE
+
/obj/item/paper/Initialize(mapload)
. = ..()
pixel_x = base_pixel_x + rand(-9, 9)
@@ -74,10 +77,14 @@
update_appearance()
+ if(can_become_message_in_bottle && !mapload && prob(MESSAGE_BOTTLE_CHANCE))
+ LAZYADD(SSpersistence.queued_message_bottles, src)
+
/obj/item/paper/Destroy()
- . = ..()
camera_holder = null
clear_paper()
+ LAZYREMOVE(SSpersistence.queued_message_bottles, src)
+ return ..()
/// Determines whether this paper has been written or stamped to.
/obj/item/paper/proc/is_empty()
@@ -527,22 +534,10 @@
static_data["user_name"] = user.real_name
- static_data["raw_text_input"] = list()
- for(var/datum/paper_input/text_input as anything in raw_text_inputs)
- static_data["raw_text_input"] += list(text_input.to_list())
-
- static_data["raw_field_input"] = list()
- for(var/datum/paper_field/field_input as anything in raw_field_input_data)
- static_data["raw_field_input"] += list(field_input.to_list())
-
- static_data["raw_stamp_input"] = list()
- for(var/datum/paper_stamp/stamp_input as anything in raw_stamp_data)
- static_data["raw_stamp_input"] += list(stamp_input.to_list())
+ static_data += convert_to_data()
static_data["max_length"] = MAX_PAPER_LENGTH
static_data["max_input_field_length"] = MAX_PAPER_INPUT_FIELD_LENGTH
- static_data["paper_color"] = color ? color : COLOR_WHITE
- static_data["paper_name"] = name
static_data["default_pen_font"] = PEN_FONT
static_data["default_pen_color"] = COLOR_BLACK
@@ -550,6 +545,43 @@
return static_data;
+/obj/item/paper/proc/convert_to_data()
+ var/list/data = list()
+
+ data[LIST_PAPER_RAW_TEXT_INPUT] = list()
+ for(var/datum/paper_input/text_input as anything in raw_text_inputs)
+ data[LIST_PAPER_RAW_TEXT_INPUT] += list(text_input.to_list())
+
+ data[LIST_PAPER_RAW_FIELD_INPUT] = list()
+ for(var/datum/paper_field/field_input as anything in raw_field_input_data)
+ data[LIST_PAPER_RAW_FIELD_INPUT] += list(field_input.to_list())
+
+ data[LIST_PAPER_RAW_STAMP_INPUT] = list()
+ for(var/datum/paper_stamp/stamp_input as anything in raw_stamp_data)
+ data[LIST_PAPER_RAW_STAMP_INPUT] += list(stamp_input.to_list())
+
+ data[LIST_PAPER_COLOR] = color ? color : COLOR_WHITE
+ data[LIST_PAPER_NAME] = name
+
+ return data
+
+/obj/item/paper/proc/write_from_data(list/data)
+ for(var/list/input as anything in data[LIST_PAPER_RAW_TEXT_INPUT])
+ add_raw_text(input[LIST_PAPER_RAW_TEXT], input[LIST_PAPER_FONT], input[LIST_PAPER_FIELD_COLOR], input[LIST_PAPER_BOLD], input[LIST_PAPER_ADVANCED_HTML])
+
+ for(var/list/field as anything in data[LIST_PAPER_RAW_FIELD_INPUT])
+ var/list/input = field[LIST_PAPER_FIELD_DATA]
+ add_field_input(field[LIST_PAPER_FIELD_INDEX], input[LIST_PAPER_RAW_TEXT], input[LIST_PAPER_FONT], input[LIST_PAPER_FIELD_COLOR], input[LIST_PAPER_BOLD], field[LIST_PAPER_IS_SIGNATURE])
+
+ for(var/list/stamp as anything in data[LIST_PAPER_RAW_STAMP_INPUT])
+ add_stamp(stamp[LIST_PAPER_CLASS], stamp[LIST_PAPER_STAMP_X], stamp[LIST_PAPER_STAMP_Y], stamp[LIST_PAPER_ROTATION])
+
+ var/new_color = data[LIST_PAPER_COLOR]
+ if(new_color != COLOR_WHITE)
+ add_atom_colour(new_color, FIXED_COLOUR_PRIORITY)
+
+ name = data[LIST_PAPER_NAME]
+
/obj/item/paper/ui_data(mob/user)
var/list/data = list()
@@ -753,11 +785,11 @@
/datum/paper_input/proc/to_list()
return list(
- raw_text = raw_text,
- font = font,
- color = colour,
- bold = bold,
- advanced_html = advanced_html,
+ LIST_PAPER_RAW_TEXT = raw_text,
+ LIST_PAPER_FONT = font,
+ LIST_PAPER_FIELD_COLOR = colour,
+ LIST_PAPER_BOLD = bold,
+ LIST_PAPER_ADVANCED_HTML = advanced_html,
)
/// Returns the raw contents of the input as html, with **ZERO SANITIZATION**
@@ -793,10 +825,10 @@
/datum/paper_stamp/proc/to_list()
return list(
- class = class,
- x = stamp_x,
- y = stamp_y,
- rotation = rotation,
+ LIST_PAPER_CLASS = class,
+ LIST_PAPER_STAMP_X = stamp_x,
+ LIST_PAPER_STAMP_Y = stamp_y,
+ LIST_PAPER_ROTATION = rotation,
)
/// A reference to some data that replaces a modifiable input field at some given index in paper raw input parsing.
@@ -818,9 +850,9 @@
/datum/paper_field/proc/to_list()
return list(
- field_index = field_index,
- field_data = field_data.to_list(),
- is_signature = is_signature,
+ LIST_PAPER_FIELD_INDEX = field_index,
+ LIST_PAPER_FIELD_DATA = field_data.to_list(),
+ LIST_PAPER_IS_SIGNATURE = is_signature,
)
/obj/item/paper/construction
diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm
index b009c5b2e79..adc99a08cf2 100644
--- a/code/modules/photography/photos/photo.dm
+++ b/code/modules/photography/photos/photo.dm
@@ -9,12 +9,21 @@
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
max_integrity = 50
+ drop_sound = 'sound/items/handling/paper_drop.ogg'
+ pickup_sound = 'sound/items/handling/paper_pickup.ogg'
grind_results = list(/datum/reagent/iodine = 4)
var/datum/picture/picture
var/scribble //Scribble on the back.
/obj/item/photo/Initialize(mapload, datum/picture/P, datum_name = TRUE, datum_desc = TRUE)
set_picture(P, datum_name, datum_desc, TRUE)
+ //Photos are quite rarer than papers, so they're more likely to be added to the queue to make things even.
+ if(!mapload && prob(MESSAGE_BOTTLE_CHANCE * 5) && picture?.id)
+ LAZYADD(SSpersistence.queued_message_bottles, src)
+ return ..()
+
+/obj/item/photo/Destroy()
+ LAZYREMOVE(SSpersistence.queued_message_bottles, src)
return ..()
/obj/item/photo/proc/set_picture(datum/picture/P, setname, setdesc, name_override = FALSE)
diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm
index 7b2183b1f22..a214ea47eb1 100644
--- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm
+++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm
@@ -39,11 +39,93 @@
var/bottle_knockdown_duration = BOTTLE_KNOCKDOWN_DEFAULT_DURATION
tool_behaviour = TOOL_ROLLINGPIN // Used to knock out the Chef.
toolspeed = 1.3 //it's a little awkward to use, but it's a cylinder alright.
+ /// A contained piece of paper, a photo, or space cash, that we can use as a message or gift to future spessmen.
+ var/obj/item/message_in_a_bottle
/obj/item/reagent_containers/cup/glass/bottle/Initialize(mapload, vol)
. = ..()
var/static/list/recipes = list(/datum/crafting_recipe/molotov)
AddElement(/datum/element/slapcrafting, recipes)
+ register_context()
+ register_item_context()
+
+/obj/item/reagent_containers/cup/glass/bottle/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+ if(message_in_a_bottle)
+ return NONE
+ if(istype(held_item, /obj/item/paper) || istype(held_item, /obj/item/stack/spacecash) || istype(held_item, /obj/item/photo))
+ context[SCREENTIP_CONTEXT_LMB] = "Insert message"
+ return CONTEXTUAL_SCREENTIP_SET
+ return NONE
+
+/obj/item/reagent_containers/cup/glass/bottle/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
+ if(message_in_a_bottle && HAS_TRAIT(target, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION))
+ context[SCREENTIP_CONTEXT_RMB] = "Toss message"
+ return CONTEXTUAL_SCREENTIP_SET
+ return NONE
+
+/obj/item/reagent_containers/cup/glass/bottle/Exited(atom/movable/gone, atom/newloc)
+ if(gone == message_in_a_bottle)
+ message_in_a_bottle = null
+ if(!QDELETED(src))
+ update_icon(UPDATE_OVERLAYS)
+ return ..()
+
+/obj/item/reagent_containers/cup/glass/bottle/CheckParts(list/parts_list)
+ . = ..()
+ var/obj/item/reagent_containers/cup/glass/bottle/bottle = locate() in contents
+ if(bottle.message_in_a_bottle)
+ message_in_a_bottle = bottle.message_in_a_bottle
+ bottle.message_in_a_bottle.forceMove(src)
+
+/obj/item/reagent_containers/cup/glass/bottle/examine(mob/user)
+ . = ..()
+ if(message_in_a_bottle)
+ . += span_info("there's \a [message_in_a_bottle] inside it. Break it to take it out, or find a beach or ocean and toss it with [EXAMINE_HINT("right-click")].")
+ else if(isGlass)
+ . += span_tinynoticeital("you could place a paper, photo or space cash inside it...")
+
+/obj/item/reagent_containers/cup/glass/bottle/update_overlays()
+ . = ..()
+ if(message_in_a_bottle)
+ var/overlay = add_message_overlay()
+ if(overlay)
+ . += overlay
+
+/obj/item/reagent_containers/cup/glass/bottle/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers)
+ if(user.combat_mode || !HAS_TRAIT(target, TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION))
+ return ..()
+ if(!user.temporarilyRemoveItemFromInventory(src))
+ balloon_alert(user, "it's stuck to your hand!")
+ return ITEM_INTERACT_BLOCKING
+ user.visible_message(span_notice("[user] tosses [src] in [target]"), span_notice("You toss [src] in [target]"), span_notice("you hear a splash."))
+ SSpersistence.save_message_bottle(message_in_a_bottle, type)
+ playsound(target, 'sound/effects/bigsplash.ogg', 70)
+ qdel(src)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/reagent_containers/cup/glass/bottle/item_interaction(mob/living/user, obj/item/item, list/modifiers)
+ if(!isGlass)
+ return NONE
+ if(!istype(item, /obj/item/paper) && !istype(item, /obj/item/stack/spacecash) && !istype(item, /obj/item/photo))
+ return NONE
+ if(message_in_a_bottle)
+ balloon_alert(user, "has a message already!")
+ return ITEM_INTERACT_BLOCKING
+ if(!user.transferItemToLoc(item, src))
+ balloon_alert(user, "it's stuck to your hand!")
+ return ITEM_INTERACT_BLOCKING
+ balloon_alert(user, "message inserted")
+ message_in_a_bottle = item
+ update_icon(UPDATE_OVERLAYS)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/reagent_containers/cup/glass/bottle/proc/add_message_overlay()
+ if(istype(message_in_a_bottle, /obj/item/paper))
+ return "paper_in_bottle"
+ if(istype(message_in_a_bottle, /obj/item/photo))
+ return "photo_in_bottle"
+ if(istype(message_in_a_bottle, /obj/item/stack/spacecash))
+ return "cash_in_bottle"
/obj/item/reagent_containers/cup/glass/bottle/small
name = "small glass bottle"
@@ -56,14 +138,16 @@
if(bartender_check(target) && ranged)
return
SplashReagents(target, ranged, override_spillable = TRUE)
- var/obj/item/broken_bottle/B = new(drop_location())
+ var/obj/item/broken_bottle/broken = new(drop_location())
if(!ranged && thrower)
- thrower.put_in_hands(B)
- B.mimic_broken(src, target, break_top)
- B.inhand_icon_state = broken_inhand_icon_state
+ thrower.put_in_hands(broken)
+ broken.mimic_broken(src, target, break_top)
+ broken.inhand_icon_state = broken_inhand_icon_state
+ if(message_in_a_bottle)
+ message_in_a_bottle.forceMove(drop_location())
qdel(src)
- target.Bumped(B)
+ target.Bumped(broken)
/obj/item/reagent_containers/cup/glass/bottle/try_splash(mob/living/user, atom/target)
@@ -339,6 +423,9 @@
list_reagents = list(/datum/reagent/water/holywater = 100)
drink_type = NONE
+/obj/item/reagent_containers/cup/glass/bottle/holywater/add_message_overlay()
+ return //looks too weird...
+
/obj/item/reagent_containers/cup/glass/bottle/holywater/hell
desc = "A flask of holy water...it's been sitting in the Necropolis a while though."
icon_state = "unholyflask"
@@ -501,7 +588,6 @@
list_reagents = list(/datum/reagent/consumable/ethanol/sake = 100)
/obj/item/reagent_containers/cup/glass/bottle/sake/Initialize(mapload)
- . = ..()
if(prob(10))
name = "Fluffy Tail Sake"
desc += " On the bottle is a picture of a kitsune with nine touchable tails."
@@ -510,6 +596,12 @@
name = "Inubashiri's Home Brew"
desc += " Awoo."
icon_state = "sakebottle_i"
+ return ..()
+
+/obj/item/reagent_containers/cup/glass/bottle/sake/add_message_overlay()
+ if(icon_state == "sakebottle_k") //doesn't fit the sprite
+ return
+ return ..()
/obj/item/reagent_containers/cup/glass/bottle/fernet
name = "Fernet Bronca"
@@ -530,6 +622,9 @@
icon_state = "curacao_bottle"
list_reagents = list(/datum/reagent/consumable/ethanol/curacao = 100)
+/obj/item/reagent_containers/cup/glass/bottle/curacao/add_message_overlay()
+ return //doesn't fit the sprite
+
/obj/item/reagent_containers/cup/glass/bottle/navy_rum
name = "Pride of the Union Navy-Strength Rum"
desc = "Ironically named, given it's made in Bermuda."
@@ -574,6 +669,9 @@
///Whether this bottle was a victim of a successful sabrage attempt
var/sabraged = FALSE
+/obj/item/reagent_containers/cup/glass/bottle/champagne/add_message_overlay()
+ return //doesn't stylistically fit the sprite
+
/obj/item/reagent_containers/cup/glass/bottle/champagne/cursed
sabrage_success_percentile = 0 //force of the sharp item used to sabrage will not increase success chance
@@ -733,12 +831,18 @@
icon_state = "hoochbottle"
list_reagents = list(/datum/reagent/consumable/ethanol/hooch = 100)
+/obj/item/reagent_containers/cup/glass/bottle/hooch/add_message_overlay()
+ return //doesn't fit the sprite
+
/obj/item/reagent_containers/cup/glass/bottle/moonshine
name = "moonshine jug"
desc = "It is said that the ancient Applalacians used these stoneware jugs to capture lightning in a bottle."
icon_state = "moonshinebottle"
list_reagents = list(/datum/reagent/consumable/ethanol/moonshine = 100)
+/obj/item/reagent_containers/cup/glass/bottle/moonshine/add_message_overlay()
+ return //doesn't fit the sprite
+
/obj/item/reagent_containers/cup/glass/bottle/mushi_kombucha
name = "Solzara Brewing Company Mushi Kombucha"
desc = "Best drunk over ice to savour the mushroomy flavour."
@@ -790,15 +894,15 @@
)
/obj/item/reagent_containers/cup/glass/bottle/molotov/CheckParts(list/parts_list)
- ..()
- var/obj/item/reagent_containers/cup/glass/bottle/B = locate() in contents
- if(B)
- icon_state = B.icon_state
- B.reagents.copy_to(src, 100)
- if(istype(B, /obj/item/reagent_containers/cup/glass/bottle/juice))
- desc += " You're not sure if making this out of a carton was the brightest idea."
- isGlass = FALSE
- return
+ . = ..()
+ var/obj/item/reagent_containers/cup/glass/bottle/bottle = locate() in contents
+ if(!bottle)
+ return
+ icon_state = bottle.icon_state
+ bottle.reagents.copy_to(src, 100)
+ if(istype(bottle, /obj/item/reagent_containers/cup/glass/bottle/juice))
+ desc += " You're not sure if making this out of a carton was the brightest idea."
+ isGlass = FALSE
/obj/item/reagent_containers/cup/glass/bottle/molotov/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum, do_splash = FALSE)
..(hit_atom, throwingdatum, do_splash = FALSE)
diff --git a/icons/effects/random_spawners.dmi b/icons/effects/random_spawners.dmi
index 4e5608330030b4bc1588879cf890f1cbee10cc1a..d6e06fb140d049897bf05e0fa9082069afcc7445 100644
GIT binary patch
delta 7120
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
SBEuR3y);yGl|MbVj`$yB=w-kF
diff --git a/icons/hud/fishing_hud.dmi b/icons/hud/fishing_hud.dmi
index 0a952615d58e70bbbea16967b5540e8c17bc0495..db36e241a2f33509fcf4e8027d306059a74f2daf 100644
GIT binary patch
delta 3864
zcma)9XIN9)(oTXQ5HJL#C?G)vK?y|#1OWpa6*&l^f`l5%p()aP$&M635JW;z)Du8C
zauks&NDDRol)KS$zvn*RbAQ|)``K%+Su<$8pqh;!;X7}dWQG~h4}>rKp;_fb8~wF61Bx&^({%2Hd}9}Xc#XX
zsx64Y6N->-t(Q;Pc$7wMcn!Pf+qE50Wp6NE1mC^9OyuYjil-O`ciZrT2V&BhbbWEf
z4>sS09pr?K-RNZboM2xIw0`LMYXE0#r}5vjpG?&ES=`a~eT%QVm1KJ91%$c^XrAjf
zL%t7+bG)|KTuaK`=f%Pb`?izmNr9wOO|!kN{8@H~-^}>=ry51e^A|I^)T_2pO4_7N
zh0bAnv94*je3US-Ks>kBsor=chxTaMprcIxhxYGE_Wkr*do}exCna0s7jl43YlnsF
zoxS*lyPdrb3ki|A*wxI=vC0pzGO>Lg`Phgz9vJ+B5NmOLGIyV2|EP(XmGHcDhU~T0
zaU(2A;1fgIu`*EJkYSxawf2ew&+S$_d~pLjF_l|e{PCwkMBK~hWGTJ`I{IDmLx^^#`!Akaedwsz?
zMz_!CyFK8Y*Dx9YF%y~WIT9%Gvbhg|;cleuwNtc2rn<9-=mfb9VoC}?wQtA6xpazP
zMv$=~!RN~hnx*CwqvytnNA(12F;69uq4K
zGqDp}e{&ymCTwRqC63d0P1BPSk=b~?bIE+`lxDwzwLnhYqkvGA`9oH6fSVnDotk=U
zHowf1d*X!-^$(X>!f|n6XKcavkA<*j!u&mCbD_QD0ikVw_(C-b;Ysisl1xyMY|y)v
z^x6b+IiXDYZWzzw$;5+sAGo|@t3CfKrbG1x(Wu``oIm-PAckWvM{aj{IRS>Z3j`;y
zn6_h@BIG@yBG*77=V=eYtR36&V)}lfo*EMmRLFFpLqG*d1}*az=4i6H*UwRF^3?MF
z{bSJ#oGS76q{wkz<2y?BWCy0@a4>ju%K>w2oZuT`I|G<{7?}5`;JtvuxW>Zqh7JGB
zF7^}CcW$%L^gQTX7o16E*e>%rHNmTz^;C$5_{Qc<%ux8G2Yh$yT2BV2CVh9+!H(`>E@u*
z9omcAJJpI{t~Tw}Cv3Yro!il7rv`L>7nOc{;3}HG9>(%&8L#0kEFvs<<3=b#%qnBA
zUJt!WFaU<-D2r?dg^On<(z4C+|2E7oUo5
zPkt(S5K92ROIf!oQ|9x$K7K7Np;h_oIzlV!r!Au-t%zsyA{s~gWEcEJX_^$+XJ^q@
z%{T0ipED^uxV}%Ed{!7sUV@8~&kG;;&o@AV!E8)SpiniXLJ~v@ZPPkCFu%g_YQboW
z((VWN)(vZo^jBe>GI(v`ht0h*8hPni$`-Gy%9cX=d}hbBhJ;MBl^Nw{26Sp1pS(Zt
zP3i;%uv@$05T#_DJ*}2h5i$GMeH|-$7hle~3$r|VC9rOor(;D}|I7%KUxBAZ1Bldn
z21e^XxHT>V6U$@HSPm>Nk5{bQl?C<(D-sp#;
_IbWhxdSwyShE1Hl))
zZ`(7To3L*bWtvZ7X&1=KbBym{7THO0JI@ShagfuN_A2)?qxq)0EwYK-p4wlb6Vp>)
z?1Q*;GZAyykqbThefjBxm0d-E=2Z#E{bOq<^x=k1eC}}NcSJZ2vKfnx)rLiOS;kR4
zFG_-Dc;jdmZqdKi@v-caz9pUgFHK)F{xsfN_DCfB=!cKz-xeFXb>DD*H_(KCg#$Q*
zWr)ptA@}}xrJ+ikhFkxY9l|fMF8#X-zmR({IgeT(9Vg0|@=D>rc5lF0R6S~GBmJNl
z4`-*4QY~?{@{pLA$ix|3NSedCSIW*Ei%FG-xk`$ql42i}j^2A>+P?zUMEmJJ?-rO|
zX`G><1Tt`Vq)9h5UNuL+W=dDMmz6cGhbxK;Gkx?aLNEn1A*Vw%WpZxd;pUTE_lD9F
z2lp45CpbvhmpcRdjo^-gt_JSTo=7BeFck(WC|nmx5b9!(Ac!rk(6%;xCH=xUlt_>X
zgA?{^vm9an*tiN`H#I{A~HgB
zE1-a$_+^I*<}%Ljv^+?sb)aZGs_@nmLldd{R5S
z$ivdgpFh?aX!GuZl9fgM3RcO=25Xsq1*q|dm}>F+Y2yKP8`Akfi`^;+1v0RL3y>a*
zs4eEM;amZ|KsG}Gs3?t-bs29x-&-rDD3$3QzI8sLB60rJWbdLpqa28;kpDJrn1}O&
zYI)QrJh|}rCcL|9;Zy0h-Vk=L3@Y?1sUthXsSQi>$aAX&Yg7v6)l$`?fj;s!83Q$m
zCXzg*Sx!-LA+yPfzXg8!SE6ERW>4wrVQr7nf|xx(;pCBIj_%0A%$L~Drz@M|BfUad
zLvDkY?WQAJT2z28Zb?9$VQA!ElaZc%t{3JK*qy9BnNGLi#V;yZ@#eIN(vt)!`J;h
z6I$W7tE`)w3}i&H6}njoAmCu8X9)#Y?2P=0NboVS;BNccM
z(B&JyTpn9rc)zsd7CC*n@}?G`$jS#BQa{Y`ht;}j4aC@uZ@)|5*ax!CiTF2si}o%B
zw2g_|!Tl?UAK{e5aW4N(GJ6zYyX|Hk1ae$wNg$kV|Hi2}zXI$#<1Vc|)sp3Fj?o1R
z4g)NA=x^XXRMr%QlNT4xJY-`Bo&TdBkd+j3Zr!Z1wKvAO@ye^PMZ^iFR(wv>
zxx|OyuO;fL2&Q`hDKio90`qcs=GbwMI>apTYsgau-pqxo27b3+sWbxkP1NVlqdBX+
zz1BI^S?`chK|KAD=kZe`D-seB9lY3A{Sx@|OxBEHH6-_@*T>os*!v#`%dDc~2bsy}
z_OUTnFn|&tw!wt>S=*LJbS*-=WIFy0XO^xdh{(lQ5_#VIJK9H%#p)Uveb^Q4%0SqqT&Q3jDoINmO5#rL
zqRuiGDK2eCX%xZL)6%bI*enLGxw(0u&Xb5}7=*z}=cJZdA*@*|0vwBN5fvgk3GV^B
zob6;6VWt0k1HXD469`g7O$h?uBG=8Vj|6+1O=!_(U}1m1Tj+peYaAP5Yt!obl#V&u
zvNuJn)D4=V(w(nGtGa}eML#D!xo}B03H?sT#n8ccMrcoETt5c{R}ZU9O0za)S>l6^
lB9(?GO7ALHamz%jI{0sYsSkC|e
delta 3711
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
gu~)(N-lRi%F46sO`UpRQ-O5H`
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