mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-23 12:08:28 +01:00
Merge pull request #10325 from VOREStation/Arokha/persistsheets
Add persistent smartfridges with lossiness
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#define MAP_LEVEL_EMPTY 0x020 // Empty Z-levels that may be used for various things (currently used by bluespace jump)
|
||||
#define MAP_LEVEL_CONSOLES 0x040 // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset.
|
||||
#define MAP_LEVEL_XENOARCH_EXEMPT 0x080 // Z-levels exempt from xenoarch digsite generation.
|
||||
#define MAP_LEVEL_PERSIST 0x100 // Z-levels where SSpersistence should persist between rounds
|
||||
|
||||
// Misc map defines.
|
||||
#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge. //VOREStation Edit
|
||||
@@ -32,8 +32,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
if(!A || (A.flags & AREA_FLAG_IS_NOT_PERSISTENT))
|
||||
return
|
||||
|
||||
// if((!T.z in GLOB.using_map.station_levels) || !initialized)
|
||||
if(!(T.z in using_map.station_levels))
|
||||
if(!(T.z in using_map.persist_levels))
|
||||
return
|
||||
|
||||
if(!tracking_values[track_type])
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
/obj/machinery/smartfridge/sheets/persistent
|
||||
persistent = /datum/persistent/storage/smartfridge/sheet_storage
|
||||
|
||||
/obj/machinery/smartfridge/sheets/persistent_lossy
|
||||
persistent = /datum/persistent/storage/smartfridge/sheet_storage/lossy
|
||||
|
||||
/obj/machinery/smartfridge/sheets/accept_check(var/obj/item/O)
|
||||
return istype(O, /obj/item/stack/material)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/obj/machinery/smartfridge/produce
|
||||
name = "\improper SmartFridge"
|
||||
name = "\improper Smart Produce Storage"
|
||||
desc = "For storing all sorts of perishable foods!"
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon_state = "fridge_food"
|
||||
@@ -9,6 +9,9 @@
|
||||
/obj/machinery/smartfridge/produce/persistent
|
||||
persistent = /datum/persistent/storage/smartfridge/produce
|
||||
|
||||
/obj/machinery/smartfridge/produce/persistent_lossy
|
||||
persistent = /datum/persistent/storage/smartfridge/produce/lossy
|
||||
|
||||
/obj/machinery/smartfridge/produce/accept_check(var/obj/item/O as obj)
|
||||
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/))
|
||||
return TRUE
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
icon_base = "fridge_sci"
|
||||
icon_contents = "chem"
|
||||
|
||||
/obj/machinery/smartfridge/New()
|
||||
..()
|
||||
/obj/machinery/smartfridge/Initialize()
|
||||
. = ..()
|
||||
if(persistent)
|
||||
SSpersistence.track_value(src, persistent)
|
||||
if(is_secure)
|
||||
|
||||
@@ -5,13 +5,9 @@
|
||||
/datum/persistent
|
||||
var/name = null
|
||||
var/filename
|
||||
var/tokens_per_line
|
||||
var/entries_expire_at // Set in rounds, this controls when the item is finally removed permanently regardless if cleaned or not.
|
||||
var/entries_decay_at // Set in rounds. This controls when item messages start getting scrambled.
|
||||
var/entry_decay_weight = 0.5
|
||||
var/file_entry_split_character = "\t"
|
||||
var/file_entry_substitute_character = " "
|
||||
var/file_line_split_character = "\n"
|
||||
var/has_admin_data
|
||||
|
||||
/datum/persistent/New()
|
||||
@@ -20,65 +16,57 @@
|
||||
|
||||
/datum/persistent/proc/SetFilename()
|
||||
if(name)
|
||||
filename = "data/persistent/[lowertext(using_map.name)]-[lowertext(name)].txt"
|
||||
filename = "data/persistent/[lowertext(using_map.name)]-[lowertext(name)].json"
|
||||
if(!isnull(entries_decay_at) && !isnull(entries_expire_at))
|
||||
entries_decay_at = round(entries_expire_at * entries_decay_at)
|
||||
|
||||
// Reads in list of text tokens taken from file, generates labelled list of actual token values
|
||||
/datum/persistent/proc/LabelTokens(var/list/tokens)
|
||||
var/list/labelled_tokens = list()
|
||||
labelled_tokens["x"] = text2num(tokens[1])
|
||||
labelled_tokens["y"] = text2num(tokens[2])
|
||||
labelled_tokens["z"] = text2num(tokens[3])
|
||||
labelled_tokens["age"] = text2num(tokens[4])
|
||||
return labelled_tokens
|
||||
|
||||
/datum/persistent/proc/GetValidTurf(var/turf/T, var/list/tokens)
|
||||
if(T && CheckTurfContents(T, tokens))
|
||||
/datum/persistent/proc/GetValidTurf(var/turf/T, var/list/token)
|
||||
if(T && CheckTurfContents(T, token))
|
||||
return T
|
||||
|
||||
/datum/persistent/proc/CheckTurfContents(var/turf/T, var/list/tokens)
|
||||
/datum/persistent/proc/CheckTurfContents(var/turf/T, var/list/token)
|
||||
return TRUE
|
||||
|
||||
/datum/persistent/proc/CheckTokenSanity(var/list/tokens)
|
||||
/datum/persistent/proc/CheckTokenSanity(var/list/token)
|
||||
return ( \
|
||||
!isnull(tokens["x"]) && \
|
||||
!isnull(tokens["y"]) && \
|
||||
!isnull(tokens["z"]) && \
|
||||
!isnull(tokens["age"]) && \
|
||||
tokens["age"] <= entries_expire_at \
|
||||
!isnull(token["x"]) && \
|
||||
!isnull(token["y"]) && \
|
||||
!isnull(token["z"]) && \
|
||||
!isnull(token["age"]) && \
|
||||
token["age"] <= entries_expire_at \
|
||||
)
|
||||
|
||||
// Restores saved data to world
|
||||
/datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/tokens)
|
||||
/datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/token)
|
||||
return
|
||||
|
||||
/datum/persistent/proc/ProcessAndApplyTokens(var/list/tokens)
|
||||
|
||||
// If it's old enough we start to trim down any textual information and scramble strings.
|
||||
if(tokens["message"] && !isnull(entries_decay_at) && !isnull(entry_decay_weight))
|
||||
var/_n = tokens["age"]
|
||||
var/_message = tokens["message"]
|
||||
if(_n >= entries_decay_at)
|
||||
var/decayed_message = ""
|
||||
for(var/i = 1 to length(_message))
|
||||
var/char = copytext(_message, i, i + 1)
|
||||
if(prob(round(_n * entry_decay_weight)))
|
||||
if(prob(99))
|
||||
decayed_message += pick(".",",","-","'","\\","/","\"",":",";")
|
||||
else
|
||||
decayed_message += char
|
||||
_message = decayed_message
|
||||
if(length(_message))
|
||||
tokens["message"] = _message
|
||||
else
|
||||
return
|
||||
for(var/list/token in tokens)
|
||||
if(token["message"] && !isnull(entries_decay_at) && !isnull(entry_decay_weight))
|
||||
var/_n = token["age"]
|
||||
var/_message = token["message"]
|
||||
if(_n >= entries_decay_at)
|
||||
var/decayed_message = ""
|
||||
for(var/i = 1 to length(_message))
|
||||
var/char = copytext(_message, i, i + 1)
|
||||
if(prob(round(_n * entry_decay_weight)))
|
||||
if(prob(99))
|
||||
decayed_message += pick(".",",","-","'","\\","/","\"",":",";")
|
||||
else
|
||||
decayed_message += char
|
||||
_message = decayed_message
|
||||
if(length(_message))
|
||||
token["message"] = _message
|
||||
else
|
||||
return
|
||||
|
||||
var/_z = tokens["z"]
|
||||
if(_z in using_map.station_levels)
|
||||
. = GetValidTurf(locate(tokens["x"], tokens["y"], _z), tokens)
|
||||
if(.)
|
||||
CreateEntryInstance(., tokens)
|
||||
var/_z = token["z"]
|
||||
if(_z in using_map.station_levels)
|
||||
. = GetValidTurf(locate(token["x"], token["y"], _z), token)
|
||||
if(.)
|
||||
CreateEntryInstance(., token)
|
||||
|
||||
/datum/persistent/proc/IsValidEntry(var/atom/entry)
|
||||
if(!istype(entry))
|
||||
@@ -99,46 +87,45 @@
|
||||
/datum/persistent/proc/CompileEntry(var/atom/entry)
|
||||
var/turf/T = get_turf(entry)
|
||||
return list(
|
||||
T.x,
|
||||
T.y,
|
||||
T.z,
|
||||
GetEntryAge(entry)
|
||||
"x" = T.x,
|
||||
"y" = T.y,
|
||||
"z" = T.z,
|
||||
"age" = GetEntryAge(entry)
|
||||
)
|
||||
|
||||
/datum/persistent/proc/Initialize()
|
||||
if(fexists(filename))
|
||||
for(var/entry_line in file2list(filename, file_line_split_character))
|
||||
if(!entry_line)
|
||||
continue
|
||||
var/list/tokens = splittext(entry_line, file_entry_split_character)
|
||||
if(LAZYLEN(tokens) < tokens_per_line)
|
||||
continue
|
||||
tokens = LabelTokens(tokens)
|
||||
if(!CheckTokenSanity(tokens))
|
||||
continue
|
||||
ProcessAndApplyTokens(tokens)
|
||||
var/list/tokens = json_decode(file2text(filename))
|
||||
for(var/list/token in tokens)
|
||||
if(!CheckTokenSanity(token))
|
||||
tokens -= token
|
||||
ProcessAndApplyTokens(tokens)
|
||||
|
||||
/datum/persistent/proc/Shutdown()
|
||||
if(fexists(filename))
|
||||
fdel(filename)
|
||||
var/write_file = file(filename)
|
||||
|
||||
var/list/to_store = list()
|
||||
for(var/thing in SSpersistence.tracking_values[type])
|
||||
if(IsValidEntry(thing))
|
||||
var/list/entry = CompileEntry(thing)
|
||||
if(tokens_per_line == PERSISTENCE_VARIABLE_TOKEN_LENGTH || \
|
||||
LAZYLEN(entry) == tokens_per_line)
|
||||
for(var/i = 1 to LAZYLEN(entry))
|
||||
if(istext(entry[i]))
|
||||
entry[i] = replacetext(entry[i], file_entry_split_character, file_entry_substitute_character)
|
||||
to_file(write_file, jointext(entry, file_entry_split_character))
|
||||
if(!IsValidEntry(thing))
|
||||
continue
|
||||
to_store[++to_store.len] = CompileEntry(thing)
|
||||
|
||||
if(to_store.len)
|
||||
to_file(file(filename), json_encode(to_store))
|
||||
|
||||
/datum/persistent/proc/RemoveValue(var/atom/value)
|
||||
qdel(value)
|
||||
|
||||
/datum/persistent/proc/GetAdminSummary(var/mob/user, var/can_modify)
|
||||
var/list/my_tracks = SSpersistence.tracking_values[type]
|
||||
if(!my_tracks?.len)
|
||||
return
|
||||
|
||||
. = list("<tr><td colspan = 4><b>[capitalize(name)]</b></td></tr>")
|
||||
. += "<tr><td colspan = 4><hr></td></tr>"
|
||||
for(var/thing in SSpersistence.tracking_values[type])
|
||||
|
||||
for(var/thing in my_tracks)
|
||||
. += "<tr>[GetAdminDataStringFor(thing, can_modify, user)]</tr>"
|
||||
. += "<tr><td colspan = 4><hr></td></tr>"
|
||||
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
/datum/persistent/filth
|
||||
name = "filth"
|
||||
tokens_per_line = 5
|
||||
entries_expire_at = 4 // 4 rounds, 24 hours.
|
||||
|
||||
/datum/persistent/filth/LabelTokens(var/list/tokens)
|
||||
var/list/labelled_tokens = ..()
|
||||
labelled_tokens["path"] = text2path(tokens[LAZYLEN(labelled_tokens)+1])
|
||||
return labelled_tokens
|
||||
|
||||
/datum/persistent/filth/IsValidEntry(var/atom/entry)
|
||||
. = ..() && entry.invisibility == 0
|
||||
|
||||
/datum/persistent/filth/CheckTokenSanity(var/list/tokens)
|
||||
return ..() && ispath(tokens["path"])
|
||||
/datum/persistent/filth/CheckTokenSanity(var/list/token)
|
||||
// byond's json implementation is "questionable", and uses types as keys and values without quotes sometimes even though they aren't valid json
|
||||
token["path"] = istext(token["path"]) ? text2path(token["path"]) : token["path"]
|
||||
return ..() && ispath(token["path"])
|
||||
|
||||
/datum/persistent/filth/CheckTurfContents(var/turf/T, var/list/tokens)
|
||||
var/_path = tokens["path"]
|
||||
/datum/persistent/filth/CheckTurfContents(var/turf/T, var/list/token)
|
||||
var/_path = token["path"]
|
||||
return (locate(_path) in T) ? FALSE : TRUE
|
||||
|
||||
/datum/persistent/filth/CreateEntryInstance(var/turf/creating, var/list/tokens)
|
||||
var/_path = tokens["path"]
|
||||
new _path(creating, tokens["age"]+1)
|
||||
/datum/persistent/filth/CreateEntryInstance(var/turf/creating, var/list/token)
|
||||
var/_path = token["path"]
|
||||
new _path(creating, token["age"]+1)
|
||||
|
||||
/datum/persistent/filth/GetEntryAge(var/atom/entry)
|
||||
var/obj/effect/decal/cleanable/filth = entry
|
||||
@@ -32,4 +28,4 @@
|
||||
|
||||
/datum/persistent/filth/CompileEntry(var/atom/entry)
|
||||
. = ..()
|
||||
LAZYADD(., "[GetEntryPath(entry)]")
|
||||
LAZYADDASSOC(., "path", "[GetEntryPath(entry)]")
|
||||
@@ -1,22 +1,14 @@
|
||||
/datum/persistent/graffiti
|
||||
name = "graffiti"
|
||||
tokens_per_line = 6
|
||||
entries_expire_at = 4 // This previously was at 50 rounds??? Over 10 days.
|
||||
has_admin_data = TRUE
|
||||
|
||||
/datum/persistent/graffiti/LabelTokens(var/list/tokens)
|
||||
var/list/labelled_tokens = ..()
|
||||
var/entries = LAZYLEN(labelled_tokens)
|
||||
labelled_tokens["author"] = tokens[entries+1]
|
||||
labelled_tokens["message"] = tokens[entries+2]
|
||||
return labelled_tokens
|
||||
|
||||
/datum/persistent/graffiti/GetValidTurf(var/turf/T, var/list/tokens)
|
||||
/datum/persistent/graffiti/GetValidTurf(var/turf/T, var/list/token)
|
||||
var/turf/checking_turf = ..()
|
||||
if(istype(checking_turf) && checking_turf.can_engrave())
|
||||
return checking_turf
|
||||
|
||||
/datum/persistent/graffiti/CheckTurfContents(var/turf/T, var/list/tokens)
|
||||
/datum/persistent/graffiti/CheckTurfContents(var/turf/T, var/list/token)
|
||||
var/too_much_graffiti = 0
|
||||
for(var/obj/effect/decal/writing/W in .)
|
||||
too_much_graffiti++
|
||||
@@ -24,8 +16,10 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/persistent/graffiti/CreateEntryInstance(var/turf/creating, var/list/tokens)
|
||||
new /obj/effect/decal/writing(creating, tokens["age"]+1, tokens["message"], tokens["author"])
|
||||
/datum/persistent/graffiti/CreateEntryInstance(var/turf/creating, var/list/token)
|
||||
var/obj/effect/decal/writing/inst = new /obj/effect/decal/writing(creating, token["age"]+1, token["message"], token["author"])
|
||||
if(token["icon_state"])
|
||||
inst.icon_state = token["icon_state"]
|
||||
|
||||
/datum/persistent/graffiti/IsValidEntry(var/atom/entry)
|
||||
. = ..()
|
||||
@@ -40,8 +34,9 @@
|
||||
/datum/persistent/graffiti/CompileEntry(var/atom/entry, var/write_file)
|
||||
. = ..()
|
||||
var/obj/effect/decal/writing/save_graffiti = entry
|
||||
LAZYADD(., "[save_graffiti.author ? save_graffiti.author : "unknown"]")
|
||||
LAZYADD(., "[save_graffiti.message]")
|
||||
LAZYADDASSOC(., "author", "[save_graffiti.author ? save_graffiti.author : "unknown"]")
|
||||
LAZYADDASSOC(., "message", "[save_graffiti.message]")
|
||||
LAZYADDASSOC(., "icon_state", "[save_graffiti.icon_state]")
|
||||
|
||||
/datum/persistent/graffiti/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user)
|
||||
var/obj/effect/decal/writing/save_graffiti = thing
|
||||
|
||||
@@ -1,32 +1,24 @@
|
||||
/datum/persistent/paper
|
||||
name = "paper"
|
||||
tokens_per_line = 7
|
||||
entries_expire_at = 50
|
||||
has_admin_data = TRUE
|
||||
var/paper_type = /obj/item/weapon/paper
|
||||
var/requires_noticeboard = TRUE
|
||||
|
||||
/datum/persistent/paper/LabelTokens(var/list/tokens)
|
||||
var/list/labelled_tokens = ..()
|
||||
var/entries = LAZYLEN(labelled_tokens)
|
||||
labelled_tokens["author"] = tokens[entries+1]
|
||||
labelled_tokens["message"] = tokens[entries+2]
|
||||
labelled_tokens["title"] = tokens[entries+3]
|
||||
return labelled_tokens
|
||||
|
||||
/datum/persistent/paper/CheckTurfContents(var/turf/T, var/list/tokens)
|
||||
/datum/persistent/paper/CheckTurfContents(var/turf/T, var/list/token)
|
||||
if(requires_noticeboard && !(locate(/obj/structure/noticeboard) in T))
|
||||
new /obj/structure/noticeboard(T)
|
||||
. = ..()
|
||||
|
||||
/datum/persistent/paper/CreateEntryInstance(var/turf/creating, var/list/tokens)
|
||||
/datum/persistent/paper/CreateEntryInstance(var/turf/creating, var/list/token)
|
||||
var/obj/structure/noticeboard/board = locate() in creating
|
||||
if(requires_noticeboard && LAZYLEN(board.notices) >= board.max_notices)
|
||||
return
|
||||
var/obj/item/weapon/paper/paper = new paper_type(creating)
|
||||
paper.info = tokens["message"]
|
||||
paper.name = tokens["title"]
|
||||
paper.last_modified_ckey = tokens["author"]
|
||||
paper.info = token["message"]
|
||||
paper.name = token["title"]
|
||||
paper.last_modified_ckey = token["author"]
|
||||
paper.age = token["age"]+1
|
||||
if(requires_noticeboard)
|
||||
board.add_paper(paper)
|
||||
if(!paper.was_maploaded) // If we were created/loaded when the map was made, skip us!
|
||||
@@ -40,9 +32,9 @@
|
||||
/datum/persistent/paper/CompileEntry(var/atom/entry, var/write_file)
|
||||
. = ..()
|
||||
var/obj/item/weapon/paper/paper = entry
|
||||
LAZYADD(., "[paper.last_modified_ckey ? paper.last_modified_ckey : "unknown"]")
|
||||
LAZYADD(., "[paper.info]")
|
||||
LAZYADD(., "[paper.name]")
|
||||
LAZYADDASSOC(., "author", "[paper.last_modified_ckey ? paper.last_modified_ckey : "unknown"]")
|
||||
LAZYADDASSOC(., "message", "[paper.info]")
|
||||
LAZYADDASSOC(., "name", "[paper.name]")
|
||||
|
||||
/datum/persistent/paper/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user)
|
||||
var/obj/item/weapon/paper/paper = thing
|
||||
|
||||
@@ -2,27 +2,22 @@
|
||||
name = "stickynotes"
|
||||
paper_type = /obj/item/weapon/paper/sticky
|
||||
requires_noticeboard = FALSE
|
||||
tokens_per_line = 10
|
||||
|
||||
/datum/persistent/paper/sticky/LabelTokens(var/list/tokens)
|
||||
var/list/labelled_tokens = ..()
|
||||
var/entries = LAZYLEN(labelled_tokens)
|
||||
labelled_tokens["offset_x"] = tokens[entries+1]
|
||||
labelled_tokens["offset_y"] = tokens[entries+2]
|
||||
labelled_tokens["color"] = tokens[entries+3]
|
||||
return labelled_tokens
|
||||
|
||||
/datum/persistent/paper/sticky/CreateEntryInstance(var/turf/creating, var/list/tokens)
|
||||
/datum/persistent/paper/sticky/CreateEntryInstance(var/turf/creating, var/list/token)
|
||||
var/atom/paper = ..()
|
||||
if(paper)
|
||||
paper.pixel_x = text2num(tokens["offset_x"])
|
||||
paper.pixel_y = text2num(tokens["offset_y"])
|
||||
paper.color = tokens["color"]
|
||||
if(prob(90))
|
||||
paper.pixel_x = token["offset_x"]
|
||||
paper.pixel_y = token["offset_y"]
|
||||
else
|
||||
paper.pixel_x = rand(-5,5)
|
||||
paper.pixel_y = rand(-5,5)
|
||||
paper.color = token["color"]
|
||||
return paper
|
||||
|
||||
/datum/persistent/paper/sticky/CompileEntry(var/atom/entry, var/write_file)
|
||||
. = ..()
|
||||
var/obj/item/weapon/paper/sticky/paper = entry
|
||||
LAZYADD(., "[paper.pixel_x]")
|
||||
LAZYADD(., "[paper.pixel_y]")
|
||||
LAZYADD(., "[paper.color]")
|
||||
LAZYADDASSOC(., "offset_x", paper.pixel_x)
|
||||
LAZYADDASSOC(., "offset_y", paper.pixel_y)
|
||||
LAZYADDASSOC(., "color", paper.color)
|
||||
@@ -6,9 +6,9 @@
|
||||
for(var/datum/stored_item/I in entry.item_records)
|
||||
.[I.item_path] = I.get_amount()
|
||||
|
||||
/datum/persistent/storage/smartfridge/CreateEntryInstance(var/turf/creating, var/list/tokens)
|
||||
/datum/persistent/storage/smartfridge/CreateEntryInstance(var/turf/creating, var/list/token)
|
||||
var/obj/machinery/smartfridge/S = find_specific_instance(creating)
|
||||
var/list/L = generate_items(tokens["items"])
|
||||
var/list/L = generate_items(token["items"])
|
||||
for(var/atom/A in L)
|
||||
if(S.accept_check(A))
|
||||
S.stock(A)
|
||||
@@ -20,50 +20,64 @@
|
||||
|
||||
|
||||
/datum/persistent/storage/smartfridge/sheet_storage
|
||||
name = "sheet_storage"
|
||||
name = "sheet storage"
|
||||
max_storage = 50
|
||||
store_per_type = TRUE
|
||||
target_type = /obj/machinery/smartfridge/sheets
|
||||
|
||||
var/stacks_go_missing = FALSE // Variable rate depletion of stacks inter-round
|
||||
|
||||
/datum/persistent/storage/smartfridge/sheet_storage/lossy
|
||||
name = "sheet storage lossy"
|
||||
max_storage = 250
|
||||
stacks_go_missing = TRUE
|
||||
|
||||
/datum/persistent/storage/smartfridge/sheet_storage/generate_items(var/list/L)
|
||||
. = list()
|
||||
for(var/obj/item/stack/material/S as anything in L)
|
||||
if(!ispath(S, /obj/item/stack/material))
|
||||
var/real_path = istext(S) ? text2path(S) : S
|
||||
if(!ispath(real_path, /obj/item/stack/material))
|
||||
log_debug("Warning: Sheet_storage persistent datum tried to create [S]")
|
||||
continue
|
||||
|
||||
var/count = L[S]
|
||||
while(count > 0)
|
||||
S = new S
|
||||
S.amount = min(count, S.get_max_amount())
|
||||
count -= S.get_amount()
|
||||
. += S
|
||||
// Skip entire stack if we hit the chance
|
||||
if(prob(go_missing_chance))
|
||||
continue
|
||||
|
||||
var/count = L[S]
|
||||
|
||||
var/obj/item/stack/material/inst = real_path
|
||||
var/max_amount = initial(inst.max_amount)
|
||||
|
||||
// Delete some stacks if we want
|
||||
if(stacks_go_missing)
|
||||
var/fuzzy = rand(-5,5)
|
||||
switch(count / max_amount)
|
||||
if(0 to 1)
|
||||
count -= 10+fuzzy // 1 stack or less, lose 10
|
||||
if(1 to 10)
|
||||
count -= max_amount+fuzzy // 1 to 10 stacks, lose a stack
|
||||
if(10 to INFINITY)
|
||||
count -= max_amount*3+fuzzy // 10+ stacks, lose 3 stacks
|
||||
if(count <= 0)
|
||||
continue
|
||||
|
||||
while(count > 0)
|
||||
inst = new real_path
|
||||
inst.amount = min(count, max_amount)
|
||||
count -= inst.get_amount()
|
||||
. += inst
|
||||
|
||||
|
||||
/datum/persistent/storage/smartfridge/produce
|
||||
name = "fruit_storage"
|
||||
name = "fruit storage"
|
||||
max_storage = 50
|
||||
store_per_type = FALSE
|
||||
target_type = /obj/machinery/smartfridge/produce
|
||||
|
||||
/datum/persistent/storage/smartfridge/produce/assemble_token(var/T)
|
||||
var/list/subtok = splittext(T, " ")
|
||||
if(subtok.len != 2)
|
||||
return null
|
||||
|
||||
if(!istype(SSplants)) // No seed controller means the fruit will come out all wonky if at all
|
||||
return null
|
||||
|
||||
subtok[2] = text2num(subtok[2])
|
||||
|
||||
// Ensure we've found a token describing the quantity of a path
|
||||
if(subtok.len != 2 || \
|
||||
!istype(SSplants.seeds[subtok[1]], /datum/seed) || \
|
||||
!isnum(subtok[2]))
|
||||
return null
|
||||
|
||||
return subtok
|
||||
/datum/persistent/storage/smartfridge/produce/lossy
|
||||
name = "fruit storage lossy"
|
||||
go_missing_chance = 12.5 // 10% loss between rounds
|
||||
|
||||
/datum/persistent/storage/smartfridge/produce/create_item(var/seedtype)
|
||||
return new /obj/item/weapon/reagent_containers/food/snacks/grown(null, seedtype) // Smartfridge will be stock()ed with it, loc is unimportant
|
||||
@@ -74,6 +88,8 @@
|
||||
|
||||
. = list()
|
||||
for(var/datum/stored_item/I in entry.item_records)
|
||||
if(prob(go_missing_chance))
|
||||
continue
|
||||
if(LAZYLEN(I.instances))
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = I.instances[1]
|
||||
if(!istype(G))
|
||||
|
||||
@@ -1,40 +1,23 @@
|
||||
/datum/persistent/storage
|
||||
name = "storage"
|
||||
entries_expire_at = 1
|
||||
has_admin_data = TRUE
|
||||
|
||||
// Don't use these for storage persistence. If someone takes some sheets out and puts them back in mixed in with
|
||||
// new sheets, how do you know the age of the stack? If you want sheets to 'decay', see go_missing_chance
|
||||
entries_decay_at = 0
|
||||
entry_decay_weight = 0
|
||||
tokens_per_line = PERSISTENCE_VARIABLE_TOKEN_LENGTH
|
||||
|
||||
// // // //
|
||||
|
||||
var/max_storage = 0
|
||||
var/store_per_type = FALSE // If true, will store up to max_storage for each type stored
|
||||
var/target_type = null // Path of the thing that this expects to put stuff into
|
||||
|
||||
var/go_missing_chance = 0 // Chance an item will fail to be spawned in from persistence and need to be restocked
|
||||
|
||||
/datum/persistent/storage/SetFilename()
|
||||
if(name)
|
||||
filename = "data/persistent/storage/[lowertext(using_map.name)]-[lowertext(name)].txt"
|
||||
|
||||
/datum/persistent/storage/LabelTokens(var/list/tokens)
|
||||
. = ..()
|
||||
.["items"] = list()
|
||||
for(var/T in tokens)
|
||||
var/list/L = assemble_token(T)
|
||||
if(LAZYLEN(L))
|
||||
.["items"][L[1]] = text2num(L[2])
|
||||
|
||||
/datum/persistent/storage/proc/assemble_token(var/T)
|
||||
var/list/subtok = splittext(T, " ")
|
||||
if(subtok.len != 2)
|
||||
return null
|
||||
|
||||
subtok[1] = text2path(subtok[1])
|
||||
subtok[2] = text2num( subtok[2])
|
||||
|
||||
// Ensure we've found a token describing the quantity of a path
|
||||
if(subtok.len != 2 || \
|
||||
!ispath(subtok[1]) || \
|
||||
!isnum(subtok[2]))
|
||||
return null
|
||||
|
||||
return subtok
|
||||
filename = "data/persistent/storage/[lowertext(using_map.name)]-[lowertext(name)].json"
|
||||
|
||||
/datum/persistent/storage/IsValidEntry(var/atom/entry)
|
||||
return ..() && istype(entry, target_type)
|
||||
@@ -52,9 +35,8 @@
|
||||
if(!store_per_type)
|
||||
stored = max(stored - item_list[item], 0)
|
||||
|
||||
for(var/item in storage_list)
|
||||
. += "[item] [storage_list[item]]"
|
||||
|
||||
LAZYADDASSOC(., "items", storage_list)
|
||||
|
||||
// Usage: returns list with structure:
|
||||
// list(
|
||||
// [type1] = [stored_quantity],
|
||||
@@ -66,16 +48,27 @@
|
||||
/datum/persistent/storage/proc/find_specific_instance(var/turf/T)
|
||||
return locate(target_type) in T
|
||||
|
||||
/datum/persistent/storage/CheckTurfContents(var/turf/T, var/list/tokens)
|
||||
/datum/persistent/storage/CheckTurfContents(var/turf/T, var/list/token)
|
||||
return istype(find_specific_instance(T), target_type)
|
||||
|
||||
/datum/persistent/storage/proc/generate_items(var/list/L)
|
||||
. = list()
|
||||
for(var/path in L)
|
||||
// byond's json implementation is "questionable", and uses types as keys and values without quotes sometimes even though they aren't valid json
|
||||
var/real_path = istext(path) ? text2path(path) : path
|
||||
for(var/i in 1 to L[path])
|
||||
var/atom/A = create_item(path)
|
||||
if(prob(go_missing_chance))
|
||||
continue
|
||||
var/atom/A = create_item(real_path)
|
||||
if(!QDELETED(A))
|
||||
. += A
|
||||
|
||||
/datum/persistent/storage/proc/create_item(var/path)
|
||||
return new path()
|
||||
return new path()
|
||||
|
||||
/datum/persistent/storage/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user)
|
||||
var/atom/T = thing
|
||||
if(!istype(T))
|
||||
return "<td><Missing entry><td>"
|
||||
else
|
||||
. = "<td colspan = 2>[T.name]</td><td>[T.x],[T.y],[T.z]</td><td>"
|
||||
|
||||
@@ -1679,6 +1679,18 @@
|
||||
/obj/structure/closet/walllocker_double/hydrant/west,
|
||||
/turf/simulated/floor/tiled/techmaint,
|
||||
/area/talon_v2/secure_storage)
|
||||
"fk" = (
|
||||
/obj/structure/railing/grey{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 1
|
||||
},
|
||||
/obj/machinery/smartfridge/sheets/persistent_lossy{
|
||||
layer = 3.3
|
||||
},
|
||||
/turf/simulated/floor/tiled/techfloor,
|
||||
/area/talon_v2/refining)
|
||||
"fm" = (
|
||||
/obj/machinery/door/airlock/glass_external{
|
||||
req_one_access = list(301)
|
||||
@@ -26593,7 +26605,7 @@ ca
|
||||
rj
|
||||
fW
|
||||
jS
|
||||
tX
|
||||
fk
|
||||
VS
|
||||
mQ
|
||||
ZR
|
||||
|
||||
@@ -527,6 +527,6 @@
|
||||
|
||||
/datum/map_z_level/tether_lateload/talon_v2
|
||||
name = "Talon"
|
||||
flags = MAP_LEVEL_PLAYER
|
||||
flags = MAP_LEVEL_PLAYER|MAP_LEVEL_PERSIST
|
||||
base_turf = /turf/space
|
||||
z = Z_LEVEL_OFFMAP1
|
||||
@@ -18423,13 +18423,13 @@
|
||||
/turf/simulated/floor/tiled,
|
||||
/area/tether/surfacebase/surface_three_hall)
|
||||
"aDX" = (
|
||||
/obj/machinery/smartfridge,
|
||||
/obj/effect/floor_decal/borderfloor{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/floor_decal/corner/lime/border{
|
||||
dir = 1
|
||||
},
|
||||
/obj/machinery/smartfridge/produce/persistent_lossy,
|
||||
/turf/simulated/floor/tiled,
|
||||
/area/tether/surfacebase/botanystorage)
|
||||
"aDY" = (
|
||||
|
||||
@@ -19061,7 +19061,6 @@
|
||||
/turf/simulated/floor,
|
||||
/area/maintenance/station/ai)
|
||||
"aSj" = (
|
||||
/obj/structure/closet/emcloset,
|
||||
/obj/machinery/atmospherics/unary/vent_pump/on{
|
||||
dir = 8
|
||||
},
|
||||
@@ -19534,6 +19533,7 @@
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/on{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/closet/emcloset,
|
||||
/turf/simulated/floor/tiled,
|
||||
/area/quartermaster/belterdock)
|
||||
"aTA" = (
|
||||
@@ -23197,6 +23197,10 @@
|
||||
},
|
||||
/turf/simulated/floor/tiled/eris/dark/techfloor,
|
||||
/area/shuttle/medivac/engines)
|
||||
"kPM" = (
|
||||
/obj/machinery/smartfridge/sheets/persistent_lossy,
|
||||
/turf/simulated/wall,
|
||||
/area/quartermaster/belterdock)
|
||||
"kPW" = (
|
||||
/obj/machinery/door/blast/regular{
|
||||
dir = 4;
|
||||
@@ -38467,7 +38471,7 @@ aHB
|
||||
aMz
|
||||
aBU
|
||||
aBU
|
||||
aQG
|
||||
kPM
|
||||
aSj
|
||||
aOu
|
||||
aOL
|
||||
|
||||
@@ -698,6 +698,7 @@
|
||||
name = "\improper South Maintenance"
|
||||
/area/maintenance/lower/trash_pit
|
||||
name = "\improper Trash Pit"
|
||||
flags = RAD_SHIELDED|AREA_FLAG_IS_NOT_PERSISTENT
|
||||
/area/maintenance/lower/solars
|
||||
name = "\improper Solars Maintenance"
|
||||
/area/maintenance/lower/mining_eva
|
||||
|
||||
@@ -299,14 +299,14 @@
|
||||
|
||||
// We have a bunch of stuff common to the station z levels
|
||||
/datum/map_z_level/tether/station
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
|
||||
holomap_legend_x = 220
|
||||
holomap_legend_y = 160
|
||||
|
||||
/datum/map_z_level/tether/station/surface_low
|
||||
z = Z_LEVEL_SURFACE_LOW
|
||||
name = "Surface 1"
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
|
||||
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
|
||||
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
|
||||
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE*0
|
||||
@@ -314,7 +314,7 @@
|
||||
/datum/map_z_level/tether/station/surface_mid
|
||||
z = Z_LEVEL_SURFACE_MID
|
||||
name = "Surface 2"
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
|
||||
base_turf = /turf/simulated/open
|
||||
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
|
||||
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE*1
|
||||
@@ -322,7 +322,7 @@
|
||||
/datum/map_z_level/tether/station/surface_high
|
||||
z = Z_LEVEL_SURFACE_HIGH
|
||||
name = "Surface 3"
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
|
||||
base_turf = /turf/simulated/open
|
||||
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
|
||||
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE*2
|
||||
@@ -359,11 +359,11 @@
|
||||
/datum/map_z_level/tether/mine
|
||||
z = Z_LEVEL_SURFACE_MINE
|
||||
name = "Mining Outpost"
|
||||
flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED
|
||||
flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED|MAP_LEVEL_PERSIST
|
||||
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
|
||||
|
||||
/datum/map_z_level/tether/solars
|
||||
z = Z_LEVEL_SOLARS
|
||||
name = "Solar Field"
|
||||
flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED
|
||||
flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED|MAP_LEVEL_PERSIST
|
||||
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
|
||||
|
||||
@@ -33,6 +33,7 @@ var/list/all_maps = list()
|
||||
var/static/list/player_levels = list() // Z-levels a character can typically reach
|
||||
var/static/list/sealed_levels = list() // Z-levels that don't allow random transit at edge
|
||||
var/static/list/xenoarch_exempt_levels = list() //Z-levels exempt from xenoarch finds and digsites spawning.
|
||||
var/static/list/persist_levels = list() // Z-levels where SSpersistence should persist between rounds. Defaults to station_levels if unset.
|
||||
var/static/list/empty_levels = null // Empty Z-levels that may be used for various things (currently used by bluespace jump)
|
||||
// End Static Lists
|
||||
|
||||
@@ -135,8 +136,10 @@ var/list/all_maps = list()
|
||||
if(zlevel_datum_type)
|
||||
for(var/type in subtypesof(zlevel_datum_type))
|
||||
new type(src)
|
||||
if(!map_levels)
|
||||
if(!map_levels?.len)
|
||||
map_levels = station_levels.Copy()
|
||||
if(!persist_levels?.len)
|
||||
persist_levels = station_levels.Copy()
|
||||
if(!allowed_jobs || !allowed_jobs.len)
|
||||
allowed_jobs = subtypesof(/datum/job)
|
||||
if(default_skybox) //Type was specified
|
||||
@@ -295,6 +298,7 @@ var/list/all_maps = list()
|
||||
if(flags & MAP_LEVEL_PLAYER) map.player_levels += z
|
||||
if(flags & MAP_LEVEL_SEALED) map.sealed_levels += z
|
||||
if(flags & MAP_LEVEL_XENOARCH_EXEMPT) map.xenoarch_exempt_levels += z
|
||||
if(flags & MAP_LEVEL_PERSIST) map.persist_levels += z
|
||||
if(flags & MAP_LEVEL_EMPTY)
|
||||
if(!map.empty_levels) map.empty_levels = list()
|
||||
map.empty_levels += z
|
||||
|
||||
+1
-2
@@ -68,7 +68,6 @@
|
||||
#include "code\__defines\objects.dm"
|
||||
#include "code\__defines\overmap.dm"
|
||||
#include "code\__defines\pda.dm"
|
||||
#include "code\__defines\persistence.dm"
|
||||
#include "code\__defines\planets.dm"
|
||||
#include "code\__defines\planets_vr.dm"
|
||||
#include "code\__defines\plants.dm"
|
||||
@@ -3287,7 +3286,7 @@
|
||||
#include "code\modules\persistence\filth.dm"
|
||||
#include "code\modules\persistence\graffiti.dm"
|
||||
#include "code\modules\persistence\noticeboard.dm"
|
||||
#include "code\modules\persistence\persistence.dm"
|
||||
#include "code\modules\persistence\serialize.dm"
|
||||
#include "code\modules\persistence\datum\persistence_datum.dm"
|
||||
#include "code\modules\persistence\effects\filth.dm"
|
||||
#include "code\modules\persistence\effects\graffiti.dm"
|
||||
|
||||
Reference in New Issue
Block a user