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

🆑
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.
/🆑
This commit is contained in:
Ghom
2024-08-24 01:31:38 -04:00
committed by GitHub
parent a64780f23d
commit 73081bcff0
28 changed files with 527 additions and 145 deletions
+58 -26
View File
@@ -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