mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
Merge pull request #13871 from silicons/debris
Merry Christmas - GIVING JANITORS A JOB
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -566,3 +566,20 @@
|
||||
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_val = 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
|
||||
|
||||
/// Dirtyness multiplier for making turfs dirty
|
||||
/datum/config_entry/number/turf_dirty_multiplier
|
||||
config_entry_value = 1
|
||||
|
||||
20
code/controllers/configuration/entries/persistence.dm
Normal file
20
code/controllers/configuration/entries/persistence.dm
Normal file
@@ -0,0 +1,20 @@
|
||||
/// 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
|
||||
|
||||
/// Wipe dirty stuff on nuke
|
||||
/datum/config_entry/flag/persistent_debris_wipe_on_nuke
|
||||
@@ -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,16 @@ 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
|
||||
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
|
||||
var/list/FailedZs = list()
|
||||
@@ -271,6 +283,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()
|
||||
|
||||
@@ -5,18 +5,14 @@ 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()
|
||||
|
||||
/// 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/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 +24,81 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/paintings = list()
|
||||
|
||||
/datum/controller/subsystem/persistence/Initialize()
|
||||
LoadSatchels()
|
||||
LoadPoly()
|
||||
LoadChiselMessages()
|
||||
LoadTrophies()
|
||||
LoadRecentModes()
|
||||
LoadRecentStorytellers()
|
||||
LoadRecentRulesets()
|
||||
LoadRecentMaps()
|
||||
LoadPhotoPersistence()
|
||||
LoadServerPersistence()
|
||||
LoadGamePersistence()
|
||||
var/map_persistence_path = get_map_persistence_path()
|
||||
if(map_persistence_path)
|
||||
LoadMapPersistence()
|
||||
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 || (SSmapping.config.persistence_key == "NO_PERSIST"))
|
||||
return null
|
||||
return "data/persistence/[ckey(SSmapping.config.persistence_key)]"
|
||||
|
||||
/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, 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()
|
||||
LoadPanicBunker()
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadSatchels()
|
||||
var/placed_satchel = 0
|
||||
var/path
|
||||
/**
|
||||
* 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()
|
||||
|
||||
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 game in general: Photos, etc
|
||||
*
|
||||
* Legacy map persistence systems also use this.
|
||||
*/
|
||||
/datum/controller/subsystem/persistence/proc/LoadGamePersistence()
|
||||
LoadChiselMessages()
|
||||
LoadPhotoPersistence()
|
||||
LoadPaintings()
|
||||
|
||||
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"])
|
||||
/**
|
||||
* Saves persistent data relevant to the game in general: Photos, etc
|
||||
*
|
||||
* Legacy map persistence systems also use this.
|
||||
*/
|
||||
/datum/controller/subsystem/persistence/proc/SaveGamePersistence()
|
||||
CollectChiselMessages()
|
||||
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
||||
SavePaintings()
|
||||
SaveScars()
|
||||
|
||||
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
|
||||
/**
|
||||
* Loads persistent data relevant to the current map: Objects, etc.
|
||||
*/
|
||||
/datum/controller/subsystem/persistence/proc/LoadMapPersistence()
|
||||
return
|
||||
|
||||
/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.
|
||||
*/
|
||||
/datum/controller/subsystem/persistence/proc/SaveMapPersistence()
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadChiselMessages()
|
||||
var/list/saved_messages = list()
|
||||
@@ -130,63 +145,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 +165,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 +234,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")
|
||||
|
||||
@@ -373,84 +249,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/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)
|
||||
|
||||
177
code/controllers/subsystem/persistence/cleanable_debris.dm
Normal file
177
code/controllers/subsystem/persistence/cleanable_debris.dm
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 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(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
|
||||
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()
|
||||
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]
|
||||
z_lookup[num2text(sz)] = text2num(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(text2num(x), text2num(y), actual_z)
|
||||
if(!tile)
|
||||
noturf++
|
||||
continue
|
||||
var/list/objects = data[z][x][y]
|
||||
for(var/_L in objects)
|
||||
var/list/objdata
|
||||
var/path
|
||||
if(islist(_L))
|
||||
objdata = _L
|
||||
path = text2path(objdata["__PATH__"])
|
||||
else
|
||||
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"))
|
||||
fdel("[get_map_persistence_path()]/debris.json")
|
||||
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
|
||||
var/list/debris = RelevantPersistentDebris()
|
||||
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
|
||||
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(z_lookup[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(saving.persistence_allow_stacking)
|
||||
serializing["__PATH__"] = path
|
||||
data[text_z][text_x][text_y] += list(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)
|
||||
|
||||
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])
|
||||
return FALSE
|
||||
var/area/A = tile.loc
|
||||
if(!A.persistent_debris_allowed)
|
||||
return FALSE
|
||||
if(!allowed_zcache[num2text(tile.z)])
|
||||
return FALSE
|
||||
if(loading)
|
||||
if(!initial(type.persistence_allow_stacking))
|
||||
var/obj/effect/decal/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
|
||||
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/decal/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
|
||||
26
code/controllers/subsystem/persistence/panic_bunker.dm
Normal file
26
code/controllers/subsystem/persistence/panic_bunker.dm
Normal file
@@ -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))
|
||||
11
code/controllers/subsystem/persistence/poly_parrot.dm
Normal file
11
code/controllers/subsystem/persistence/poly_parrot.dm
Normal file
@@ -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?!
|
||||
107
code/controllers/subsystem/persistence/recent_votes_etc.dm
Normal file
107
code/controllers/subsystem/persistence/recent_votes_etc.dm
Normal file
@@ -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"]
|
||||
79
code/controllers/subsystem/persistence/secret_satchels.dm
Normal file
79
code/controllers/subsystem/persistence/secret_satchels.dm
Normal file
@@ -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))
|
||||
84
code/controllers/subsystem/persistence/trophies.dm
Normal file
84
code/controllers/subsystem/persistence/trophies.dm
Normal file
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
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
|
||||
/// Dirty flooring allowed
|
||||
var/dirt_buildup_allowed = TRUE
|
||||
|
||||
/// If mining tunnel generation is allowed in this area
|
||||
var/tunnel_allowed = FALSE
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
/obj/effect/decal/cleanable
|
||||
gender = PLURAL
|
||||
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
|
||||
/// Are we deleted by turf changes?
|
||||
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
|
||||
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
|
||||
@@ -29,9 +36,21 @@
|
||||
|
||||
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0)
|
||||
|
||||
/**
|
||||
* 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(list/data)
|
||||
return type
|
||||
|
||||
/**
|
||||
* 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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -159,6 +164,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 +207,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 +222,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()
|
||||
|
||||
@@ -8,12 +8,18 @@
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
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.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()
|
||||
..()
|
||||
@@ -24,7 +30,22 @@
|
||||
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
|
||||
|
||||
/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"
|
||||
@@ -38,6 +59,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 +70,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(text2num(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(text2num(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(), FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/effect/cleanable/trail_holder/Initialize()
|
||||
. = ..()
|
||||
@@ -84,8 +133,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(text2num(data["dir"]))
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
|
||||
if(ishuman(O))
|
||||
var/mob/living/carbon/human/H = O
|
||||
@@ -143,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))
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
@@ -53,10 +57,33 @@
|
||||
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
|
||||
wiped_by_floor_change = TRUE
|
||||
|
||||
/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)
|
||||
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 = text2num(data["alpha"])
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/Initialize()
|
||||
. = ..()
|
||||
@@ -94,6 +121,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 +151,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 +167,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 +183,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 +202,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 +219,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 +228,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 +237,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 +246,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 +270,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 +297,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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,35 @@
|
||||
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_state
|
||||
data["paint_color"] = paint_colour
|
||||
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)
|
||||
. = ..()
|
||||
if(data["name"])
|
||||
name = data["name"]
|
||||
if(do_icon_rotate && data["rotation"])
|
||||
var/matrix/M = matrix()
|
||||
M.Turn(text2num(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"]
|
||||
if(data["pixel_x"])
|
||||
pixel_x = data["pixel_x"]
|
||||
if(data["pixel_y"])
|
||||
pixel_y = data["pixel_y"]
|
||||
|
||||
@@ -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. Null to use config.
|
||||
var/dirt_spawn_threshold
|
||||
/// Slowdown applied to mobs on us.
|
||||
var/slowdown = 0 //negative for faster, positive for slower
|
||||
|
||||
var/postdig_icon_change = FALSE
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -137,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)
|
||||
|
||||
@@ -61,6 +61,9 @@
|
||||
to_chat(user, "<span class='notice'>You begin reinforcing the floor...</span>")
|
||||
if(do_after(user, 30, target = src))
|
||||
if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine))
|
||||
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)
|
||||
@@ -78,6 +81,9 @@
|
||||
to_chat(user, "<span class='notice'>You begin adding glass to the floor...</span>")
|
||||
if(do_after(user, 5, target = src))
|
||||
if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass))
|
||||
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)
|
||||
@@ -95,6 +101,9 @@
|
||||
to_chat(user, "<span class='notice'>You begin adding reinforced glass to the floor...</span>")
|
||||
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)
|
||||
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/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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
icon_state = "0"
|
||||
name = "\proper space"
|
||||
intact = 0
|
||||
dirt_buildup_allowed = FALSE
|
||||
|
||||
temperature = TCMB
|
||||
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
|
||||
|
||||
@@ -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--
|
||||
|
||||
@@ -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,16 @@
|
||||
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)
|
||||
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]"))
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
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
|
||||
var/hair_color = "000"
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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 = FALSE
|
||||
|
||||
var/list/roundstart_quirks = list()
|
||||
|
||||
|
||||
@@ -101,7 +101,30 @@
|
||||
|
||||
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 = 1)
|
||||
var/turf/open/T = loc
|
||||
if(!istype(T) || !T.dirt_buildup_allowed)
|
||||
return
|
||||
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))
|
||||
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)
|
||||
. = ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
#USE_FIELD_OF_VISION
|
||||
|
||||
## Default turf threshold to get dirt
|
||||
TURF_DIRT_THRESHOLD 100
|
||||
|
||||
## Default alpha of dirt on spawn
|
||||
DIRT_ALPHA_STARTING 127
|
||||
|
||||
14
config/persistence.txt
Normal file
14
config/persistence.txt
Normal file
@@ -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
|
||||
@@ -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"
|
||||
@@ -340,7 +341,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 +363,13 @@
|
||||
#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\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"
|
||||
#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"
|
||||
|
||||
Reference in New Issue
Block a user