From 9784331cdbc8bf058405653ce5efa22b1b0e43df Mon Sep 17 00:00:00 2001 From: Chompstation Bot Date: Sat, 15 May 2021 17:15:26 +0000 Subject: [PATCH] Add persistent smartfridges with lossiness --- code/__defines/map.dm | 5 + code/controllers/subsystems/persistence.dm | 3 +- code/modules/food/kitchen/smartfridge.dm | 423 ++++++++++++++++++ .../food/kitchen/smartfridge/engineering.dm | 3 + .../food/kitchen/smartfridge/hydroponics.dm | 5 +- .../persistence/datum/persistence_datum.dm | 145 ++++-- code/modules/persistence/effects/filth.dm | 24 +- code/modules/persistence/effects/graffiti.dm | 23 +- code/modules/persistence/effects/paper.dm | 26 +- .../persistence/effects/paper_sticky.dm | 27 +- .../{persistence.dm => serialize.dm} | 0 .../persistence/storage/smartfridge.dm | 72 +-- code/modules/persistence/storage/storage.dm | 59 ++- maps/offmap_vr/talon/talon_v2.dmm | 14 +- maps/tether/submaps/_tether_submaps.dm | 2 +- maps/tether/tether-03-surface3.dmm | 2 +- maps/tether/tether-07-station3.dmm | 8 +- maps/tether/tether_areas.dm | 1 + maps/tether/tether_defines.dm | 12 +- maps/~map_system/maps.dm | 10 +- vorestation.dme | 1 + 21 files changed, 682 insertions(+), 183 deletions(-) create mode 100644 code/modules/food/kitchen/smartfridge.dm rename code/modules/persistence/{persistence.dm => serialize.dm} (100%) diff --git a/code/__defines/map.dm b/code/__defines/map.dm index be86ee58d6..b6b182d14b 100644 --- a/code/__defines/map.dm +++ b/code/__defines/map.dm @@ -7,7 +7,12 @@ #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. +<<<<<<< HEAD #define MAP_LEVEL_VORESPAWN 0x100 // Z-levels players are allowed to late join to via vorish means. Usually non-dangerous locations. +||||||| parent of ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets +======= +#define MAP_LEVEL_PERSIST 0x100 // Z-levels where SSpersistence should persist between rounds +>>>>>>> ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets // 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 \ No newline at end of file diff --git a/code/controllers/subsystems/persistence.dm b/code/controllers/subsystems/persistence.dm index 8ea9e0b582..1667aa8320 100644 --- a/code/controllers/subsystems/persistence.dm +++ b/code/controllers/subsystems/persistence.dm @@ -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]) diff --git a/code/modules/food/kitchen/smartfridge.dm b/code/modules/food/kitchen/smartfridge.dm new file mode 100644 index 0000000000..a6def6bd2b --- /dev/null +++ b/code/modules/food/kitchen/smartfridge.dm @@ -0,0 +1,423 @@ +/* SmartFridge. Much todo +*/ +/obj/machinery/smartfridge + name = "\improper SmartFridge" + desc = "For storing all sorts of perishable foods!" + icon = 'icons/obj/vending.dmi' + icon_state = "fridge_food" + var/icon_base = "fridge_food" //Iconstate to base all the broken/deny/etc on + var/icon_contents = "food" //Overlay to put on glass to show contents + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 5 + active_power_usage = 100 + flags = NOREACT + var/max_n_of_items = 999 // Sorry but the BYOND infinite loop detector doesn't look things over 1000. //VOREStation Edit - Non-global + //var/global/max_n_of_items = 999 // Sorry but the BYOND infinite loop detector doesn't look things over 1000. + var/list/item_records = list() + var/datum/stored_item/currently_vending = null //What we're putting out of the machine. + var/seconds_electrified = 0; + var/shoot_inventory = 0 + var/locked = 0 + var/scan_id = 1 + var/is_secure = 0 + var/wrenchable = 0 + var/datum/wires/smartfridge/wires = null + +/obj/machinery/smartfridge/secure + is_secure = 1 + icon_state = "fridge_sci" + icon_base = "fridge_sci" + icon_contents = "chem" + +/obj/machinery/smartfridge/New() + ..() + if(is_secure) + wires = new/datum/wires/smartfridge/secure(src) + else + wires = new/datum/wires/smartfridge(src) + +/obj/machinery/smartfridge/Destroy() + qdel(wires) + for(var/A in item_records) //Get rid of item records. + qdel(A) + wires = null + return ..() + +/obj/machinery/smartfridge/proc/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 1 + return 0 + +/obj/machinery/smartfridge/seeds + name = "\improper MegaSeed Servitor" + desc = "When you need seeds fast!" + icon_contents = "chem" + +/obj/machinery/smartfridge/seeds/accept_check(var/obj/item/O as obj) + if(istype(O,/obj/item/seeds/)) + return 1 + return 0 + +/obj/machinery/smartfridge/secure/extract + name = "\improper Biological Sample Storage" + desc = "A refrigerated storage unit for xenobiological samples." + icon_contents = "slime" + req_access = list(access_research) + +/obj/machinery/smartfridge/secure/extract/accept_check(var/obj/item/O as obj) + if(istype(O, /obj/item/slime_extract)) + return TRUE + if(istype(O, /obj/item/slimepotion)) + return TRUE + return FALSE + +/obj/machinery/smartfridge/secure/medbay + name = "\improper Refrigerated Medicine Storage" + desc = "A refrigerated storage unit for storing medicine and chemicals." + req_one_access = list(access_medical,access_chemistry) + +/obj/machinery/smartfridge/secure/medbay/accept_check(var/obj/item/O as obj) + if(istype(O,/obj/item/weapon/reagent_containers/glass/)) + return 1 + if(istype(O,/obj/item/weapon/storage/pill_bottle/)) + return 1 + if(istype(O,/obj/item/weapon/reagent_containers/pill/)) + return 1 + return 0 + +/obj/machinery/smartfridge/secure/virology + name = "\improper Refrigerated Virus Storage" + desc = "A refrigerated storage unit for storing viral material." + icon_contents = "drink" + req_access = list(access_virology) + +/obj/machinery/smartfridge/secure/virology/accept_check(var/obj/item/O as obj) + if(istype(O,/obj/item/weapon/reagent_containers/glass/beaker/vial/)) + return 1 + if(istype(O,/obj/item/weapon/virusdish/)) + return 1 + return 0 + +/obj/machinery/smartfridge/chemistry //Is this used anywhere? It's not secure. + name = "\improper Smart Chemical Storage" + desc = "A refrigerated storage unit for medicine and chemical storage." + icon_contents = "chem" + +/obj/machinery/smartfridge/chemistry/accept_check(var/obj/item/O as obj) + if(istype(O,/obj/item/weapon/storage/pill_bottle) || istype(O,/obj/item/weapon/reagent_containers)) + return 1 + return 0 + +/obj/machinery/smartfridge/chemistry/virology //Same + name = "\improper Smart Virus Storage" + desc = "A refrigerated storage unit for volatile sample storage." + +/obj/machinery/smartfridge/drinks + name = "\improper Drink Showcase" + desc = "A refrigerated storage unit for tasty tasty alcohol." + icon_state = "fridge_drinks" + icon_base = "fridge_drinks" + icon_contents = "drink" + +/obj/machinery/smartfridge/drinks/accept_check(var/obj/item/O as obj) + if(istype(O,/obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks) || istype(O,/obj/item/weapon/reagent_containers/food/condiment)) + return 1 + +/obj/machinery/smartfridge/drying_rack + name = "\improper Drying Rack" + desc = "A machine for drying plants." + wrenchable = 1 + icon_state = "drying_rack" + icon_base = "drying_rack" + +/obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj) + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/)) + var/obj/item/weapon/reagent_containers/food/snacks/S = O + if (S.dried_type) + return 1 + + if(istype(O, /obj/item/stack/wetleather)) + return 1 + + return 0 + +/obj/machinery/smartfridge/drying_rack/process() + ..() + if(stat & (BROKEN|NOPOWER)) + return + if(contents.len) + dry() + update_icon() + +/obj/machinery/smartfridge/drying_rack/update_icon() + var/not_working = stat & (BROKEN|NOPOWER) + var/hasItems + for(var/datum/stored_item/I in item_records) + if(I.get_amount()) + hasItems = 1 + break + if(hasItems) + if(not_working) + icon_state = "[icon_base]-plant-off" + else + icon_state = "[icon_base]-plant" + else + if(not_working) + icon_state = "[icon_base]-off" + else + icon_state = "[icon_base]" + +/obj/machinery/smartfridge/drying_rack/proc/dry() + for(var/datum/stored_item/I in item_records) + for(var/obj/item/weapon/reagent_containers/food/snacks/S in I.instances) + if(S.dry) continue + if(S.dried_type == S.type) + S.dry = 1 + S.name = "dried [S.name]" + S.color = "#AAAAAA" + I.instances -= S + S.forceMove(get_turf(src)) + else + var/D = S.dried_type + new D(get_turf(src)) + qdel(S) + return + + for(var/obj/item/stack/wetleather/WL in I.instances) + if(!WL.wetness) + if(WL.amount) + WL.forceMove(get_turf(src)) + WL.dry() + I.instances -= WL + break + + WL.wetness = max(0, WL.wetness - rand(1, 3)) + + return + +/obj/machinery/smartfridge/process() + if(stat & (BROKEN|NOPOWER)) + return + if(src.seconds_electrified > 0) + src.seconds_electrified-- + if(src.shoot_inventory && prob(2)) + src.throw_item() + +/obj/machinery/smartfridge/power_change() + var/old_stat = stat + ..() + if(old_stat != stat) + update_icon() + +/obj/machinery/smartfridge/update_icon() + cut_overlays() + if(stat & (BROKEN|NOPOWER)) + icon_state = "[icon_base]-off" + else + icon_state = icon_base + + if(is_secure) + add_overlay("[icon_base]-sidepanel") + + if(panel_open) + add_overlay("[icon_base]-panel") + + var/is_off = "" + if(inoperable()) + is_off = "-off" + + // Fridge contents + if(contents) //VOREStation Edit - Some fridges do not have visible contents + switch(contents.len) + if(0) + add_overlay("empty[is_off]") + if(1 to 2) + add_overlay("[icon_contents]-1[is_off]") + if(3 to 5) + add_overlay("[icon_contents]-2[is_off]") + if(6 to 8) + add_overlay("[icon_contents]-3[is_off]") + else + add_overlay("[icon_contents]-4[is_off]") + + // Fridge top + var/image/top = image(icon, "[icon_base]-top") + top.pixel_z = 32 + top.layer = ABOVE_WINDOW_LAYER + add_overlay(top) + +/******************* +* Item Adding +********************/ + +/obj/machinery/smartfridge/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(O.is_screwdriver()) + panel_open = !panel_open + user.visible_message("[user] [panel_open ? "opens" : "closes"] the maintenance panel of \the [src].", "You [panel_open ? "open" : "close"] the maintenance panel of \the [src].") + playsound(src, O.usesound, 50, 1) + update_icon() + return + + if(wrenchable && default_unfasten_wrench(user, O, 20)) + return + + if(istype(O, /obj/item/device/multitool) || O.is_wirecutter()) + if(panel_open) + attack_hand(user) + return + + if(stat & NOPOWER) + to_chat(user, "\The [src] is unpowered and useless.") + return + + if(accept_check(O)) + user.remove_from_mob(O) + stock(O) + user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].") + + else if(istype(O, /obj/item/weapon/storage/bag)) + var/obj/item/weapon/storage/bag/P = O + var/plants_loaded = 0 + for(var/obj/G in P.contents) + if(accept_check(G)) + P.remove_from_storage(G) //fixes ui bug - Pull Request 5515 + stock(G) + plants_loaded = 1 + if(plants_loaded) + user.visible_message("[user] loads \the [src] with \the [P].", "You load \the [src] with \the [P].") + if(P.contents.len > 0) + to_chat(user, "Some items are refused.") + + else if(istype(O, /obj/item/weapon/gripper)) // Grippers. ~Mechoid. + var/obj/item/weapon/gripper/B = O //B, for Borg. + if(!B.wrapped) + to_chat(user, "\The [B] is not holding anything.") + return + else + var/B_held = B.wrapped + to_chat(user, "You use \the [B] to put \the [B_held] into \the [src].") + return + + else + to_chat(user, "\The [src] smartly refuses [O].") + return 1 + +/obj/machinery/smartfridge/secure/emag_act(var/remaining_charges, var/mob/user) + if(!emagged) + emagged = 1 + locked = -1 + to_chat(user, "You short out the product lock on [src].") + return 1 + +/obj/machinery/smartfridge/proc/stock(obj/item/O) + var/hasRecord = FALSE //Check to see if this passes or not. + for(var/datum/stored_item/I in item_records) + if((O.type == I.item_path) && (O.name == I.item_name)) + I.add_product(O) + hasRecord = TRUE + break + if(!hasRecord) + var/datum/stored_item/item = new/datum/stored_item(src, O.type, O.name) + item.add_product(O) + item_records.Add(item) + SStgui.update_uis(src) + +/obj/machinery/smartfridge/proc/vend(datum/stored_item/I) + I.get_product(get_turf(src)) + SStgui.update_uis(src) + +/obj/machinery/smartfridge/attack_ai(mob/user as mob) + attack_hand(user) + +/obj/machinery/smartfridge/attack_hand(mob/user as mob) + if(stat & (NOPOWER|BROKEN)) + return + wires.Interact(user) + tgui_interact(user) + +/obj/machinery/smartfridge/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SmartVend", name) + ui.set_autoupdate(FALSE) + ui.open() + +/obj/machinery/smartfridge/tgui_data(mob/user) + . = list() + + var/list/items = list() + for(var/i=1 to length(item_records)) + var/datum/stored_item/I = item_records[i] + var/count = I.get_amount() + if(count > 0) + items.Add(list(list("name" = html_encode(capitalize(I.item_name)), "index" = i, "amount" = count))) + + .["contents"] = items + .["name"] = name + .["locked"] = locked + .["secure"] = is_secure + +/obj/machinery/smartfridge/tgui_act(action, params) + if(..()) + return TRUE + + add_fingerprint(usr) + switch(action) + if("Release") + var/amount = 0 + if(params["amount"]) + amount = params["amount"] + else + amount = input("How many items?", "How many items would you like to take out?", 1) as num|null + + if(QDELETED(src) || QDELETED(usr) || !usr.Adjacent(src)) + return FALSE + + var/index = text2num(params["index"]) + var/datum/stored_item/I = item_records[index] + var/count = I.get_amount() + + // Sanity check, there are probably ways to press the button when it shouldn't be possible. + if(count > 0) + if((count - amount) < 0) + amount = count + for(var/i = 1 to amount) + vend(I) + + return TRUE + return FALSE + +/obj/machinery/smartfridge/proc/throw_item() + var/obj/throw_item = null + var/mob/living/target = locate() in view(7,src) + if(!target) + return 0 + + for(var/datum/stored_item/I in item_records) + throw_item = I.get_product(get_turf(src)) + if (!throw_item) + continue + break + + if(!throw_item) + return 0 + spawn(0) + throw_item.throw_at(target,16,3,src) + src.visible_message("[src] launches [throw_item.name] at [target.name]!") + SStgui.update_uis(src) + return 1 + +/************************ +* Secure SmartFridges +*************************/ + +/obj/machinery/smartfridge/secure/tgui_act(action, params) + if(stat & (NOPOWER|BROKEN)) + return TRUE + if(usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) + if(!allowed(usr) && !emagged && locked != -1 && action == "Release") + to_chat(usr, "Access denied.") + return TRUE + return ..() diff --git a/code/modules/food/kitchen/smartfridge/engineering.dm b/code/modules/food/kitchen/smartfridge/engineering.dm index 22983611f0..8141ca496d 100644 --- a/code/modules/food/kitchen/smartfridge/engineering.dm +++ b/code/modules/food/kitchen/smartfridge/engineering.dm @@ -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) diff --git a/code/modules/food/kitchen/smartfridge/hydroponics.dm b/code/modules/food/kitchen/smartfridge/hydroponics.dm index ebf706c25e..9b50136d79 100644 --- a/code/modules/food/kitchen/smartfridge/hydroponics.dm +++ b/code/modules/food/kitchen/smartfridge/hydroponics.dm @@ -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 diff --git a/code/modules/persistence/datum/persistence_datum.dm b/code/modules/persistence/datum/persistence_datum.dm index 8499caef0b..9dc2d7c17c 100644 --- a/code/modules/persistence/datum/persistence_datum.dm +++ b/code/modules/persistence/datum/persistence_datum.dm @@ -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,10 +16,22 @@ /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) +<<<<<<< HEAD +/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)) +||||||| parent of ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets // 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() @@ -35,50 +43,62 @@ /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)) +>>>>>>> ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets 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 \ ) +<<<<<<< HEAD +/datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/tokens) +||||||| parent of ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets // Restores saved data to world /datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/tokens) +======= +// Restores saved data to world +/datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/token) +>>>>>>> ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets 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)) @@ -98,31 +118,42 @@ /datum/persistent/proc/CompileEntry(var/atom/entry) var/turf/T = get_turf(entry) +<<<<<<< HEAD + . = list( + T.x, + T.y, + T.z, + GetEntryAge(entry) +||||||| parent of ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets return list( T.x, T.y, T.z, GetEntryAge(entry) +======= + return list( + "x" = T.x, + "y" = T.y, + "z" = T.z, + "age" = GetEntryAge(entry) +>>>>>>> ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets ) /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]) +<<<<<<< HEAD if(IsValidEntry(thing)) var/list/entry = CompileEntry(thing) if(tokens_per_line == PERSISTENCE_VARIABLE_TOKEN_LENGTH || \ @@ -131,14 +162,36 @@ 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)) +||||||| parent of ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets + 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)) +>>>>>>> ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets /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("[capitalize(name)]") . += "
" - for(var/thing in SSpersistence.tracking_values[type]) + + for(var/thing in my_tracks) . += "[GetAdminDataStringFor(thing, can_modify, user)]" . += "
" diff --git a/code/modules/persistence/effects/filth.dm b/code/modules/persistence/effects/filth.dm index 10b304e18e..166c374c02 100644 --- a/code/modules/persistence/effects/filth.dm +++ b/code/modules/persistence/effects/filth.dm @@ -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)]") \ No newline at end of file + LAZYADDASSOC(., "path", "[GetEntryPath(entry)]") \ No newline at end of file diff --git a/code/modules/persistence/effects/graffiti.dm b/code/modules/persistence/effects/graffiti.dm index 6ca1bbf32f..369f9156b4 100644 --- a/code/modules/persistence/effects/graffiti.dm +++ b/code/modules/persistence/effects/graffiti.dm @@ -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 diff --git a/code/modules/persistence/effects/paper.dm b/code/modules/persistence/effects/paper.dm index fe2ef81368..95968274eb 100644 --- a/code/modules/persistence/effects/paper.dm +++ b/code/modules/persistence/effects/paper.dm @@ -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 diff --git a/code/modules/persistence/effects/paper_sticky.dm b/code/modules/persistence/effects/paper_sticky.dm index 1871eb4a03..08fb905009 100644 --- a/code/modules/persistence/effects/paper_sticky.dm +++ b/code/modules/persistence/effects/paper_sticky.dm @@ -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]") \ No newline at end of file + LAZYADDASSOC(., "offset_x", paper.pixel_x) + LAZYADDASSOC(., "offset_y", paper.pixel_y) + LAZYADDASSOC(., "color", paper.color) \ No newline at end of file diff --git a/code/modules/persistence/persistence.dm b/code/modules/persistence/serialize.dm similarity index 100% rename from code/modules/persistence/persistence.dm rename to code/modules/persistence/serialize.dm diff --git a/code/modules/persistence/storage/smartfridge.dm b/code/modules/persistence/storage/smartfridge.dm index 0b2eee0ca1..0584ab9e79 100644 --- a/code/modules/persistence/storage/smartfridge.dm +++ b/code/modules/persistence/storage/smartfridge.dm @@ -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)) diff --git a/code/modules/persistence/storage/storage.dm b/code/modules/persistence/storage/storage.dm index 9ad9531cbc..58b23a6ce9 100644 --- a/code/modules/persistence/storage/storage.dm +++ b/code/modules/persistence/storage/storage.dm @@ -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() \ No newline at end of file + return new path() + +/datum/persistent/storage/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user) + var/atom/T = thing + if(!istype(T)) + return "" + else + . = "[T.name][T.x],[T.y],[T.z]" diff --git a/maps/offmap_vr/talon/talon_v2.dmm b/maps/offmap_vr/talon/talon_v2.dmm index 1f5fdef65c..bf5637ebb9 100644 --- a/maps/offmap_vr/talon/talon_v2.dmm +++ b/maps/offmap_vr/talon/talon_v2.dmm @@ -1918,6 +1918,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) @@ -26583,7 +26595,7 @@ ca rj fW jS -tX +fk VS mQ ZR diff --git a/maps/tether/submaps/_tether_submaps.dm b/maps/tether/submaps/_tether_submaps.dm index 38d43844ce..0980436c8b 100644 --- a/maps/tether/submaps/_tether_submaps.dm +++ b/maps/tether/submaps/_tether_submaps.dm @@ -553,6 +553,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 \ No newline at end of file diff --git a/maps/tether/tether-03-surface3.dmm b/maps/tether/tether-03-surface3.dmm index 3212a18e84..263da6150f 100644 --- a/maps/tether/tether-03-surface3.dmm +++ b/maps/tether/tether-03-surface3.dmm @@ -272518,13 +272518,13 @@ aaa /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" = ( diff --git a/maps/tether/tether-07-station3.dmm b/maps/tether/tether-07-station3.dmm index f40c8549d0..0cd00a8eec 100644 --- a/maps/tether/tether-07-station3.dmm +++ b/maps/tether/tether-07-station3.dmm @@ -19037,7 +19037,6 @@ /turf/simulated/floor, /area/maintenance/station/ai) "aSj" = ( -/obj/structure/closet/emcloset, /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 8 }, @@ -19510,6 +19509,7 @@ /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 8 }, +/obj/structure/closet/emcloset, /turf/simulated/floor/tiled, /area/quartermaster/belterdock) "aTA" = ( @@ -23196,6 +23196,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; @@ -38495,7 +38499,7 @@ aHB aMz aBU aBU -aQG +kPM aSj aOu aOL diff --git a/maps/tether/tether_areas.dm b/maps/tether/tether_areas.dm index 8f53b49f8b..ded5e8110f 100644 --- a/maps/tether/tether_areas.dm +++ b/maps/tether/tether_areas.dm @@ -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 diff --git a/maps/tether/tether_defines.dm b/maps/tether/tether_defines.dm index 27b7b41daf..efb3f626ab 100644 --- a/maps/tether/tether_defines.dm +++ b/maps/tether/tether_defines.dm @@ -291,14 +291,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 @@ -306,7 +306,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 @@ -314,7 +314,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 @@ -351,11 +351,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 diff --git a/maps/~map_system/maps.dm b/maps/~map_system/maps.dm index 0ed8fc4b18..6e86eb8aa3 100644 --- a/maps/~map_system/maps.dm +++ b/maps/~map_system/maps.dm @@ -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) var/static/list/vorespawn_levels = list() //Z-levels where players are allowed to vore latejoin to. // End Static Lists @@ -138,8 +139,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 @@ -298,7 +301,12 @@ 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 +<<<<<<< HEAD if(flags & MAP_LEVEL_VORESPAWN) map.vorespawn_levels += z +||||||| parent of ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets +======= + if(flags & MAP_LEVEL_PERSIST) map.persist_levels += z +>>>>>>> ba346f5f63... Merge pull request #10325 from VOREStation/Arokha/persistsheets if(flags & MAP_LEVEL_EMPTY) if(!map.empty_levels) map.empty_levels = list() map.empty_levels += z diff --git a/vorestation.dme b/vorestation.dme index b2cf2c482d..29b2c90c04 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -3532,6 +3532,7 @@ #include "code\modules\persistence\filth.dm" #include "code\modules\persistence\graffiti.dm" #include "code\modules\persistence\noticeboard.dm" +<<<<<<< HEAD #include "code\modules\persistence\noticeboard_yw.dm" #include "code\modules\persistence\persistence.dm" #include "code\modules\persistence\datum\persistence_datum.dm"