From c05c57acf97bfd798dfa8c2a679d16484dc36679 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 25 Dec 2020 15:49:55 -0800 Subject: [PATCH 01/31] persistent module --- .../_persistence.dm} | 329 +++--------------- .../subsystem/persistence/panic_bunker.dm | 26 ++ .../subsystem/persistence/poly_parrot.dm | 11 + .../subsystem/persistence/recent_votes_etc.dm | 107 ++++++ .../subsystem/persistence/secret_satchels.dm | 79 +++++ .../subsystem/persistence/trophies.dm | 84 +++++ tgstation.dme | 7 +- 7 files changed, 370 insertions(+), 273 deletions(-) rename code/controllers/subsystem/{persistence.dm => persistence/_persistence.dm} (51%) create mode 100644 code/controllers/subsystem/persistence/panic_bunker.dm create mode 100644 code/controllers/subsystem/persistence/poly_parrot.dm create mode 100644 code/controllers/subsystem/persistence/recent_votes_etc.dm create mode 100644 code/controllers/subsystem/persistence/secret_satchels.dm create mode 100644 code/controllers/subsystem/persistence/trophies.dm diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm similarity index 51% rename from code/controllers/subsystem/persistence.dm rename to code/controllers/subsystem/persistence/_persistence.dm index e39242aac3..edecba311b 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -5,18 +5,9 @@ SUBSYSTEM_DEF(persistence) name = "Persistence" init_order = INIT_ORDER_PERSISTENCE flags = SS_NO_FIRE - var/list/satchel_blacklist = list() //this is a typecache - var/list/new_secret_satchels = list() //these are objects - var/list/old_secret_satchels = list() var/list/obj/structure/chisel_message/chisel_messages = list() var/list/saved_messages = list() - var/list/saved_modes = list(1,2,3) - var/list/saved_dynamic_rules = list(list(),list(),list()) - var/list/saved_storytellers = list("foo","bar","baz") - var/list/average_dynamic_threat = 50 - var/list/saved_maps - var/list/saved_trophies = list() var/list/spawned_objects = list() var/list/antag_rep = list() var/list/antag_rep_change = list() @@ -28,62 +19,71 @@ SUBSYSTEM_DEF(persistence) var/list/paintings = list() /datum/controller/subsystem/persistence/Initialize() - LoadSatchels() - LoadPoly() - LoadChiselMessages() - LoadTrophies() - LoadRecentModes() - LoadRecentStorytellers() - LoadRecentRulesets() - LoadRecentMaps() - LoadPhotoPersistence() + LoadServerPersistence() + LoadGamePersistence() + LoadMapPersistence() + return ..() + +/datum/controller/subsystem/persistence/proc/CollectData() + SaveServerPersistence() + SaveGamePersistence() + SaveMapPersistence() + +/** + * Loads persistent data relevant to the server: Configurations, past gamemodes, votes, etc + */ +/datum/controller/subsystem/persistence/proc/LoadServerPersistence() for(var/client/C in GLOB.clients) LoadSavedVote(C.ckey) if(CONFIG_GET(flag/use_antag_rep)) LoadAntagReputation() + +/** + * Saves persistent data relevant to the server: Configurations, past gamemodes, votes, etc + */ +/datum/controller/subsystem/persistence/proc/SaveServerPersistence() + if(CONFIG_GET(flag/use_antag_rep)) + CollectAntagReputation() + +/** + * Loads persistent data relevant to the game in general: Trophies, antag reputation, etc + * + * Legacy map persistence systems also use this. + */ +/datum/controller/subsystem/persistence/proc/LoadGamePersistence() + LoadChiselMessages() + LoadPhotoPersistence() LoadRandomizedRecipes() - LoadPanicBunker() - return ..() -/datum/controller/subsystem/persistence/proc/LoadSatchels() - var/placed_satchel = 0 - var/path +/** + * Saves persistent data relevant to the game in general: Trophies, antag reputation, etc + * + * Legacy map persistence systems also use this. + */ +/datum/controller/subsystem/persistence/proc/SaveGamePersistence() + SaveRandomizedRecipes() + CollectChiselMessages() + SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION. + SavePaintings() + SaveScars() - var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") - var/list/json = list() - if(fexists(json_file)) - json = json_decode(file2text(json_file)) +/** + * Loads persistent data relevant to the current map: Objects, etc. + * + * @params + * data_directory - The data directory to use. Each map with a persistence key has its own, and this is based on the persistence key. + */ +/datum/controller/subsystem/persistence/proc/LoadMapPersistence(data_directory) + return - old_secret_satchels = json["data"] - var/obj/item/storage/backpack/satchel/flat/F - if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear. - var/pos = rand(1, old_secret_satchels.len) - F = new() - old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len) - F.x = old_secret_satchels[pos]["x"] - F.y = old_secret_satchels[pos]["y"] - F.z = SSmapping.station_start - path = text2path(old_secret_satchels[pos]["saved_obj"]) - - if(F) - if(isfloorturf(F.loc) && !isplatingturf(F.loc)) - F.hide(1) - if(ispath(path)) - var/spawned_item = new path(F) - spawned_objects[spawned_item] = TRUE - placed_satchel++ - var/free_satchels = 0 - for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only - if(isfloorturf(T) && !isplatingturf(T)) - new /obj/item/storage/backpack/satchel/flat/secret(T) - free_satchels++ - if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves - break - -/datum/controller/subsystem/persistence/proc/LoadPoly() - for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list) - twitterize(P.speech_buffer, "polytalk") - break //Who's been duping the bird?! +/** + * Saves persistent data relevant to the current map: Objects, etc. + * + * @params + * data_directory - The data directory to use. Each map with a persistence key has its own, and this is based on the persistence key. + */ +/datum/controller/subsystem/persistence/proc/SaveMapPersistence(data_directory) + return /datum/controller/subsystem/persistence/proc/LoadChiselMessages() var/list/saved_messages = list() @@ -130,63 +130,6 @@ SUBSYSTEM_DEF(persistence) log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]") -/datum/controller/subsystem/persistence/proc/LoadTrophies() - if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new - var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav") - var/saved_json - S >> saved_json - if(!saved_json) - return - saved_trophies = json_decode(saved_json) - fdel("data/npc_saves/TrophyItems.sav") - else - var/json_file = file("data/npc_saves/TrophyItems.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_trophies = json["data"] - SetUpTrophies(saved_trophies.Copy()) - -/datum/controller/subsystem/persistence/proc/LoadRecentModes() - var/json_file = file("data/RecentModes.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_modes = json["data"] - -/datum/controller/subsystem/persistence/proc/LoadRecentRulesets() - var/json_file = file("data/RecentRulesets.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_dynamic_rules = json["data"] - -/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers() - var/json_file = file("data/RecentStorytellers.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_storytellers = json["data"] - if(saved_storytellers.len > 3) - average_dynamic_threat = saved_storytellers[4] - saved_storytellers.len = 3 - -/datum/controller/subsystem/persistence/proc/LoadRecentMaps() - var/json_file = file("data/RecentMaps.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_maps = json["maps"] /datum/controller/subsystem/persistence/proc/LoadAntagReputation() var/json = file2text(FILE_ANTAG_REP) @@ -207,59 +150,6 @@ SUBSYSTEM_DEF(persistence) return saved_votes[ckey] = json["data"] -/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) - for(var/A in GLOB.trophy_cases) - var/obj/structure/displaycase/trophy/T = A - if (T.showpiece) - continue - T.added_roundstart = TRUE - - var/trophy_data = pick_n_take(trophy_items) - - if(!islist(trophy_data)) - continue - - var/list/chosen_trophy = trophy_data - - if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed - continue - - var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null - if(!path) - continue - - T.showpiece = new /obj/item/showpiece_dummy(T, path) - T.trophy_message = chosen_trophy["message"] - T.placer_key = chosen_trophy["placer_key"] - T.update_icon() - -/datum/controller/subsystem/persistence/proc/CollectData() - CollectChiselMessages() - CollectSecretSatchels() - CollectTrophies() - CollectRoundtype() - if(istype(SSticker.mode, /datum/game_mode/dynamic)) - var/datum/game_mode/dynamic/mode = SSticker.mode - CollectStoryteller(mode) - CollectRulesets(mode) - RecordMaps() - SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION. - if(CONFIG_GET(flag/use_antag_rep)) - CollectAntagReputation() - SaveRandomizedRecipes() - SavePanicBunker() - SavePaintings() - SaveScars() - -/datum/controller/subsystem/persistence/proc/LoadPanicBunker() - var/bunker_path = file("data/bunker_passthrough.json") - if(fexists(bunker_path)) - var/list/json = json_decode(file2text(bunker_path)) - GLOB.bunker_passthrough = json["data"] - for(var/ckey in GLOB.bunker_passthrough) - if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days)) - GLOB.bunker_passthrough -= ckey - /datum/controller/subsystem/persistence/proc/GetPhotoAlbums() var/album_path = file("data/photo_albums.json") if(fexists(album_path)) @@ -329,35 +219,6 @@ SUBSYSTEM_DEF(persistence) WRITE_FILE(frame_path, frame_json) -/datum/controller/subsystem/persistence/proc/CollectSecretSatchels() - satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) - var/list/satchels_to_add = list() - for(var/A in new_secret_satchels) - var/obj/item/storage/backpack/satchel/flat/F = A - if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM) - continue - var/list/savable_obj = list() - for(var/obj/O in F) - if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1)) - continue - if(O.persistence_replacement) - savable_obj += O.persistence_replacement - else - savable_obj += O.type - if(isemptylist(savable_obj)) - continue - var/list/data = list() - data["x"] = F.x - data["y"] = F.y - data["saved_obj"] = pick(savable_obj) - satchels_to_add += list(data) - - var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") - var/list/file_data = list() - fdel(json_file) - file_data["data"] = old_secret_satchels + satchels_to_add - WRITE_FILE(json_file, json_encode(file_data)) - /datum/controller/subsystem/persistence/proc/CollectChiselMessages() var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json") @@ -374,82 +235,6 @@ SUBSYSTEM_DEF(persistence) saved_messages += list(M.pack()) // dm eats one list -/datum/controller/subsystem/persistence/proc/CollectTrophies() - var/json_file = file("data/npc_saves/TrophyItems.json") - var/list/file_data = list() - file_data["data"] = remove_duplicate_trophies(saved_trophies) - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/SavePanicBunker() - var/json_file = file("data/bunker_passthrough.json") - var/list/file_data = list() - file_data["data"] = GLOB.bunker_passthrough - fdel(json_file) - WRITE_FILE(json_file,json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies) - var/list/ukeys = list() - . = list() - for(var/trophy in trophies) - var/tkey = "[trophy["path"]]-[trophy["message"]]" - if(ukeys[tkey]) - continue - else - . += list(trophy) - ukeys[tkey] = TRUE - -/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T) - if(!T.added_roundstart && T.showpiece) - var/list/data = list() - data["path"] = T.showpiece.type - data["message"] = T.trophy_message - data["placer_key"] = T.placer_key - saved_trophies += list(data) - -/datum/controller/subsystem/persistence/proc/CollectRoundtype() - saved_modes[3] = saved_modes[2] - saved_modes[2] = saved_modes[1] - saved_modes[1] = SSticker.mode.config_tag - var/json_file = file("data/RecentModes.json") - var/list/file_data = list() - file_data["data"] = saved_modes - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode) - saved_storytellers.len = 3 - saved_storytellers[3] = saved_storytellers[2] - saved_storytellers[2] = saved_storytellers[1] - saved_storytellers[1] = mode.storyteller.name - average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2 - var/json_file = file("data/RecentStorytellers.json") - var/list/file_data = list() - file_data["data"] = saved_storytellers + average_dynamic_threat - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode) - saved_dynamic_rules[3] = saved_dynamic_rules[2] - saved_dynamic_rules[2] = saved_dynamic_rules[1] - saved_dynamic_rules[1] = list() - for(var/r in mode.executed_rules) - var/datum/dynamic_ruleset/rule = r - saved_dynamic_rules[1] += rule.config_tag - var/json_file = file("data/RecentRulesets.json") - var/list/file_data = list() - file_data["data"] = saved_dynamic_rules - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/RecordMaps() - saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]") - var/json_file = file("data/RecentMaps.json") - var/list/file_data = list() - file_data["maps"] = saved_maps - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - /datum/controller/subsystem/persistence/proc/CollectAntagReputation() var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum) diff --git a/code/controllers/subsystem/persistence/panic_bunker.dm b/code/controllers/subsystem/persistence/panic_bunker.dm new file mode 100644 index 0000000000..93ada2835c --- /dev/null +++ b/code/controllers/subsystem/persistence/panic_bunker.dm @@ -0,0 +1,26 @@ +/** + * Persists panic bunker whitelisting for a configured period of time + */ +/datum/controller/subsystem/persistence/LoadServerPersistence() + . = ..() + LoadPanicBunker() + +/datum/controller/subsystem/persistence/SaveServerPersistence() + . = ..() + SavePanicBunker() + +/datum/controller/subsystem/persistence/proc/LoadPanicBunker() + var/bunker_path = file("data/bunker_passthrough.json") + if(fexists(bunker_path)) + var/list/json = json_decode(file2text(bunker_path)) + GLOB.bunker_passthrough = json["data"] + for(var/ckey in GLOB.bunker_passthrough) + if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days)) + GLOB.bunker_passthrough -= ckey + +/datum/controller/subsystem/persistence/proc/SavePanicBunker() + var/json_file = file("data/bunker_passthrough.json") + var/list/file_data = list() + file_data["data"] = GLOB.bunker_passthrough + fdel(json_file) + WRITE_FILE(json_file,json_encode(file_data)) diff --git a/code/controllers/subsystem/persistence/poly_parrot.dm b/code/controllers/subsystem/persistence/poly_parrot.dm new file mode 100644 index 0000000000..64743e9623 --- /dev/null +++ b/code/controllers/subsystem/persistence/poly_parrot.dm @@ -0,0 +1,11 @@ +/** + * Persists poly messages across rounds + */ +/datum/controller/subsystem/persistence/LoadGamePersistence() + . = ..() + LoadPoly() + +/datum/controller/subsystem/persistence/proc/LoadPoly() + for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list) + twitterize(P.speech_buffer, "polytalk") + break //Who's been duping the bird?! diff --git a/code/controllers/subsystem/persistence/recent_votes_etc.dm b/code/controllers/subsystem/persistence/recent_votes_etc.dm new file mode 100644 index 0000000000..f1b902d6ab --- /dev/null +++ b/code/controllers/subsystem/persistence/recent_votes_etc.dm @@ -0,0 +1,107 @@ +/** + * Stores recently played gamemodes, maps, etc. + */ +/datum/controller/subsystem/persistence + var/list/saved_modes = list(1,2,3) + var/list/saved_dynamic_rules = list(list(),list(),list()) + var/list/saved_storytellers = list("foo","bar","baz") + var/list/average_dynamic_threat = 50 + var/list/saved_maps + +/datum/controller/subsystem/persistence/SaveServerPersistence() + . = ..() + CollectRoundtype() + if(istype(SSticker.mode, /datum/game_mode/dynamic)) + var/datum/game_mode/dynamic/mode = SSticker.mode + CollectStoryteller(mode) + CollectRulesets(mode) + RecordMaps() + +/datum/controller/subsystem/persistence/LoadServerPersistence() + . = ..() + LoadRecentModes() + LoadRecentStorytellers() + LoadRecentRulesets() + LoadRecentMaps() + +/datum/controller/subsystem/persistence/proc/CollectRoundtype() + saved_modes[3] = saved_modes[2] + saved_modes[2] = saved_modes[1] + saved_modes[1] = SSticker.mode.config_tag + var/json_file = file("data/RecentModes.json") + var/list/file_data = list() + file_data["data"] = saved_modes + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode) + saved_storytellers.len = 3 + saved_storytellers[3] = saved_storytellers[2] + saved_storytellers[2] = saved_storytellers[1] + saved_storytellers[1] = mode.storyteller.name + average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2 + var/json_file = file("data/RecentStorytellers.json") + var/list/file_data = list() + file_data["data"] = saved_storytellers + average_dynamic_threat + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode) + saved_dynamic_rules[3] = saved_dynamic_rules[2] + saved_dynamic_rules[2] = saved_dynamic_rules[1] + saved_dynamic_rules[1] = list() + for(var/r in mode.executed_rules) + var/datum/dynamic_ruleset/rule = r + saved_dynamic_rules[1] += rule.config_tag + var/json_file = file("data/RecentRulesets.json") + var/list/file_data = list() + file_data["data"] = saved_dynamic_rules + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/RecordMaps() + saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]") + var/json_file = file("data/RecentMaps.json") + var/list/file_data = list() + file_data["maps"] = saved_maps + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/LoadRecentModes() + var/json_file = file("data/RecentModes.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_modes = json["data"] + +/datum/controller/subsystem/persistence/proc/LoadRecentRulesets() + var/json_file = file("data/RecentRulesets.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_dynamic_rules = json["data"] + +/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers() + var/json_file = file("data/RecentStorytellers.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_storytellers = json["data"] + if(saved_storytellers.len > 3) + average_dynamic_threat = saved_storytellers[4] + saved_storytellers.len = 3 + +/datum/controller/subsystem/persistence/proc/LoadRecentMaps() + var/json_file = file("data/RecentMaps.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_maps = json["maps"] diff --git a/code/controllers/subsystem/persistence/secret_satchels.dm b/code/controllers/subsystem/persistence/secret_satchels.dm new file mode 100644 index 0000000000..fa2a445317 --- /dev/null +++ b/code/controllers/subsystem/persistence/secret_satchels.dm @@ -0,0 +1,79 @@ +/** + * Secret satchel persistence - allows storing of items in underfloor satchels that's loaded later. + */ +/datum/controller/subsystem/persistence + var/list/satchel_blacklist = list() //this is a typecache + var/list/new_secret_satchels = list() //these are objects + var/list/old_secret_satchels = list() + +/datum/controller/subsystem/persistence/LoadGamePersistence() + . = ..() + LoadSatchels() + +/datum/controller/subsystem/persistence/SaveGamePersistence() + . = ..() + CollectSecretSatchels() + +/datum/controller/subsystem/persistence/proc/LoadSatchels() + var/placed_satchel = 0 + var/path + + var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") + var/list/json = list() + if(fexists(json_file)) + json = json_decode(file2text(json_file)) + + old_secret_satchels = json["data"] + var/obj/item/storage/backpack/satchel/flat/F + if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear. + var/pos = rand(1, old_secret_satchels.len) + F = new() + old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len) + F.x = old_secret_satchels[pos]["x"] + F.y = old_secret_satchels[pos]["y"] + F.z = SSmapping.station_start + path = text2path(old_secret_satchels[pos]["saved_obj"]) + + if(F) + if(isfloorturf(F.loc) && !isplatingturf(F.loc)) + F.hide(1) + if(ispath(path)) + var/spawned_item = new path(F) + spawned_objects[spawned_item] = TRUE + placed_satchel++ + var/free_satchels = 0 + for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only + if(isfloorturf(T) && !isplatingturf(T)) + new /obj/item/storage/backpack/satchel/flat/secret(T) + free_satchels++ + if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves + break + +/datum/controller/subsystem/persistence/proc/CollectSecretSatchels() + satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) + var/list/satchels_to_add = list() + for(var/A in new_secret_satchels) + var/obj/item/storage/backpack/satchel/flat/F = A + if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM) + continue + var/list/savable_obj = list() + for(var/obj/O in F) + if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1)) + continue + if(O.persistence_replacement) + savable_obj += O.persistence_replacement + else + savable_obj += O.type + if(isemptylist(savable_obj)) + continue + var/list/data = list() + data["x"] = F.x + data["y"] = F.y + data["saved_obj"] = pick(savable_obj) + satchels_to_add += list(data) + + var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") + var/list/file_data = list() + fdel(json_file) + file_data["data"] = old_secret_satchels + satchels_to_add + WRITE_FILE(json_file, json_encode(file_data)) diff --git a/code/controllers/subsystem/persistence/trophies.dm b/code/controllers/subsystem/persistence/trophies.dm new file mode 100644 index 0000000000..770ca99125 --- /dev/null +++ b/code/controllers/subsystem/persistence/trophies.dm @@ -0,0 +1,84 @@ +/** + * Stores trophies in curator display cases + */ +/datum/controller/subsystem/persistence + var/list/saved_trophies = list() + +/datum/controller/subsystem/persistence/LoadGamePersistence() + . = ..() + LoadTrophies() + +/datum/controller/subsystem/persistence/SaveGamePersistence() + . = ..() + CollectTrophies() + +/datum/controller/subsystem/persistence/proc/LoadTrophies() + if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav") + var/saved_json + S >> saved_json + if(!saved_json) + return + saved_trophies = json_decode(saved_json) + fdel("data/npc_saves/TrophyItems.sav") + else + var/json_file = file("data/npc_saves/TrophyItems.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_trophies = json["data"] + SetUpTrophies(saved_trophies.Copy()) + +/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) + for(var/A in GLOB.trophy_cases) + var/obj/structure/displaycase/trophy/T = A + if (T.showpiece) + continue + T.added_roundstart = TRUE + + var/trophy_data = pick_n_take(trophy_items) + + if(!islist(trophy_data)) + continue + + var/list/chosen_trophy = trophy_data + + if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed + continue + + var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null + if(!path) + continue + + T.showpiece = new /obj/item/showpiece_dummy(T, path) + T.trophy_message = chosen_trophy["message"] + T.placer_key = chosen_trophy["placer_key"] + T.update_icon() + +/datum/controller/subsystem/persistence/proc/CollectTrophies() + var/json_file = file("data/npc_saves/TrophyItems.json") + var/list/file_data = list() + file_data["data"] = remove_duplicate_trophies(saved_trophies) + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies) + var/list/ukeys = list() + . = list() + for(var/trophy in trophies) + var/tkey = "[trophy["path"]]-[trophy["message"]]" + if(ukeys[tkey]) + continue + else + . += list(trophy) + ukeys[tkey] = TRUE + +/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T) + if(!T.added_roundstart && T.showpiece) + var/list/data = list() + data["path"] = T.showpiece.type + data["message"] = T.trophy_message + data["placer_key"] = T.placer_key + saved_trophies += list(data) diff --git a/tgstation.dme b/tgstation.dme index 07eefc79ef..a5cad8bc0a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -340,7 +340,6 @@ #include "code\controllers\subsystem\pai.dm" #include "code\controllers\subsystem\parallax.dm" #include "code\controllers\subsystem\pathfinder.dm" -#include "code\controllers\subsystem\persistence.dm" #include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" @@ -363,6 +362,12 @@ #include "code\controllers\subsystem\vis_overlays.dm" #include "code\controllers\subsystem\vore.dm" #include "code\controllers\subsystem\vote.dm" +#include "code\controllers\subsystem\persistence\_persistence.dm" +#include "code\controllers\subsystem\persistence\panic_bunker.dm" +#include "code\controllers\subsystem\persistence\poly_parrot.dm" +#include "code\controllers\subsystem\persistence\recent_votes_etc.dm" +#include "code\controllers\subsystem\persistence\secret_satchels.dm" +#include "code\controllers\subsystem\persistence\trophies.dm" #include "code\controllers\subsystem\processing\chemistry.dm" #include "code\controllers\subsystem\processing\circuit.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" From 999262665b5e152d05e920bccc6c366684e74c5f Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 25 Dec 2020 15:54:28 -0800 Subject: [PATCH 02/31] map keys --- .../subsystem/persistence/_persistence.dm | 17 +++++++++++++++-- code/modules/mapping/map_config.dm | 11 +++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index edecba311b..6cf9f84b91 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -21,13 +21,26 @@ SUBSYSTEM_DEF(persistence) /datum/controller/subsystem/persistence/Initialize() LoadServerPersistence() LoadGamePersistence() - LoadMapPersistence() + var/map_persistence_path = get_map_persistence_path() + if(map_persistence_path) + LoadMapPersistence(map_persistence_path) return ..() +/** + * Gets the persistence path of the current map. + */ +/datum/controller/subsystem/persistence/proc/get_map_persistence_path() + ASSERT(SSmapping.config) + if(SSmapping.config.persistence_key == "NO_PERSIST") + return null + return "data/persistence/[ckey(SSmapping.config.persistence_key)]" + /datum/controller/subsystem/persistence/proc/CollectData() SaveServerPersistence() SaveGamePersistence() - SaveMapPersistence() + var/map_persistence_path = get_map_persistence_path() + if(map_persistence_path) + SaveMapPersistence(map_persistence_path) /** * Loads persistent data relevant to the server: Configurations, past gamemodes, votes, etc diff --git a/code/modules/mapping/map_config.dm b/code/modules/mapping/map_config.dm index d18ca1e1e3..83418462f1 100644 --- a/code/modules/mapping/map_config.dm +++ b/code/modules/mapping/map_config.dm @@ -18,6 +18,8 @@ var/map_name = "Box Station" var/map_path = "map_files/BoxStation" var/map_file = "BoxStation.dmm" + /// Persistence key: Defaults to ckey(map_name). If set to "NO_PERSIST", this map will have NO persistence. + var/persistence_key var/traits = null var/space_ruin_levels = 4 @@ -99,6 +101,15 @@ map_path = json["map_path"] map_file = json["map_file"] + + persistence_key = ckey(map_name) + + var/json_persistence_key = json["persistence_key"] + if(json_persistence_key == "NO_PERSIST") + persistence_key = null + else + persistence_key = json_persistence_key + // "map_file": "BoxStation.dmm" if (istext(map_file)) if (!fexists("_maps/[map_path]/[map_file]")) From 5e66e4509f88c1310f7776bba5f2ea60e84b292c Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 25 Dec 2020 16:07:17 -0800 Subject: [PATCH 03/31] wew --- .../configuration/entries/persistence.dm | 17 +++++++++++++++++ .../subsystem/persistence/_persistence.dm | 3 +-- .../subsystem/persistence/cleanable_debris.dm | 3 +++ code/game/objects/effects/decals/cleanable.dm | 17 +++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 code/controllers/configuration/entries/persistence.dm create mode 100644 code/controllers/subsystem/persistence/cleanable_debris.dm diff --git a/code/controllers/configuration/entries/persistence.dm b/code/controllers/configuration/entries/persistence.dm new file mode 100644 index 0000000000..cf7b23bef3 --- /dev/null +++ b/code/controllers/configuration/entries/persistence.dm @@ -0,0 +1,17 @@ +/// Whether or not to use the persistence system for cleanable objects +/datum/config_entry/flag/persistent_debris + config_entry_value = FALSE + +/// Whether or not to nuke all roundstart debris that isn't due to persistence if the above is true +/datum/config_entry/flag/persistent_debris_only + config_entry_value = TRUE + +/// Max amount of objects to store, total +/datum/config_entry/number/persistent_debris_global_max + config_entry_value = 10000 + integer = TRUE + +/// Max amount of objects to store per type +/datum/config_entry/number/persistent_debris_type_max + config_entry_value = 2000 + integer = TRUE diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index 6cf9f84b91..a950a78f2b 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -67,6 +67,7 @@ SUBSYSTEM_DEF(persistence) LoadChiselMessages() LoadPhotoPersistence() LoadRandomizedRecipes() + LoadPaintings() /** * Saves persistent data relevant to the game in general: Trophies, antag reputation, etc @@ -247,8 +248,6 @@ SUBSYSTEM_DEF(persistence) /datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M) saved_messages += list(M.pack()) // dm eats one list - - /datum/controller/subsystem/persistence/proc/CollectAntagReputation() var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm new file mode 100644 index 0000000000..1e3390357b --- /dev/null +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -0,0 +1,3 @@ +/** + * Persistence for cleanable debris. + */ diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 34996177af..cadda8da00 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -1,6 +1,9 @@ /obj/effect/decal/cleanable gender = PLURAL layer = ABOVE_NORMAL_TURF_LAYER + /// Is this kind of cleanable decal persistent + var/persistent = FALSE + var/list/random_icon_states = null var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints @@ -9,6 +12,8 @@ /obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) . = ..() + if(mapload && persistent && CONFIG_GET(flag/persistent_debris_only)) + return INITIALIZE_HINT_QDEL LAZYINITLIST(blood_DNA) //Kinda needed if (random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0) icon_state = pick(random_icon_states) @@ -29,6 +34,18 @@ addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0) +/** + * Returns a list of data + */ +/obj/effect/decal/cleanable/proc/PersistenceSave() + return null + +/** + * Laods from a data list. + */ +/obj/effect/decal/cleanable/proc/PersistenceLoad(list/data) + return + /obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal if(mergeable_decal) qdel(C) From d5ab4b79dcda45ee422a53243cf0e5a7afac2d78 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 25 Dec 2020 16:07:29 -0800 Subject: [PATCH 04/31] dme --- tgstation.dme | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tgstation.dme b/tgstation.dme index a5cad8bc0a..4fca500006 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -292,6 +292,7 @@ #include "code\controllers\configuration\entries\fail2topic.dm" #include "code\controllers\configuration\entries\game_options.dm" #include "code\controllers\configuration\entries\general.dm" +#include "code\controllers\configuration\entries\persistence.dm" #include "code\controllers\configuration\entries\plushies.dm" #include "code\controllers\configuration\entries\policy.dm" #include "code\controllers\configuration\entries\resources.dm" @@ -363,6 +364,7 @@ #include "code\controllers\subsystem\vore.dm" #include "code\controllers\subsystem\vote.dm" #include "code\controllers\subsystem\persistence\_persistence.dm" +#include "code\controllers\subsystem\persistence\cleanable_debris.dm" #include "code\controllers\subsystem\persistence\panic_bunker.dm" #include "code\controllers\subsystem\persistence\poly_parrot.dm" #include "code\controllers\subsystem\persistence\recent_votes_etc.dm" From 5cf717e75da31bd21bbb5ca8446d414ec65937cd Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 25 Dec 2020 16:10:32 -0800 Subject: [PATCH 05/31] self message --- code/game/objects/effects/decals/cleanable.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index cadda8da00..63f17d61ee 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -12,7 +12,8 @@ /obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) . = ..() - if(mapload && persistent && CONFIG_GET(flag/persistent_debris_only)) + #warn OPTIMIZE THE BELOW LINE, CACHE THINGS, THIS IS INSANELY EXPENSIVE + if(mapload && persistent && CONFIG_GET(flag/persistent_debris_only) && (z in SSmapping.levels_by_trait(ZTRAIT_STATION))) return INITIALIZE_HINT_QDEL LAZYINITLIST(blood_DNA) //Kinda needed if (random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0) From 45af2360addcdd33803a0289e14a7f452da67a4f Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 11:35:47 -0800 Subject: [PATCH 06/31] changes --- .../subsystem/persistence/_persistence.dm | 14 ++---- .../subsystem/persistence/cleanable_debris.dm | 46 +++++++++++++++++++ code/game/area/Space_Station_13_areas.dm | 1 + code/game/area/areas.dm | 2 + code/game/objects/effects/decals/cleanable.dm | 14 +++--- .../objects/effects/decals/cleanable/misc.dm | 29 ++++++++++++ code/game/objects/effects/decals/crayon.dm | 26 +++++++++++ 7 files changed, 116 insertions(+), 16 deletions(-) diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index a950a78f2b..00135bbcc2 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(persistence) LoadGamePersistence() var/map_persistence_path = get_map_persistence_path() if(map_persistence_path) - LoadMapPersistence(map_persistence_path) + LoadMapPersistence() return ..() /** @@ -40,7 +40,7 @@ SUBSYSTEM_DEF(persistence) SaveGamePersistence() var/map_persistence_path = get_map_persistence_path() if(map_persistence_path) - SaveMapPersistence(map_persistence_path) + SaveMapPersistence() /** * Loads persistent data relevant to the server: Configurations, past gamemodes, votes, etc @@ -83,20 +83,14 @@ SUBSYSTEM_DEF(persistence) /** * Loads persistent data relevant to the current map: Objects, etc. - * - * @params - * data_directory - The data directory to use. Each map with a persistence key has its own, and this is based on the persistence key. */ -/datum/controller/subsystem/persistence/proc/LoadMapPersistence(data_directory) +/datum/controller/subsystem/persistence/proc/LoadMapPersistence() return /** * Saves persistent data relevant to the current map: Objects, etc. - * - * @params - * data_directory - The data directory to use. Each map with a persistence key has its own, and this is based on the persistence key. */ -/datum/controller/subsystem/persistence/proc/SaveMapPersistence(data_directory) +/datum/controller/subsystem/persistence/proc/SaveMapPersistence() return /datum/controller/subsystem/persistence/proc/LoadChiselMessages() diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 1e3390357b..13c80aee57 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -1,3 +1,49 @@ /** * Persistence for cleanable debris. */ +/datum/controller/subsystem/persistence + /// tracks if we already loaded debris. Unlike everything else, this can actually be a major problem if some badmin procs it twice. + var/loaded_debris = FALSE + +/datum/controller/subsystem/persistence/LoadMapPersistence() + . = ..() + if(CONFIG_GET(flag/persistent_debris)) + LoadMapDebris() + +/datum/controller/subsystem/persistence/SaveMapPersistence() + . = ..() + if(CONFIG_GET(flag/persistent_debris)) + SaveMapDebris() + +/datum/controller/subsystem/persistence/proc/LoadMapDebris() + if(!fexists("[get_map_persistence_path()]/debris.json")) + return + if(loaded_debris) + return + loaded_debris = TRUE + var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json")) + + +/datum/controller/subsystem/persistence/proc/SaveMapDebris() + if(fexists("[get_map_persistence_path()]/debris.json")) + fdel("[get_map_persistence_path()]/debris.json") + var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) + var/list/allowed_z_cache = list() + for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) + allowed_z_cache[num2text(z)] = TRUE + var/list/data = list() + + WRITE_FILE("[get_map_persistence_path()]/debris.json", json_encode(data)) + + +/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache) + if(!allowed_typecache[tile.type]) + return FALSE + if(!tile.loc.persistent_debris_allowed) + return FALSE + if(!allowed_zcache[num2text(tile.z)]) + return FALSE + for(var/obj/structure/window/W in tile) + if(W.fulltile) + return FALSE + return TRUE diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index 5310b24202..03a2309e8a 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -41,6 +41,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station power_environ = FALSE valid_territory = FALSE outdoors = TRUE + persistent_debris_allowed = FALSE ambientsounds = SPACE blob_allowed = FALSE //Eating up space doesn't count for victory as a blob. considered_hull_exterior = TRUE diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index b9415f3cf8..fcde2bd1eb 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -24,6 +24,8 @@ var/clockwork_warp_allowed = TRUE /// Message to display when the clockwork warp fails var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)" + /// Persistent debris alowed + var/persistent_debris_allowed = TRUE /// If mining tunnel generation is allowed in this area var/tunnel_allowed = FALSE diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 63f17d61ee..1ad2173f76 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -3,6 +3,8 @@ layer = ABOVE_NORMAL_TURF_LAYER /// Is this kind of cleanable decal persistent var/persistent = FALSE + /// Can we stack multiple in one tile? + var/persistence_allow_stacking = FALSE var/list/random_icon_states = null var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA @@ -36,20 +38,20 @@ addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0) /** - * Returns a list of data + * A data list is passed into this. + * This should return null to skip saving, or the type of data to save. Type must be /cleanable. */ -/obj/effect/decal/cleanable/proc/PersistenceSave() - return null +/obj/effect/decal/cleanable/proc/PersistenceSave(list/data) + return type /** - * Laods from a data list. + * Loads from a data list. */ /obj/effect/decal/cleanable/proc/PersistenceLoad(list/data) return /obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal - if(mergeable_decal) - qdel(C) + return mergeable_decal /obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks)) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 044c5c6e86..9c0fb2eca9 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -12,6 +12,8 @@ icon_state = "ash" mergeable_decal = FALSE beauty = -50 + persistent = TRUE + persistence_allow_stacking = TRUE /obj/effect/decal/cleanable/ash/Initialize() . = ..() @@ -38,6 +40,8 @@ icon = 'icons/obj/shards.dmi' icon_state = "tiny" beauty = -100 + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/glass/Initialize() . = ..() @@ -94,6 +98,8 @@ light_color = LIGHT_COLOR_GREEN icon_state = "greenglow" beauty = -300 + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/greenglow/Initialize(mapload) . = ..() @@ -122,6 +128,8 @@ icon_state = "molten" mergeable_decal = FALSE beauty = -150 + persistent = TRUE + persistence_allow_stacking = TRUE /obj/effect/decal/cleanable/molten_object/large name = "big gooey grey mass" @@ -136,6 +144,7 @@ icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") beauty = -150 + persistent = TRUE /obj/effect/decal/cleanable/vomit/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(ishuman(user)) @@ -151,6 +160,10 @@ reagents.trans_to(H, reagents.total_volume) qdel(src) +/obj/effect/decal/cleanable/vomit/PersistenceSave(list/data) + . = ..() + return /obj/effect/decal/cleanable/vomit/old + /obj/effect/decal/cleanable/vomit/old name = "crusty dried vomit" desc = "You try not to look at the chunks, and fail." @@ -166,12 +179,16 @@ icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") beauty = -100 + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/plant_smudge name = "plant smudge" gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_plant") + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/egg_smudge name = "smashed egg" @@ -179,6 +196,8 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3") + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/pie_smudge //honk name = "smashed pie" @@ -186,6 +205,8 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_pie") + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/chem_pile name = "chemical pile" @@ -193,6 +214,8 @@ gender = NEUTER icon = 'icons/obj/objects.dmi' icon_state = "ash" + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/shreds name = "shreds" @@ -200,6 +223,8 @@ icon_state = "shreds" gender = PLURAL mergeable_decal = FALSE + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/shreds/ex_act(severity, target) if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion. @@ -222,6 +247,8 @@ desc = "The herpes of arts and crafts." icon = 'icons/effects/atmospherics.dmi' gender = NEUTER + mergeable_decal = TRUE + persistent = TRUE /obj/effect/decal/cleanable/glitter/pink name = "pink glitter" @@ -247,3 +274,5 @@ icon = 'icons/effects/blood.dmi' icon_state = "xfloor1" random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7") + mergeable_decal = TRUE + persistent = TRUE diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 8cfdad0432..d62f8fccb6 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -5,6 +5,8 @@ icon_state = "rune1" plane = ABOVE_WALL_PLANE //makes the graffiti visible over a wall. gender = NEUTER + persistent = TRUE + persistence_allow_stacking = TRUE mergeable_decal = FALSE var/do_icon_rotate = TRUE var/rotation = 0 @@ -29,3 +31,27 @@ if(main) paint_colour = main add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY) + +/obj/effect/decal/cleanable/crayon/PersistenceSave(list/data) + . = ..() + if(icon != initial(icon)) // no support for alticons yet, awful system anyways + return null + data["icon_state"] = icon_stsate + data["paint_color"] = paint_colour + if(do_icon_rotate) + data["rotation"] = rotation + data["name"] = name + +/obj/effect/decal/cleanable/crayon/PersistenceLoad(list/data) + . = ..() + if(data["name"]) + name = data["name"] + if(do_icon_rotate && data["rotation"]) + var/matrix/M = matrix() + M.turn(data["rotation"]) + transform = M + if(data["paint_color"]) + paint_colour = data["paint_color"]) + add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY) + if(data["icon_state"]) + icon_state = data["icon_state"] From d474643debad991e371a8f7e910e256be2b82b52 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 11:41:25 -0800 Subject: [PATCH 07/31] changes --- code/controllers/subsystem/mapping.dm | 10 ++++++++++ .../subsystem/persistence/cleanable_debris.dm | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 2ea3b29c91..3d45672c3b 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -41,6 +41,8 @@ SUBSYSTEM_DEF(mapping) var/datum/space_level/transit var/datum/space_level/empty_space var/num_of_res_levels = 1 + /// Lookup for zlevel to station z. text = num. + var/list/z_to_station_z_index var/stat_map_name = "Loading..." @@ -259,6 +261,12 @@ SUBSYSTEM_DEF(mapping) INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!") return parsed_maps +/datum/controller/subsystem/mapping/proc/setup_station_z_index() + z_to_station_z_index = list() + var/sz = 1 + for(var/i in station_start to (station_Start + islist(config.map_file)? (length(config.map_file) - 1) : 0)) + z_to_station_z_index["[i]"] = sz++ + /datum/controller/subsystem/mapping/proc/loadWorld() //if any of these fail, something has gone horribly, HORRIBLY, wrong var/list/FailedZs = list() @@ -271,6 +279,8 @@ SUBSYSTEM_DEF(mapping) INIT_ANNOUNCE("Loading [config.map_name]...") LoadGroup(FailedZs, "Station", config.map_path, config.map_file, config.traits, ZTRAITS_STATION, FALSE, config.orientation) + setup_station_z_index() + if(SSdbcore.Connect()) var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]") query_round_map_name.Execute() diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 13c80aee57..c4ef98121b 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -22,7 +22,11 @@ return loaded_debris = TRUE var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json")) - + var/list/z_lookup = list() + /// reverse it + for(var/z in SSmapping.z_to_station_z_index) + var/sz = SSmapping.z_to_station_z_index[z] + z_lookup[num2text(sz)] = z /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) @@ -32,6 +36,7 @@ for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) allowed_z_cache[num2text(z)] = TRUE var/list/data = list() + var/list/z_lookup = SSmapping.z_to_station_z_index WRITE_FILE("[get_map_persistence_path()]/debris.json", json_encode(data)) From 338869f6ad5913d6542c1818e6b07c22e1b00448 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 11:48:28 -0800 Subject: [PATCH 08/31] changes --- .../subsystem/persistence/cleanable_debris.dm | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index c4ef98121b..6f85436df8 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -21,12 +21,31 @@ if(loaded_debris) return loaded_debris = TRUE + var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) + var/list/allowed_z_cache = list() var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json")) var/list/z_lookup = list() /// reverse it for(var/z in SSmapping.z_to_station_z_index) var/sz = SSmapping.z_to_station_z_index[z] z_lookup[num2text(sz)] = z + for(var/z in data) + var/actual_z = z_lookup[z] + var/list/L1 = data[z] + for(var/x in L1) + var/list/L2 = data[z][x] + for(var/y in L2) + var/turf/tile = locate(x, y, z) + if(!tile) + continue + var/list/objects = data[z][x][y] + for(var/path in objects) + if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) + continue + var/obj/effect/cleanable/instantiated = new path(tile) + var/list/data = objects[path] + if(data) + instantiated.PersistenceLoad(data) /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) @@ -38,16 +57,22 @@ var/list/data = list() var/list/z_lookup = SSmapping.z_to_station_z_index + WRITE_FILE("[get_map_persistence_path()]/debris.json", json_encode(data)) - -/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache) +/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, type, loading = FALSE) if(!allowed_typecache[tile.type]) return FALSE if(!tile.loc.persistent_debris_allowed) return FALSE if(!allowed_zcache[num2text(tile.z)]) return FALSE + if(loading) + if(!initial(type.persistence_allow_stacking)) + var/obj/effect/cleanable/C = locate(type) in tile + if(!QDELETED(C)) + return FALSE + // Saving verifies allow stacking in the save proc. for(var/obj/structure/window/W in tile) if(W.fulltile) return FALSE From 5c0b4f824f81560fad4f1bf0916890c94969167e Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 12:42:03 -0800 Subject: [PATCH 09/31] hoh boy --- code/controllers/subsystem/mapping.dm | 2 +- .../subsystem/persistence/cleanable_debris.dm | 88 +++++++++++++++++-- code/game/objects/effects/decals/cleanable.dm | 3 - code/game/objects/effects/decals/crayon.dm | 4 +- 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 3d45672c3b..1893e9ccd9 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -264,7 +264,7 @@ SUBSYSTEM_DEF(mapping) /datum/controller/subsystem/mapping/proc/setup_station_z_index() z_to_station_z_index = list() var/sz = 1 - for(var/i in station_start to (station_Start + islist(config.map_file)? (length(config.map_file) - 1) : 0)) + for(var/i in station_start to (station_start + islist(config.map_file)? (length(config.map_file) - 1) : 0)) z_to_station_z_index["[i]"] = sz++ /datum/controller/subsystem/mapping/proc/loadWorld() diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 6f85436df8..8b8cd55d0d 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -21,8 +21,12 @@ if(loaded_debris) return loaded_debris = TRUE + if(CONFIG_GET(flag/persistent_debris_only)) + wipe_existing_debris() var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) var/list/allowed_z_cache = list() + for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) + allowed_z_cache[num2text(z)] = TRUE var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json")) var/list/z_lookup = list() /// reverse it @@ -39,31 +43,78 @@ if(!tile) continue var/list/objects = data[z][x][y] - for(var/path in objects) + for(var/_L in objects) + var/list/data + var/path + if(islist(_L)) + data = _L + path = data["__PATH__"] + else + path = _L + data = objects[_L] if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) continue + var/path = data["__PATH__"] + if(!path) + continue var/obj/effect/cleanable/instantiated = new path(tile) - var/list/data = objects[path] if(data) - instantiated.PersistenceLoad(data) + instantiated.LoadPersistence(data) /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) fdel("[get_map_persistence_path()]/debris.json") - var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) - var/list/allowed_z_cache = list() - for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) - allowed_z_cache[num2text(z)] = TRUE var/list/data = list() var/list/z_lookup = SSmapping.z_to_station_z_index + var/list/debris = RelevantPersistentDebris() + var/obj/effect/cleanable/saving + var/global_max = CONFIG_GET(number/persistent_debris_global_max) + var/type_max = CONFIG_GET(number/persistent_debris_type_max) + var/stored = 0 + var/list/stored_by_type = list() + for(var/i in debris) + saving = i + var/list/serializing = list() + var/path = saving.PersistenceSave(serializing) + if(!path) + continue + if(stored_by_type[path] > type_max) + continue + var/text_z = num2text(saving.z) + var/text_y = num2text(saving.y) + var/text_x = num2text(saving.x) + LAZYINITLIST(data[text_z]) + LAZYINITLIST(data[text_z][text_x]) + LAZYINITLIST(data[text_z][text_x][text_y]) + if(storing.persistence_allow_stacking) + serializing["__PATH__"] = path + data[text_z][text_x][text_y] += serializing + else + data[text_z][text_x][text_y][path] = serializing + stored++ + if(stored > global_max) + var/w = "Persistent debris saving globally aborted due to global max >= [global_max]. Either janitors never do their jobs or something is wrong." + message_admins(w) + subsystem_log(w)) + return + stored_by_type[path] = stored_by_type[path]? stored_by_type[path] + 1 : 1 + if(stored_by_type[path] > type_max) + var/w = "Persistent debris saving aborted for type [path] due to type max >= [global_max]. Either janitors never do their jobs or something is wrong." + message_admins(w) + subsystem_log(w)) - + subsystem_log({" + Debris saving completed: + Total: [global_max] + By type: [english_list(stored_by_type)] + "}) WRITE_FILE("[get_map_persistence_path()]/debris.json", json_encode(data)) /datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, type, loading = FALSE) if(!allowed_typecache[tile.type]) return FALSE - if(!tile.loc.persistent_debris_allowed) + var/area/A = tile.loc + if(!A.persistent_debris_allowed) return FALSE if(!allowed_zcache[num2text(tile.z)]) return FALSE @@ -77,3 +128,22 @@ if(W.fulltile) return FALSE return TRUE + +/datum/controller/subsystem/persistence/proc/wipe_existing_debris() + var/list/existing = RelevantPersistentDebris() + QDEL_LIST(existing) + +/datum/controller/subsystem/persistence/proc/RelevantPersistentDebris() + var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) + var/list/allowed_z_cache = list() + for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) + allowed_z_cache[num2text(z)] = TRUE + . = list() + for(var/obj/effect/cleanable/C in world) + if(!C.loc || QDELETED(C)) + continue + if(!C.persistent) + continue + if(!IsValidDebrisLocation(C.loc, allowed_turf_typecache, allowed_z_cache, C.type, FALSE)) + continue + . += C diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 1ad2173f76..11d76d3cdf 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -14,9 +14,6 @@ /obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) . = ..() - #warn OPTIMIZE THE BELOW LINE, CACHE THINGS, THIS IS INSANELY EXPENSIVE - if(mapload && persistent && CONFIG_GET(flag/persistent_debris_only) && (z in SSmapping.levels_by_trait(ZTRAIT_STATION))) - return INITIALIZE_HINT_QDEL LAZYINITLIST(blood_DNA) //Kinda needed if (random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0) icon_state = pick(random_icon_states) diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index d62f8fccb6..6ebd798e40 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -36,7 +36,7 @@ . = ..() if(icon != initial(icon)) // no support for alticons yet, awful system anyways return null - data["icon_state"] = icon_stsate + data["icon_state"] = icon_state data["paint_color"] = paint_colour if(do_icon_rotate) data["rotation"] = rotation @@ -51,7 +51,7 @@ M.turn(data["rotation"]) transform = M if(data["paint_color"]) - paint_colour = data["paint_color"]) + paint_colour = data["paint_color"] add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY) if(data["icon_state"]) icon_state = data["icon_state"] From a5bcd0457ead82cc7bb02dba3ed20a6ce2318a2b Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 12:48:10 -0800 Subject: [PATCH 10/31] hoh boy --- .../subsystem/persistence/cleanable_debris.dm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 8b8cd55d0d..772091529a 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -57,9 +57,9 @@ var/path = data["__PATH__"] if(!path) continue - var/obj/effect/cleanable/instantiated = new path(tile) + var/obj/effect/decal/cleanable/instantiated = new path(tile) if(data) - instantiated.LoadPersistence(data) + instantiated.PersistenceLoad(data) /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) @@ -67,7 +67,7 @@ var/list/data = list() var/list/z_lookup = SSmapping.z_to_station_z_index var/list/debris = RelevantPersistentDebris() - var/obj/effect/cleanable/saving + var/obj/effect/decal/cleanable/saving var/global_max = CONFIG_GET(number/persistent_debris_global_max) var/type_max = CONFIG_GET(number/persistent_debris_type_max) var/stored = 0 @@ -95,13 +95,13 @@ if(stored > global_max) var/w = "Persistent debris saving globally aborted due to global max >= [global_max]. Either janitors never do their jobs or something is wrong." message_admins(w) - subsystem_log(w)) + subsystem_log(w) return stored_by_type[path] = stored_by_type[path]? stored_by_type[path] + 1 : 1 if(stored_by_type[path] > type_max) var/w = "Persistent debris saving aborted for type [path] due to type max >= [global_max]. Either janitors never do their jobs or something is wrong." message_admins(w) - subsystem_log(w)) + subsystem_log(w) subsystem_log({" Debris saving completed: @@ -110,7 +110,7 @@ "}) WRITE_FILE("[get_map_persistence_path()]/debris.json", json_encode(data)) -/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, type, loading = FALSE) +/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, obj/effect/decal/cleanable/type, loading = FALSE) if(!allowed_typecache[tile.type]) return FALSE var/area/A = tile.loc @@ -120,7 +120,7 @@ return FALSE if(loading) if(!initial(type.persistence_allow_stacking)) - var/obj/effect/cleanable/C = locate(type) in tile + var/obj/effect/decal/cleanable/C = locate(type) in tile if(!QDELETED(C)) return FALSE // Saving verifies allow stacking in the save proc. @@ -139,7 +139,7 @@ for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) allowed_z_cache[num2text(z)] = TRUE . = list() - for(var/obj/effect/cleanable/C in world) + for(var/obj/effect/decal/cleanable/C in world) if(!C.loc || QDELETED(C)) continue if(!C.persistent) From 9f130e0c5a4bedfd6b6e5d0d3d47b5ddcd1dd80c Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 14:09:10 -0800 Subject: [PATCH 11/31] blood --- .../objects/effects/decals/cleanable/gibs.dm | 19 +++++++ .../effects/decals/cleanable/humans.dm | 57 ++++++++++++++++++- .../effects/decals/cleanable/robots.dm | 4 ++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm index 7df0153ddc..1f9897071c 100644 --- a/code/game/objects/effects/decals/cleanable/gibs.dm +++ b/code/game/objects/effects/decals/cleanable/gibs.dm @@ -6,6 +6,7 @@ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") mergeable_decal = FALSE bloodiness = 0 //This isn't supposed to be bloody. + persistent = TRUE var/body_colors = "#e3ba84" //a default color just in case. var/gibs_reagent_id = /datum/reagent/liquidgibs var/gibs_bloodtype = "A+" @@ -31,6 +32,10 @@ flesh.color = body_colors add_overlay(flesh) +/obj/effect/decal/cleanable/blood/gibs/PersistenceSave(list/data) + . = ..() + return /obj/effect/decal/cleanable/blood/gibs/old + /obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target) return @@ -92,6 +97,8 @@ icon_state = "1" random_icon_states = list("drip1","drip2","drip3","drip4","drip5") bloodiness = 0 + persistent = TRUE + persistence_allow_stacking = TRUE var/drips = 1 /obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in() @@ -159,6 +166,10 @@ . = ..() update_icon() +/obj/effect/decal/cleanable/blood/gibs/slime/PersistenceSave(list/data) + . = ..() + return type + /obj/effect/decal/cleanable/blood/gibs/slime/update_icon() add_atom_colour(body_colors, FIXED_COLOUR_PRIORITY) cut_overlays() @@ -198,6 +209,10 @@ . = ..() update_icon() +/obj/effect/decal/cleanable/blood/gibs/synth/PersistenceSave(list/data) + . = ..() + return type + //IPCs /obj/effect/decal/cleanable/blood/gibs/ipc desc = "They look sharp yet oozing." @@ -209,6 +224,10 @@ . = ..() update_icon() +/obj/effect/decal/cleanable/blood/gibs/ipc/PersistenceSave(list/data) + . = ..() + return type + /obj/effect/decal/cleanable/blood/gibs/ipc/update_icon() add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY) cut_overlays() diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index fa16a95faf..5d514bc68f 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -8,6 +8,7 @@ bloodiness = BLOOD_AMOUNT_PER_DECAL color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere. beauty = -100 + persistent = TRUE /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) if (C.blood_DNA) @@ -24,7 +25,20 @@ update_icon() /obj/effect/decal/cleanable/blood/update_icon() - color = blood_DNA_to_color() + . = ..() + if(!fixed_color) + add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY) + +/obj/effect/decal/cleanable/blood/PersistenceSave(list/data) + . = ..() + data["color"] = color + return /obj/effect/decal/cleanable/blood/old + +/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data) + . = ..() + if(data["color"]) + fixed_color = TRUE + add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY) /obj/effect/decal/cleanable/blood/old name = "dried blood" @@ -38,6 +52,7 @@ /obj/effect/decal/cleanable/blood/splats random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5") + persistence_allow_stacking = TRUE /obj/effect/decal/cleanable/blood/splatter random_icon_states = list("splatter1", "splatter2", "splatter3", "splatter4", "splatter5") @@ -48,16 +63,43 @@ random_icon_states = null beauty = -50 +/obj/effect/decal/cleanable/blood/tracks/PersistenceSave(list/data) + . = ..() + data["dir"] = dir + +/obj/effect/decal/cleanable/blood/tracks/PersistenceLoad(list/data) + . = ..() + if(data["dir"]) + setDir(data["dir"]) + /obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose name = "blood" icon_state = "ltrails_1" desc = "Your instincts say you shouldn't be following these." random_icon_states = null beauty = -50 + persistent = TRUE + persistence_allow_stacking = TRUE var/list/existing_dirs = list() + var/fixed_color = FALSE + +/obj/effect/decal/cleanable/trail_holder/PersistenceSave(list/data) + . = ..() + data["dir"] = dir + data["color"] = color + +/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data) + . = ..() + if(data["dir"]) + setDir(data["dir"]) + if(data["color"]) + fixed_color = TRUE + add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY) /obj/effect/decal/cleanable/trail_holder/update_icon() - color = blood_DNA_to_color() + . = ..() + if(!fixed_color) + add_atom_colour(blood_DNA_to_color()) /obj/effect/cleanable/trail_holder/Initialize() . = ..() @@ -84,8 +126,19 @@ var/entered_dirs = 0 var/exited_dirs = 0 blood_state = BLOOD_STATE_BLOOD //the icon state to load images from + persistent = TRUE + persistence_allow_stacking = TRUE var/list/shoe_types = list() +/obj/effect/decal/cleanable/blood/footprints/PersistenceSave(list/data) + . = ..() + data["dir"] = dir + +/obj/effect/decal/cleanable/blood/footprints/PersistenceLoad(list/data) + . = ..() + if(data["dir"]) + setDir(data["dir"]) + /obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O) if(ishuman(O)) var/mob/living/carbon/human/H = O diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index 2765330977..8f8f27c3c6 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -11,6 +11,7 @@ bloodiness = BLOOD_AMOUNT_PER_DECAL mergeable_decal = FALSE beauty = -50 + persistent = TRUE /obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -52,6 +53,7 @@ blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL beauty = -100 + persistent = TRUE /obj/effect/decal/cleanable/oil/Initialize() . = ..() @@ -61,8 +63,10 @@ /obj/effect/decal/cleanable/oil/streak random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5") beauty = -50 + persistent = TRUE /obj/effect/decal/cleanable/oil/slippery + persistent = FALSE /obj/effect/decal/cleanable/oil/slippery/Initialize() AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE)) From b7cd14b41e5faa101705e8296c1b0050112cecb8 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:09:24 -0800 Subject: [PATCH 12/31] poggy? --- code/controllers/subsystem/persistence/cleanable_debris.dm | 2 +- code/game/objects/effects/decals/cleanable/humans.dm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 772091529a..dccc609ed3 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -86,7 +86,7 @@ LAZYINITLIST(data[text_z]) LAZYINITLIST(data[text_z][text_x]) LAZYINITLIST(data[text_z][text_x][text_y]) - if(storing.persistence_allow_stacking) + if(saving.persistence_allow_stacking) serializing["__PATH__"] = path data[text_z][text_x][text_y] += serializing else diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 5d514bc68f..5206279d42 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -9,6 +9,7 @@ color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere. beauty = -100 persistent = TRUE + var/fixed_color = FALSE /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) if (C.blood_DNA) From 6044086de034a9aeae81be11f53c39a24a773878 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:29:52 -0800 Subject: [PATCH 13/31] changes --- code/game/area/areas.dm | 2 ++ .../objects/effects/decals/cleanable/misc.dm | 18 ++++++++++++++++ code/game/turfs/open.dm | 7 +++++++ code/game/turfs/simulated/chasm.dm | 1 + code/game/turfs/simulated/dirtystation.dm | 5 ++++- code/game/turfs/simulated/floor.dm | 1 + code/game/turfs/simulated/lava.dm | 1 + code/game/turfs/simulated/reebe_void.dm | 1 + code/game/turfs/space/space.dm | 1 + code/modules/mob/living/living_defines.dm | 2 ++ code/modules/mob/living/living_movement.dm | 21 +++++++++++++++++++ 11 files changed, 59 insertions(+), 1 deletion(-) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index fcde2bd1eb..ff177898cb 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -26,6 +26,8 @@ var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)" /// Persistent debris alowed var/persistent_debris_allowed = TRUE + /// Dirty flooring allowed + var/dirt_buildup_allowed = TRUE /// If mining tunnel generation is allowed in this area var/tunnel_allowed = FALSE diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 9c0fb2eca9..e3f223f380 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -57,10 +57,28 @@ name = "dirt" desc = "Someone should clean that up." icon_state = "dirt" + alpha = 127 canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall) smooth = SMOOTH_FALSE mouse_opacity = MOUSE_OPACITY_TRANSPARENT beauty = -75 + mergeable_decal = TRUE + persistent = TRUE + +/obj/effect/decal/cleanable/dirt/proc/dirty(strength) + if(alpha < 255) + alpha += strength + if(alpha > 255) + alpha = 255 + +/obj/effect/decal/cleanable/dirt/PersistenceSave(list/data) + . = ..() + data["alpha"] = alpha + +/obj/effect/decal/cleanable/dirt/PersistenceLoad(list/data) + . = ..() + if(data["alpha"]) + alpha = data["alpha"] /obj/effect/decal/cleanable/dirt/Initialize() . = ..() diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 493e88d442..15f5738033 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -1,5 +1,12 @@ /turf/open plane = FLOOR_PLANE + /// Does dirt buildup happen on us? + var/dirt_buildup_allowed = FALSE + /// Dirt level. + var/dirtyness = 0 + /// Dirt level to spawn dirt. + var/dirt_spawn_threshold = 100 + /// Slowdown applied to mobs on us. var/slowdown = 0 //negative for faster, positive for slower var/postdig_icon_change = FALSE diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm index 5e8f55feed..9490d728fe 100644 --- a/code/game/turfs/simulated/chasm.dm +++ b/code/game/turfs/simulated/chasm.dm @@ -9,6 +9,7 @@ canSmoothWith = list(/turf/open/floor/fakepit, /turf/open/chasm) density = TRUE //This will prevent hostile mobs from pathing into chasms, while the canpass override will still let it function like an open turf bullet_bounce_sound = null //abandon all hope ye who enter + dirt_buildup_allowed = FALSE /turf/open/chasm/Initialize() . = ..() diff --git a/code/game/turfs/simulated/dirtystation.dm b/code/game/turfs/simulated/dirtystation.dm index e29d75a248..add8467ceb 100644 --- a/code/game/turfs/simulated/dirtystation.dm +++ b/code/game/turfs/simulated/dirtystation.dm @@ -8,6 +8,9 @@ //Making the station dirty, one tile at a time. Called by master controller's setup_objects /turf/open/floor/proc/MakeDirty() + if(CONFIG_GET(flag/persistent_debris_only)) + return + if(prob(66)) //fastest possible exit 2/3 of the time return @@ -38,7 +41,7 @@ return //Construction zones. Blood, sweat, and oil. Oh, and dirt. - var/static/list/engine_dirt_areas = typecacheof(list(/area/engine, + var/static/list/engine_dirt_areas = typecacheof(list(/area/engine, /area/crew_quarters/heads/chief, /area/ruin/space/derelict/assembly_line, /area/science/robotics, diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index ddec9750d9..6a95a4a95d 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -5,6 +5,7 @@ name = "floor" icon = 'icons/turf/floors.dmi' baseturfs = /turf/open/floor/plating + dirt_buildup_allowed = TRUE footstep = FOOTSTEP_FLOOR barefootstep = FOOTSTEP_HARD_BAREFOOT diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 2f223f2c40..e7471478fb 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -6,6 +6,7 @@ gender = PLURAL //"That's some lava." baseturfs = /turf/open/lava //lava all the way down slowdown = 2 + dirt_buildup_allowed = FALSE light_range = 2 light_power = 0.75 diff --git a/code/game/turfs/simulated/reebe_void.dm b/code/game/turfs/simulated/reebe_void.dm index 14aa02065d..3f3bf31f9b 100644 --- a/code/game/turfs/simulated/reebe_void.dm +++ b/code/game/turfs/simulated/reebe_void.dm @@ -6,6 +6,7 @@ planetary_atmos = TRUE bullet_bounce_sound = null //forever falling tiled_dirt = FALSE + dirt_buildup_allowed = FALSE /turf/open/indestructible/reebe_void/Initialize(mapload) . = ..() diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index b150d4930e..3cdbe8badb 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -3,6 +3,7 @@ icon_state = "0" name = "\proper space" intact = 0 + dirt_buildup_allowed = FALSE temperature = TCMB thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index d4ccc63b34..79334e1698 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -63,6 +63,8 @@ //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas //and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt + /// Do we make floors dirty as we move? + var/causes_dirt_buildup_on_floor = TRUE var/list/roundstart_quirks = list() diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 0cdfe9dbf2..e7a5de294d 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -101,7 +101,28 @@ if(lying && !buckled && prob(getBruteLoss()*200/maxHealth)) makeTrail(newloc, T, old_direction) + if(causes_dirt_buildup_on_floor && (movement_type & GROUND)) + dirt_buildup() +/** + * Attempts to make the floor dirty. + */ +/mob/living/proc/dirt_buildup(strength) + var/turf/T = loc + if(!istype(T) || !T.allow_dirt_buildup) + return + var/area/A = T.loc + if(!A.allow_dirt_buildup) + return + var/obj/effect/decal/cleanable/dirt/D = locate() in T + if(D) + D.dirty(strength) + else + T.dirtyness += strength + if(T.dirtyness >= T.dirt_spawn_threshold) + D = new /obj/effect/decal/cleanable/dirt(T) + D.dirty(T.dirt_spawn_threshold - T.dirtyness) + T.dirtyness = 0 // reset. /mob/living/Move_Pulled(atom/A) . = ..() From 952d74437864fe1762c65f5f85d2f51f51686b52 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:31:31 -0800 Subject: [PATCH 14/31] done --- code/modules/mob/living/living_movement.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index e7a5de294d..2a9e2d2634 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -108,11 +108,11 @@ * Attempts to make the floor dirty. */ /mob/living/proc/dirt_buildup(strength) - var/turf/T = loc - if(!istype(T) || !T.allow_dirt_buildup) + var/turf/open/T = loc + if(!istype(T) || !T.dirt_buildup_allowed) return var/area/A = T.loc - if(!A.allow_dirt_buildup) + if(!A.dirt_buildup_allowed) return var/obj/effect/decal/cleanable/dirt/D = locate() in T if(D) From 322843523767669b2074fe6e5f9143168c93e43f Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:33:16 -0800 Subject: [PATCH 15/31] errors --- .../subsystem/persistence/cleanable_debris.dm | 17 ++++++++--------- code/game/objects/effects/decals/crayon.dm | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index dccc609ed3..a08c4c4964 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -39,27 +39,26 @@ for(var/x in L1) var/list/L2 = data[z][x] for(var/y in L2) - var/turf/tile = locate(x, y, z) + var/turf/tile = locate(x, y, actual_z) if(!tile) continue var/list/objects = data[z][x][y] for(var/_L in objects) - var/list/data + var/list/objdata var/path if(islist(_L)) - data = _L - path = data["__PATH__"] + objdata = _L + path = objdata["__PATH__"] else path = _L - data = objects[_L] + objdata = objects[_L] if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) continue - var/path = data["__PATH__"] if(!path) continue var/obj/effect/decal/cleanable/instantiated = new path(tile) - if(data) - instantiated.PersistenceLoad(data) + if(objdata) + instantiated.PersistenceLoad(objdata) /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) @@ -82,7 +81,7 @@ continue var/text_z = num2text(saving.z) var/text_y = num2text(saving.y) - var/text_x = num2text(saving.x) + var/text_x = num2text(z_lookup[num2text(saving.x)]) LAZYINITLIST(data[text_z]) LAZYINITLIST(data[text_z][text_x]) LAZYINITLIST(data[text_z][text_x][text_y]) diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 6ebd798e40..ad9abe10b1 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -48,7 +48,7 @@ name = data["name"] if(do_icon_rotate && data["rotation"]) var/matrix/M = matrix() - M.turn(data["rotation"]) + M.Turn(data["rotation"]) transform = M if(data["paint_color"]) paint_colour = data["paint_color"] From dafc6bf89fe7816474b5a5fe31d42efecfc1b9a6 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:41:21 -0800 Subject: [PATCH 16/31] fix --- .../configuration/entries/game_options.dm | 13 +++++++++++++ code/game/objects/effects/decals/cleanable/misc.dm | 6 +++++- code/game/turfs/open.dm | 4 ++-- code/modules/mob/living/living_movement.dm | 4 ++-- config/game_options.txt | 8 +++++++- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 67e4a97894..dcede1e3e0 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -566,3 +566,16 @@ config_entry_value = 0.333 min_val = 0 integer = FALSE + +/// Amount of dirtyness tiles need to spawn dirt. +/datum/config_entry/number/turf_dirt_threshold + config_entry_value = 100 + min_value = 1 + integer = TRUE + +/// Alpha dirt starts at +/datum/config_entry/number/dirt_alpha_starting + config_entry_value = 127 + max_val = 255 + min_val = 0 + integer = TRUE diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index e3f223f380..b4c3a3acec 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -65,7 +65,11 @@ mergeable_decal = TRUE persistent = TRUE -/obj/effect/decal/cleanable/dirt/proc/dirty(strength) +/obj/effect/decal/cleanable/dirt/Initialize(mapload) + . = ..() + alpha = CONFIG_GET(number/dirt_alpha_starting) + +/obj/effect/decal/cleanable/dirt/proc/dirty(strength = 1) if(alpha < 255) alpha += strength if(alpha > 255) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 15f5738033..7e00b1cf63 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -4,8 +4,8 @@ var/dirt_buildup_allowed = FALSE /// Dirt level. var/dirtyness = 0 - /// Dirt level to spawn dirt. - var/dirt_spawn_threshold = 100 + /// Dirt level to spawn dirt. Null to use config. + var/dirt_spawn_threshold /// Slowdown applied to mobs on us. var/slowdown = 0 //negative for faster, positive for slower diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 2a9e2d2634..d4694a76ea 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -107,7 +107,7 @@ /** * Attempts to make the floor dirty. */ -/mob/living/proc/dirt_buildup(strength) +/mob/living/proc/dirt_buildup(strength =) var/turf/open/T = loc if(!istype(T) || !T.dirt_buildup_allowed) return @@ -119,7 +119,7 @@ D.dirty(strength) else T.dirtyness += strength - if(T.dirtyness >= T.dirt_spawn_threshold) + if(T.dirtyness >= isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold) D = new /obj/effect/decal/cleanable/dirt(T) D.dirty(T.dirt_spawn_threshold - T.dirtyness) T.dirtyness = 0 // reset. diff --git a/config/game_options.txt b/config/game_options.txt index bc5fdf940e..3c53d9fecb 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -668,4 +668,10 @@ ALLOW_CUSTOM_SKINTONES ## Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh. ## Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best. -#USE_FIELD_OF_VISION \ No newline at end of file +#USE_FIELD_OF_VISION + +## Default turf threshold to get dirt +TURF_DIRT_THRESHOLD 100 + +## Default alpha of dirt on spawn +DIRT_ALPHA_STARTING 127 From d3414a4d2387597c95bdfb1e6600d502396a9c9c Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:47:50 -0800 Subject: [PATCH 17/31] ok --- code/game/objects/effects/decals/cleanable.dm | 2 ++ code/game/objects/effects/decals/cleanable/misc.dm | 1 + code/game/turfs/simulated/floor.dm | 3 +++ code/game/turfs/simulated/floor/plating.dm | 12 ++++++++++++ code/game/turfs/simulated/floor/reinf_floor.dm | 3 +++ 5 files changed, 21 insertions(+) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 11d76d3cdf..b447b46754 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -5,6 +5,8 @@ var/persistent = FALSE /// Can we stack multiple in one tile? var/persistence_allow_stacking = FALSE + /// Are we deleted by turf changes? + var/wiped_by_turf_change = FALSE var/list/random_icon_states = null var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index b4c3a3acec..e2cd40a1af 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -64,6 +64,7 @@ beauty = -75 mergeable_decal = TRUE persistent = TRUE + wiped_by_turf_change = TRUE /obj/effect/decal/cleanable/dirt/Initialize(mapload) . = ..() diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 6a95a4a95d..6a4ddea63b 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -138,6 +138,9 @@ burnt = 1 /turf/open/floor/proc/make_plating() + for(var/obj/effect/decal/cleanable/C in src) + if(C.wiped_by_floor_change) + qdel(C) return ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/ChangeTurf(path, new_baseturf, flags) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 35ee06a584..539fcb63e0 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -61,6 +61,9 @@ to_chat(user, "You begin reinforcing the floor...") if(do_after(user, 30, target = src)) if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine)) + for(var/obj/effect/decal/cleanable/C in src) + if(C.wiped_by_floor_change) + qdel(C) PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) R.use(2) @@ -78,6 +81,9 @@ to_chat(user, "You begin adding glass to the floor...") if(do_after(user, 5, target = src)) if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass)) + for(var/obj/effect/decal/cleanable/C in src) + if(C.wiped_by_floor_change) + qdel(C) PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) G.use(2) @@ -95,6 +101,9 @@ to_chat(user, "You begin adding reinforced glass to the floor...") if(do_after(user, 10, target = src)) if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced)) + for(var/obj/effect/decal/cleanable/C in src) + if(C.wiped_by_floor_change) + qdel(C) PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) RG.use(2) @@ -110,6 +119,9 @@ var/obj/item/stack/tile/W = C if(!W.use(1)) return + for(var/obj/effect/decal/cleanable/C in src) + if(C.wiped_by_floor_change) + qdel(C) if(istype(W, /obj/item/stack/tile/material)) var/turf/newturf = PlaceOnTop(/turf/open/floor/material, flags = CHANGETURF_INHERIT_AIR) newturf.set_custom_materials(W.custom_materials) diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index 42b4707b50..f8c6ff1ce2 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -43,6 +43,9 @@ return TRUE if(floor_tile) new floor_tile(src, 2) + for(var/obj/effect/decal/cleanable/C in src) + if(C.wiped_by_floor_change) + qdel(C) ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return TRUE From bfb3d087c3221ab8a217646d08445241fa8392e6 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:50:28 -0800 Subject: [PATCH 18/31] ok --- .../configuration/entries/game_options.dm | 2 +- code/game/objects/effects/decals/cleanable.dm | 2 +- .../objects/effects/decals/cleanable/misc.dm | 2 +- code/game/turfs/simulated/floor/plating.dm | 24 +++++++++---------- code/modules/mob/living/living_movement.dm | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index dcede1e3e0..ffa73d2c32 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -570,7 +570,7 @@ /// Amount of dirtyness tiles need to spawn dirt. /datum/config_entry/number/turf_dirt_threshold config_entry_value = 100 - min_value = 1 + min_val = 1 integer = TRUE /// Alpha dirt starts at diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index b447b46754..5a6d5e54e9 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -6,7 +6,7 @@ /// Can we stack multiple in one tile? var/persistence_allow_stacking = FALSE /// Are we deleted by turf changes? - var/wiped_by_turf_change = FALSE + var/wiped_by_floor_change = FALSE var/list/random_icon_states = null var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index e2cd40a1af..2bd79edfb4 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -64,7 +64,7 @@ beauty = -75 mergeable_decal = TRUE persistent = TRUE - wiped_by_turf_change = TRUE + wiped_by_floor_change = TRUE /obj/effect/decal/cleanable/dirt/Initialize(mapload) . = ..() diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 539fcb63e0..1b875a5e69 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -61,9 +61,9 @@ to_chat(user, "You begin reinforcing the floor...") if(do_after(user, 30, target = src)) if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine)) - for(var/obj/effect/decal/cleanable/C in src) - if(C.wiped_by_floor_change) - qdel(C) + for(var/obj/effect/decal/cleanable/decal in src) + if(decal.wiped_by_floor_change) + qdel(decal) PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) R.use(2) @@ -81,9 +81,9 @@ to_chat(user, "You begin adding glass to the floor...") if(do_after(user, 5, target = src)) if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass)) - for(var/obj/effect/decal/cleanable/C in src) - if(C.wiped_by_floor_change) - qdel(C) + for(var/obj/effect/decal/cleanable/decal in src) + if(decal.wiped_by_floor_change) + qdel(decal) PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) G.use(2) @@ -101,9 +101,9 @@ to_chat(user, "You begin adding reinforced glass to the floor...") if(do_after(user, 10, target = src)) if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced)) - for(var/obj/effect/decal/cleanable/C in src) - if(C.wiped_by_floor_change) - qdel(C) + for(var/obj/effect/decal/cleanable/decal in src) + if(decal.wiped_by_floor_change) + qdel(decal) PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) RG.use(2) @@ -119,9 +119,9 @@ var/obj/item/stack/tile/W = C if(!W.use(1)) return - for(var/obj/effect/decal/cleanable/C in src) - if(C.wiped_by_floor_change) - qdel(C) + for(var/obj/effect/decal/cleanable/decal in src) + if(decal.wiped_by_floor_change) + qdel(decal) if(istype(W, /obj/item/stack/tile/material)) var/turf/newturf = PlaceOnTop(/turf/open/floor/material, flags = CHANGETURF_INHERIT_AIR) newturf.set_custom_materials(W.custom_materials) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index d4694a76ea..1196bc0252 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -107,7 +107,7 @@ /** * Attempts to make the floor dirty. */ -/mob/living/proc/dirt_buildup(strength =) +/mob/living/proc/dirt_buildup(strength = 1) var/turf/open/T = loc if(!istype(T) || !T.dirt_buildup_allowed) return From a6ae0fe5c2a241f52f8628546150664c1851d637 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:56:48 -0800 Subject: [PATCH 19/31] ok --- .../configuration/entries/persistence.dm | 3 +++ .../subsystem/persistence/cleanable_debris.dm | 2 ++ code/game/turfs/simulated/floor/plating.dm | 6 +++--- config/config.txt | 1 + config/persistence.txt | 14 ++++++++++++++ 5 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 config/persistence.txt diff --git a/code/controllers/configuration/entries/persistence.dm b/code/controllers/configuration/entries/persistence.dm index cf7b23bef3..2444034b86 100644 --- a/code/controllers/configuration/entries/persistence.dm +++ b/code/controllers/configuration/entries/persistence.dm @@ -15,3 +15,6 @@ /datum/config_entry/number/persistent_debris_type_max config_entry_value = 2000 integer = TRUE + +/// Wipe dirty stuff on nuke +/datum/config_entry/flag/persistent_debris_wipe_on_nuke diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index a08c4c4964..8c9e7ba5c0 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -63,6 +63,8 @@ /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) fdel("[get_map_persistence_path()]/debris.json") + if(CONFIG_GET(flag/persistent_debris_wipe_on_nuke) && SSticker?.mode?.station_was_nuked) + return // local janitor cheers on nukeop team to save some work var/list/data = list() var/list/z_lookup = SSmapping.z_to_station_z_index var/list/debris = RelevantPersistentDebris() diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 1b875a5e69..ad3cf86864 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -101,9 +101,9 @@ to_chat(user, "You begin adding reinforced glass to the floor...") if(do_after(user, 10, target = src)) if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced)) - for(var/obj/effect/decal/cleanable/decal in src) - if(decal.wiped_by_floor_change) - qdel(decal) + for(var/obj/effect/decal/cleanable/decal in src) + if(decal.wiped_by_floor_change) + qdel(decal) PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) RG.use(2) diff --git a/config/config.txt b/config/config.txt index 72df74beb1..c7bb36af0e 100644 --- a/config/config.txt +++ b/config/config.txt @@ -11,6 +11,7 @@ $include dynamic_config.txt $include plushies/defines.txt $include job_threats.txt $include policy.txt +$include persistence.txt $include respawns.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game diff --git a/config/persistence.txt b/config/persistence.txt new file mode 100644 index 0000000000..7d65a150e2 --- /dev/null +++ b/config/persistence.txt @@ -0,0 +1,14 @@ +### Whether or not cleanable object persistence is on +PERSISTENT_DEBRIS + +### Whether or not ONLY persistent cleanable objects should be spawned, for supported objects +PERSISTENT_DEBRIS_ONLY + +### Max objects to store, total +PERSISTENT_DEBRIS_GLOBAL_MAX 10000 + +### Max objects to store per type, total +PERSISTENT_DEBRIS_TYPE_MAX 2000 + +### Wipe objects on nuke for the above +PERSISTENT_DEBRIS_WIPE_ON_NUKE From 46b58fa5ba7193ded5f14f7f3dfc2c43254c8680 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 21:10:12 -0800 Subject: [PATCH 20/31] file ops --- .../subsystem/persistence/_persistence.dm | 2 +- .../subsystem/persistence/cleanable_debris.dm | 20 +++++++++++-------- code/modules/mapping/map_config.dm | 9 +++++---- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index 00135bbcc2..4086fe6408 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -31,7 +31,7 @@ SUBSYSTEM_DEF(persistence) */ /datum/controller/subsystem/persistence/proc/get_map_persistence_path() ASSERT(SSmapping.config) - if(SSmapping.config.persistence_key == "NO_PERSIST") + if(!SSmapping.config.persistence_key || (SSmapping.config.persistence_key == "NO_PERSIST")) return null return "data/persistence/[ckey(SSmapping.config.persistence_key)]" diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 8c9e7ba5c0..430bc871dd 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -16,13 +16,13 @@ SaveMapDebris() /datum/controller/subsystem/persistence/proc/LoadMapDebris() + if(CONFIG_GET(flag/persistent_debris_only)) + wipe_existing_debris() if(!fexists("[get_map_persistence_path()]/debris.json")) return if(loaded_debris) return loaded_debris = TRUE - if(CONFIG_GET(flag/persistent_debris_only)) - wipe_existing_debris() var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) var/list/allowed_z_cache = list() for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) @@ -104,12 +104,16 @@ message_admins(w) subsystem_log(w) - subsystem_log({" - Debris saving completed: - Total: [global_max] - By type: [english_list(stored_by_type)] - "}) - WRITE_FILE("[get_map_persistence_path()]/debris.json", json_encode(data)) + var/list/bytype = list() + for(var/path in stored_by_type) + bytype += "[path] - [stored_by_type[path]]" + subsystem_log( + {"Debris saving completed: + Total: [stored] + By type: + [bytype.Join("\n")]"} + ) + WRITE_FILE(file("[get_map_persistence_path()]/debris.json"), json_encode(data)) /datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, obj/effect/decal/cleanable/type, loading = FALSE) if(!allowed_typecache[tile.type]) diff --git a/code/modules/mapping/map_config.dm b/code/modules/mapping/map_config.dm index 83418462f1..1f4b558e21 100644 --- a/code/modules/mapping/map_config.dm +++ b/code/modules/mapping/map_config.dm @@ -105,10 +105,11 @@ persistence_key = ckey(map_name) var/json_persistence_key = json["persistence_key"] - if(json_persistence_key == "NO_PERSIST") - persistence_key = null - else - persistence_key = json_persistence_key + if(json_persistence_key) + if(json_persistence_key == "NO_PERSIST") + persistence_key = null + else + persistence_key = json_persistence_key // "map_file": "BoxStation.dmm" if (istext(map_file)) From 753c1389cc3060299619f35384dcf287029e5058 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 22:04:05 -0800 Subject: [PATCH 21/31] fix --- .../configuration/entries/game_options.dm | 4 ++++ .../subsystem/persistence/cleanable_debris.dm | 20 +++++++++++++------ .../mob/living/carbon/human/human_defines.dm | 1 + .../mob/living/carbon/human/human_movement.dm | 5 +++++ code/modules/mob/living/living_defines.dm | 2 +- code/modules/mob/living/living_movement.dm | 4 +++- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index ffa73d2c32..dc8e9e1859 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -579,3 +579,7 @@ max_val = 255 min_val = 0 integer = TRUE + +/// Dirtyness multiplier for making turfs dirty +/datum/config_entry/number/turf_dirty_multiplier + config_entry_value = 1 diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 430bc871dd..9f55177cbb 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -34,13 +34,19 @@ var/sz = SSmapping.z_to_station_z_index[z] z_lookup[num2text(sz)] = z for(var/z in data) + to_chat(world, "DEBUG: looking at z [z]") var/actual_z = z_lookup[z] + to_chat(world, "DEBUG: actual z [actual_z]") var/list/L1 = data[z] for(var/x in L1) + to_chat(world, "DEBUG: looking at x [x]") var/list/L2 = data[z][x] for(var/y in L2) + to_chat(world, "DEBUG: looking at y [y]") var/turf/tile = locate(x, y, actual_z) + to_chat(world, "DEBUG: finding turf [x] [y] [z]: [tile]") if(!tile) + to_chat(world, "DEBUG: aborting due to no turf") continue var/list/objects = data[z][x][y] for(var/_L in objects) @@ -48,13 +54,15 @@ var/path if(islist(_L)) objdata = _L - path = objdata["__PATH__"] + path = text2path(objdata["__PATH__"]) else - path = _L + path = text2path(_L) objdata = objects[_L] - if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) - continue if(!path) + to_chat(world, "DEBUG: Aborting: No path") + continue + if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) + to_chat(world, "DEBUG: Aborting: Invalid location") continue var/obj/effect/decal/cleanable/instantiated = new path(tile) if(objdata) @@ -81,9 +89,9 @@ continue if(stored_by_type[path] > type_max) continue - var/text_z = num2text(saving.z) + var/text_z = num2text(z_lookup[num2text(saving.z)]) var/text_y = num2text(saving.y) - var/text_x = num2text(z_lookup[num2text(saving.x)]) + var/text_x = num2text(saving.x) LAZYINITLIST(data[text_z]) LAZYINITLIST(data[text_z][text_x]) LAZYINITLIST(data[text_z][text_x][text_y]) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 2e8641b43e..07d45f966a 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -15,6 +15,7 @@ block_parry_data = /datum/block_parry_data/unarmed/human default_block_parry_data = /datum/block_parry_data/unarmed/pugilist + causes_dirt_buildup_on_floor = TRUE //Hair colour and style var/hair_color = "000" diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 509633c0d5..440400f889 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -100,3 +100,8 @@ if(dna.species.space_move(src)) return TRUE return ..() + +/mob/living/carbon/human/dirt_buildup(strength) + if(!shoes || !(shoes.body_parts_covered & FEET)) + return // barefoot advantage + return ..() diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 79334e1698..742d4d8624 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -64,7 +64,7 @@ var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas //and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt /// Do we make floors dirty as we move? - var/causes_dirt_buildup_on_floor = TRUE + var/causes_dirt_buildup_on_floor = FALSE var/list/roundstart_quirks = list() diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 1196bc0252..9e093d391e 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -114,12 +114,14 @@ var/area/A = T.loc if(!A.dirt_buildup_allowed) return + var/multiplier = CONFIG_GET(number/turf_dirty_multiplier) + strength *= multiplier var/obj/effect/decal/cleanable/dirt/D = locate() in T if(D) D.dirty(strength) else T.dirtyness += strength - if(T.dirtyness >= isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold) + if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold)) D = new /obj/effect/decal/cleanable/dirt(T) D.dirty(T.dirt_spawn_threshold - T.dirtyness) T.dirtyness = 0 // reset. From 57065d995e49963adb807e0ff49cc5c466bdfa97 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 22:20:04 -0800 Subject: [PATCH 22/31] fix --- code/controllers/subsystem/mapping.dm | 8 ++++++-- .../subsystem/persistence/cleanable_debris.dm | 15 +++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 1893e9ccd9..90908bbde0 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -264,8 +264,12 @@ SUBSYSTEM_DEF(mapping) /datum/controller/subsystem/mapping/proc/setup_station_z_index() z_to_station_z_index = list() var/sz = 1 - for(var/i in station_start to (station_start + islist(config.map_file)? (length(config.map_file) - 1) : 0)) - z_to_station_z_index["[i]"] = sz++ + var/cz = station_start + if(islist(config.map_file)) + for(var/map in config.map_file) + z_to_station_z_index["[cz++]"] = sz++ + else + z_to_station_z_index["[station_start]"] = 1 /datum/controller/subsystem/mapping/proc/loadWorld() //if any of these fail, something has gone horribly, HORRIBLY, wrong diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 9f55177cbb..e2da6114a6 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -32,21 +32,16 @@ /// reverse it for(var/z in SSmapping.z_to_station_z_index) var/sz = SSmapping.z_to_station_z_index[z] - z_lookup[num2text(sz)] = z + z_lookup[num2text(sz)] = text2num(z) for(var/z in data) - to_chat(world, "DEBUG: looking at z [z]") var/actual_z = z_lookup[z] - to_chat(world, "DEBUG: actual z [actual_z]") var/list/L1 = data[z] for(var/x in L1) - to_chat(world, "DEBUG: looking at x [x]") var/list/L2 = data[z][x] for(var/y in L2) - to_chat(world, "DEBUG: looking at y [y]") - var/turf/tile = locate(x, y, actual_z) - to_chat(world, "DEBUG: finding turf [x] [y] [z]: [tile]") + var/turf/tile = locate(text2num(x), text2num(y), actual_z) if(!tile) - to_chat(world, "DEBUG: aborting due to no turf") + to_chat(world, "DEBUG: aborting due to no turf ([x] [y] [actual_z])") continue var/list/objects = data[z][x][y] for(var/_L in objects) @@ -59,10 +54,10 @@ path = text2path(_L) objdata = objects[_L] if(!path) - to_chat(world, "DEBUG: Aborting: No path") + to_chat(world, "DEBUG: Aborting: No path ([x] [y] [actual_z])") continue if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) - to_chat(world, "DEBUG: Aborting: Invalid location") + to_chat(world, "DEBUG: Aborting: Invalid location ([x] [y] [actual_z])") continue var/obj/effect/decal/cleanable/instantiated = new path(tile) if(objdata) From 5266ae1437e062384189321b70f247f7f686ea9a Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 22:28:41 -0800 Subject: [PATCH 23/31] okay --- code/controllers/subsystem/persistence/cleanable_debris.dm | 3 --- code/game/objects/effects/decals/cleanable/humans.dm | 6 +++--- code/game/objects/effects/decals/cleanable/misc.dm | 2 +- code/game/objects/effects/decals/crayon.dm | 2 +- code/game/objects/effects/decals/remains.dm | 1 + 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index e2da6114a6..63e7c7a2e8 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -41,7 +41,6 @@ for(var/y in L2) var/turf/tile = locate(text2num(x), text2num(y), actual_z) if(!tile) - to_chat(world, "DEBUG: aborting due to no turf ([x] [y] [actual_z])") continue var/list/objects = data[z][x][y] for(var/_L in objects) @@ -54,10 +53,8 @@ path = text2path(_L) objdata = objects[_L] if(!path) - to_chat(world, "DEBUG: Aborting: No path ([x] [y] [actual_z])") continue if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) - to_chat(world, "DEBUG: Aborting: Invalid location ([x] [y] [actual_z])") continue var/obj/effect/decal/cleanable/instantiated = new path(tile) if(objdata) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 5206279d42..bec00aa944 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -71,7 +71,7 @@ /obj/effect/decal/cleanable/blood/tracks/PersistenceLoad(list/data) . = ..() if(data["dir"]) - setDir(data["dir"]) + setDir(text2num(data["dir"])) /obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose name = "blood" @@ -92,7 +92,7 @@ /obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data) . = ..() if(data["dir"]) - setDir(data["dir"]) + setDir(text2num(data["dir"])) if(data["color"]) fixed_color = TRUE add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY) @@ -138,7 +138,7 @@ /obj/effect/decal/cleanable/blood/footprints/PersistenceLoad(list/data) . = ..() if(data["dir"]) - setDir(data["dir"]) + setDir(text2num(data["dir"])) /obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O) if(ishuman(O)) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 2bd79edfb4..0f7d7c185d 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -83,7 +83,7 @@ /obj/effect/decal/cleanable/dirt/PersistenceLoad(list/data) . = ..() if(data["alpha"]) - alpha = data["alpha"] + alpha = text2num(data["alpha"]) /obj/effect/decal/cleanable/dirt/Initialize() . = ..() diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index ad9abe10b1..a0590b7180 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -48,7 +48,7 @@ name = data["name"] if(do_icon_rotate && data["rotation"]) var/matrix/M = matrix() - M.Turn(data["rotation"]) + M.Turn(text2num(data["rotation"])) transform = M if(data["paint_color"]) paint_colour = data["paint_color"] diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index 87337a526c..34019ba897 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -2,6 +2,7 @@ name = "remains" gender = PLURAL icon = 'icons/effects/blood.dmi' + persistent = TRUE /obj/effect/decal/remains/acid_act() visible_message("[src] dissolve[gender==PLURAL?"":"s"] into a puddle of sizzling goop!") From a42fa987ba38b427be7f2ec4d68f7145d058f49a Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 26 Dec 2020 22:43:25 -0800 Subject: [PATCH 24/31] ok --- code/game/objects/effects/decals/remains.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index 34019ba897..87337a526c 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -2,7 +2,6 @@ name = "remains" gender = PLURAL icon = 'icons/effects/blood.dmi' - persistent = TRUE /obj/effect/decal/remains/acid_act() visible_message("[src] dissolve[gender==PLURAL?"":"s"] into a puddle of sizzling goop!") From 57d85f7e86cd2d8ed056bb1ffaf55ddef9f69dc0 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 27 Dec 2020 05:20:29 -0800 Subject: [PATCH 25/31] okay --- .../subsystem/persistence/cleanable_debris.dm | 25 ++++++++++++++++++- .../effects/decals/cleanable/humans.dm | 4 ++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 63e7c7a2e8..80d10027a0 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -29,6 +29,11 @@ allowed_z_cache[num2text(z)] = TRUE var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json")) var/list/z_lookup = list() + var/loaded = 0 + var/list/loaded_by_type = list() + var/nopath = 0 + var/badloc = 0 + var/noturf = 0 /// reverse it for(var/z in SSmapping.z_to_station_z_index) var/sz = SSmapping.z_to_station_z_index[z] @@ -41,6 +46,7 @@ for(var/y in L2) var/turf/tile = locate(text2num(x), text2num(y), actual_z) if(!tile) + noturf++ continue var/list/objects = data[z][x][y] for(var/_L in objects) @@ -53,12 +59,29 @@ path = text2path(_L) objdata = objects[_L] if(!path) + nopath++ continue if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) + badloc++ continue var/obj/effect/decal/cleanable/instantiated = new path(tile) + loaded_by_type[path] += 1 + loaded++ if(objdata) instantiated.PersistenceLoad(objdata) + var/list/bytype = list() + for(var/path in loaded_by_type) + bytype += "[path] - [loaded_by_type[path]]" + subsystem_log( + {"Debris loading completed: + Errors: + No path: [nopath] + Invalid location: [badloc] + No turf on map: [noturf] + Total loaded: [loaded] + By type: + [bytype.Join("\n")]"} + ) /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) @@ -89,7 +112,7 @@ LAZYINITLIST(data[text_z][text_x][text_y]) if(saving.persistence_allow_stacking) serializing["__PATH__"] = path - data[text_z][text_x][text_y] += serializing + data[text_z][text_x][text_y] += list(serializing) else data[text_z][text_x][text_y][path] = serializing stored++ diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index bec00aa944..68b13389b9 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -33,13 +33,15 @@ /obj/effect/decal/cleanable/blood/PersistenceSave(list/data) . = ..() data["color"] = color - return /obj/effect/decal/cleanable/blood/old /obj/effect/decal/cleanable/blood/PersistenceLoad(list/data) . = ..() if(data["color"]) fixed_color = TRUE add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY) + name = "dried blood" + desc = "Looks like it's been here a while. Eew" + bloodiness = 0 /obj/effect/decal/cleanable/blood/old name = "dried blood" From 51d1e3a87f44d49c36c705deef1e05628a634348 Mon Sep 17 00:00:00 2001 From: DeltaFire Date: Mon, 28 Dec 2020 19:41:39 +0100 Subject: [PATCH 26/31] intendation sigh --- code/modules/mob/living/carbon/human/human_defines.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index d130b053e2..a82151cc1d 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -14,7 +14,7 @@ blocks_emissive = EMISSIVE_BLOCK_UNIQUE block_parry_data = /datum/block_parry_data/unarmed/human - default_block_parry_data = /datum/block_parry_data/unarmed/human + default_block_parry_data = /datum/block_parry_data/unarmed/human causes_dirt_buildup_on_floor = TRUE //Hair colour and style From 0c87c3b0e0931e4106ae6bfd0c151749eb711727 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Mon, 28 Dec 2020 12:15:55 -0800 Subject: [PATCH 27/31] fiX --- code/__HELPERS/roundend.dm | 7 +++++-- .../subsystem/persistence/_persistence.dm | 19 +++++++++++++------ .../subsystem/persistence/cleanable_debris.dm | 2 +- .../ratvar_the_clockwork_justicar.dm | 1 + code/modules/power/singularity/narsie.dm | 1 + 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index e4a2e6521a..a860a8cd3f 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -238,8 +238,11 @@ CHECK_TICK SSdbcore.SetRoundEnd() //Collects persistence features - if(mode.allow_persistence_save) - SSpersistence.CollectData() + if(mode.station_was_nuked) + SSpersistence.station_was_destroyed = TRUE + if(!mode.allow_persistence_save) + SSpersistence.station_persistence_save_disabled = TRUE + SSpersistence.CollectData() //stop collecting feedback during grifftime SSblackbox.Seal() diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index 4086fe6408..741d1dd72a 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -6,6 +6,11 @@ SUBSYSTEM_DEF(persistence) init_order = INIT_ORDER_PERSISTENCE flags = SS_NO_FIRE + /// Marks if the station got horribly destroyed + var/station_was_destroyed = FALSE + /// Marks if persistence save should be disabled + var/station_persistence_save_disabled = FALSE + var/list/obj/structure/chisel_message/chisel_messages = list() var/list/saved_messages = list() var/list/spawned_objects = list() @@ -37,45 +42,47 @@ SUBSYSTEM_DEF(persistence) /datum/controller/subsystem/persistence/proc/CollectData() SaveServerPersistence() + if(station_persistence_save_disabled) + return SaveGamePersistence() var/map_persistence_path = get_map_persistence_path() if(map_persistence_path) SaveMapPersistence() /** - * Loads persistent data relevant to the server: Configurations, past gamemodes, votes, etc + * Loads persistent data relevant to the server: Configurations, past gamemodes, votes, antag rep, etc */ /datum/controller/subsystem/persistence/proc/LoadServerPersistence() for(var/client/C in GLOB.clients) LoadSavedVote(C.ckey) if(CONFIG_GET(flag/use_antag_rep)) LoadAntagReputation() + LoadRandomizedRecipes() /** - * Saves persistent data relevant to the server: Configurations, past gamemodes, votes, etc + * Saves persistent data relevant to the server: Configurations, past gamemodes, votes, antag rep, etc */ /datum/controller/subsystem/persistence/proc/SaveServerPersistence() if(CONFIG_GET(flag/use_antag_rep)) CollectAntagReputation() + SaveRandomizedRecipes() /** - * Loads persistent data relevant to the game in general: Trophies, antag reputation, etc + * Loads persistent data relevant to the game in general: Photos, etc * * Legacy map persistence systems also use this. */ /datum/controller/subsystem/persistence/proc/LoadGamePersistence() LoadChiselMessages() LoadPhotoPersistence() - LoadRandomizedRecipes() LoadPaintings() /** - * Saves persistent data relevant to the game in general: Trophies, antag reputation, etc + * Saves persistent data relevant to the game in general: Photos, etc * * Legacy map persistence systems also use this. */ /datum/controller/subsystem/persistence/proc/SaveGamePersistence() - SaveRandomizedRecipes() CollectChiselMessages() SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION. SavePaintings() diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm index 80d10027a0..a0817c460b 100644 --- a/code/controllers/subsystem/persistence/cleanable_debris.dm +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -86,7 +86,7 @@ /datum/controller/subsystem/persistence/proc/SaveMapDebris() if(fexists("[get_map_persistence_path()]/debris.json")) fdel("[get_map_persistence_path()]/debris.json") - if(CONFIG_GET(flag/persistent_debris_wipe_on_nuke) && SSticker?.mode?.station_was_nuked) + if(CONFIG_GET(flag/persistent_debris_wipe_on_nuke) && station_was_destroyed) return // local janitor cheers on nukeop team to save some work var/list/data = list() var/list/z_lookup = SSmapping.z_to_station_z_index diff --git a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm index 73ae89a19b..28901ea0b2 100644 --- a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm +++ b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm @@ -30,6 +30,7 @@ var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert") notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [get_area_name(src)] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay) INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0) + SSpersistence.station_was_destroyed = TRUE /obj/structure/destructible/clockwork/massive/ratvar/Destroy() GLOB.ratvar_awakens-- diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 8bf20fddc6..5b5292a020 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -78,6 +78,7 @@ set_security_level("delta") SSshuttle.registerHostileEnvironment(src) SSshuttle.lockdown = TRUE + SSpersistence.station_was_destroyed = TRUE sleep(600) if(resolved == FALSE) resolved = TRUE From e6000ceffa07dcfc9ab12c3416ad0b0400599458 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Tue, 29 Dec 2020 11:12:06 -0800 Subject: [PATCH 28/31] meme --- code/game/objects/effects/decals/cleanable/humans.dm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 68b13389b9..cbf9c571e3 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -12,10 +12,14 @@ var/fixed_color = FALSE /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) + if(C.fixed_color) + qdel(C) + return FALSE if (C.blood_DNA) blood_DNA |= C.blood_DNA + qdel(C) update_icon() - ..() + return FALSE /obj/effect/decal/cleanable/blood/transfer_blood_dna() ..() @@ -199,7 +203,7 @@ return if(color != C.color) return - ..() + return ..() /obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in() if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY)) From 34256a61efd05826820deecffe36c77593086f3a Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Wed, 30 Dec 2020 21:06:34 -0800 Subject: [PATCH 29/31] remove drips --- code/game/objects/effects/decals/cleanable/gibs.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm index 1f9897071c..4b63cbecc8 100644 --- a/code/game/objects/effects/decals/cleanable/gibs.dm +++ b/code/game/objects/effects/decals/cleanable/gibs.dm @@ -97,8 +97,6 @@ icon_state = "1" random_icon_states = list("drip1","drip2","drip3","drip4","drip5") bloodiness = 0 - persistent = TRUE - persistence_allow_stacking = TRUE var/drips = 1 /obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in() From 78322199e3bcdc7dcae24c3ee463342fe4490258 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 1 Jan 2021 00:38:46 -0800 Subject: [PATCH 30/31] fix --- code/game/objects/effects/decals/crayon.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index a0590b7180..387b8c167d 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -41,6 +41,10 @@ if(do_icon_rotate) data["rotation"] = rotation data["name"] = name + if(pixel_x != initial(pixel_x)) + data["pixel_x"] = pixel_x + if(pixel_y != initial(pixel_y)) + data["pixel_y"] = pixel_y /obj/effect/decal/cleanable/crayon/PersistenceLoad(list/data) . = ..() @@ -55,3 +59,7 @@ add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY) if(data["icon_state"]) icon_state = data["icon_state"] + if(data["pixel_x"]) + pixel_x = data["pixel_x"] + if(data["pixel_y"]) + pixel_y = data["pixel_y"] From 407b1fe071548dad8dc7546782c5529ba5b91dbb Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Thu, 7 Jan 2021 23:14:59 -0700 Subject: [PATCH 31/31] Update humans.dm --- code/game/objects/effects/decals/cleanable/humans.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index cbf9c571e3..6d051b6c8c 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -106,7 +106,7 @@ /obj/effect/decal/cleanable/trail_holder/update_icon() . = ..() if(!fixed_color) - add_atom_colour(blood_DNA_to_color()) + add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY) /obj/effect/cleanable/trail_holder/Initialize() . = ..()