From 70286d7618ef8446c0a104357cfeba761b447490 Mon Sep 17 00:00:00 2001 From: Werner Date: Thu, 20 Feb 2020 00:14:00 +0100 Subject: [PATCH] Reworks Away Mission Selection (#8292) --- aurorastation.dme | 2 +- code/_helpers/files.dm | 12 ++ .../initialization/map_finalization.dm | 123 +++++++++++------- .../persistent_configuration.dm | 4 +- code/datums/helper_datums/away_mission.dm | 41 ++++++ code/datums/helper_datums/space_ruin.dm | 26 ---- config/example/space_ruins.json | 71 ---------- dynamic_maps/.gitignore | 3 +- maps/_common/mapsystem/map.dm | 2 - maps/aurora/aurora-4_mainlevel.dmm | 2 +- maps/aurora/aurora-6_surface.dmm | 2 +- maps/aurora/code/aurora.dm | 2 - 12 files changed, 134 insertions(+), 156 deletions(-) create mode 100644 code/datums/helper_datums/away_mission.dm delete mode 100644 code/datums/helper_datums/space_ruin.dm delete mode 100644 config/example/space_ruins.json diff --git a/aurorastation.dme b/aurorastation.dme index 25d7fd0ffe0..90e5f229c04 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -307,10 +307,10 @@ #include "code\datums\expansions\multitool\items\cable.dm" #include "code\datums\expansions\multitool\items\items.dm" #include "code\datums\expansions\multitool\machinery\cloning.dm" +#include "code\datums\helper_datums\away_mission.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\getrev.dm" -#include "code\datums\helper_datums\space_ruin.dm" #include "code\datums\helper_datums\synthsprites.dm" #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm" diff --git a/code/_helpers/files.dm b/code/_helpers/files.dm index 73c470da363..7e91c61534c 100644 --- a/code/_helpers/files.dm +++ b/code/_helpers/files.dm @@ -12,6 +12,18 @@ return text +/proc/get_subfolders(var/root) + var/list/folders = list() + var/list/contents = flist(root) + + for(var/file in contents) + //Check if the filename ends with / to see if its a folder + if(copytext(file,-1,0) != "/") + continue + folders.Add("[root][file]") + + return folders + //Sends resource files to client cache /client/proc/getFiles() for(var/file in args) diff --git a/code/controllers/subsystems/initialization/map_finalization.dm b/code/controllers/subsystems/initialization/map_finalization.dm index 1340e2cc06d..ccf22b7db0c 100644 --- a/code/controllers/subsystems/initialization/map_finalization.dm +++ b/code/controllers/subsystems/initialization/map_finalization.dm @@ -6,7 +6,7 @@ init_order = SS_INIT_MAPFINALIZE var/dmm_suite/maploader - var/datum/space_ruin/selected_ruin + var/datum/away_mission/selected_mission /datum/controller/subsystem/finalize/Initialize(timeofday) // Setup the global antag uplink. This needs to be done after SSatlas as it requires current_map. @@ -16,10 +16,8 @@ current_map.finalize_load() log_ss("map_finalization", "Finalized map in [(world.time - time)/10] seconds.") - //Select ruin and spawn it - if(current_map.has_space_ruins) - select_ruin() - load_space_ruin() + select_ruin() + load_space_ruin() if(config.dungeon_chance > 0) place_dungeon_spawns() @@ -48,62 +46,87 @@ sortTim(all_areas, /proc/cmp_name_asc) /datum/controller/subsystem/finalize/proc/select_ruin() - var/list/ruinconfig = list() - var/list/ruinlist = list() - var/list/weightedlist = list() - try - ruinconfig = json_decode(return_file_text("config/space_ruins.json")) - catch(var/exception/ej) - log_debug("SSatlas: Warning: Could not load space ruin config, as space_ruins.json is missing - [ej]") - return + //Get all the folders in dynamic maps and check if they contain a config.json + var/map_directory = "dynamic_maps/" + var/list/mission_list = list() + var/list/weighted_mission_list = list() - for(var/ruinname in ruinconfig) - //Create the datums - var/datum/space_ruin/sr = new(ruinname,ruinconfig[ruinname]["file_name"]) - if("weight" in ruinconfig[ruinname]) - sr.weight = ruinconfig[ruinname]["weight"] - if("valid_maps" in ruinconfig[ruinname]) - sr.valid_maps = ruinconfig[ruinname]["valid_maps"] - if("characteristics" in ruinconfig[ruinname]) - sr.characteristics = ruinconfig[ruinname]["characteristics"] + var/list/subfolders = get_subfolders(map_directory) - //Check if the file exists - var/map_directory = "dynamic_maps/" - if(!fexists("[map_directory][sr.file_name]")) - admin_notice("Map file [sr.file_name] for ruin [sr.name] does not exist.") - log_ss("atlas","Map file [sr.file_name] for ruin [sr.name] does not exist.") + //Build the list of available missions + for(var/folder in subfolders) + var/list/mission_config = null + var/datum/away_mission/am = null + if(!fexists("[folder]config.json")) + log_ss("map_finalization", "Found no cofiguration file in [folder] - Skipping") continue - //Build the lists - if(length(sr.valid_maps)) - if(!(current_map.name in sr.valid_maps)) - continue - ruinlist[sr.name] = sr - weightedlist[sr.name] = sr.weight + try + mission_config = json_decode(file2text("[folder]config.json")) + catch(var/exception/ed) + log_ss("map_finalization", "Invalid config.json in [folder]: [ed]") + continue - if(!length(ruinlist)) - log_ss("atlas","Found no valid ruins for current map.") + try + am = new(mission_config, folder) + catch(var/exception/ec) + log_ss("map_finalization", "Error while creating away mission datum: [ec]") + continue + + if(length(am.valid_maps)) + if(!(current_map.name in am.valid_maps)) + log_ss("map_finalization", "[current_map.name] is not a valid map for [am.name]") + continue + + if(!am.validate_maps(folder)) + continue + + mission_list[am.name] = am + if(am.autoselect) + weighted_mission_list[am.name] = am.weight + else + log_debug("[am.name] has a disabled autoselect") + + if(!length(mission_list)) + log_ss("map_finalization", "Found no valid ruins for the current map.") return - log_ss("atlas", "Loaded ruin config.") - var/ruinname = pickweight(weightedlist) - selected_ruin = ruinlist[ruinname] + log_ss("map_finalization", "Loaded ruin config.") + + //Check if we have a enforced mission we should try to load. + if(SSpersist_config.forced_awaymission in mission_list) + selected_mission = mission_list[SSpersist_config.forced_awaymission] + log_ss("map_finalization", "Selected enforced away mission.") + admin_notice(SPAN_DANGER("Selected enforced away mission."), R_DEBUG) + return + else + log_ss("map_finalization", "Failed to selected enforced away mission. Fallback to weighted selection.") + admin_notice(SPAN_DANGER("Failed to selected enforced away mission. Fallback to weighted selection."), R_DEBUG) + + var/mission_name = pickweight(weighted_mission_list) + selected_mission = mission_list[mission_name] + admin_notice(SPAN_DANGER("Selected away mission."), R_DEBUG) return /datum/controller/subsystem/finalize/proc/load_space_ruin() maploader = new - if(!selected_ruin) + if(!selected_mission) + log_ss("map_finalization", "Not loading away mission, because no mission has been selected.") + admin_notice(SPAN_DANGER("Not loading away mission, because no mission has been selected."), R_DEBUG) return - var/map_directory = "dynamic_maps/" - var/mfile = "[map_directory][selected_ruin.file_name]" - var/time = world.time + for(var/map in selected_mission.map_files) + var/mfile = "[selected_mission.base_dir][map]" + var/time = world.time + log_debug("Attempting to load [mfile]") - if (!maploader.load_map(file(mfile), 0, 0, no_changeturf = TRUE)) - log_ss("finalize", "Failed to load '[mfile]'!") - else - log_ss("finalize", "Loaded space ruin on z [world.maxz] in [(world.time - time)/10] seconds.") - current_map.restricted_levels.Add(world.maxz) + if (!maploader.load_map(file(mfile), 0, 0, no_changeturf = TRUE)) + log_ss("map_finalization", "Failed to load '[mfile]'!") + admin_notice(SPAN_DANGER("Failed to load '[mfile]'!"), R_DEBUG) + else + log_ss("map_finalization", "Loaded away mission on z [world.maxz] in [(world.time - time)/10] seconds.") + admin_notice(SPAN_DANGER("Loaded away mission on z [world.maxz] in [(world.time - time)/10] seconds."), R_DEBUG) + current_map.restricted_levels.Add(world.maxz) QDEL_NULL(maploader) /datum/controller/subsystem/finalize/proc/place_dungeon_spawns() @@ -149,11 +172,11 @@ qdel(maploader) /datum/controller/subsystem/finalize/proc/generate_contact_report() - if(!selected_ruin) + if(!selected_mission) return - var/report_text = selected_ruin.get_contact_report() + var/report_text = selected_mission.get_contact_report() for(var/obj/effect/landmark/C in landmarks_list) - if(C.name == "Space Ruin Paper") + if(C.name == "Mission Paper") var/obj/item/paper/P = new /obj/item/paper(get_turf(C)) P.name = "Icarus reading report" P.info = report_text diff --git a/code/controllers/subsystems/initialization/persistent_configuration.dm b/code/controllers/subsystems/initialization/persistent_configuration.dm index 573910d06e5..5f421688016 100644 --- a/code/controllers/subsystems/initialization/persistent_configuration.dm +++ b/code/controllers/subsystems/initialization/persistent_configuration.dm @@ -10,10 +10,11 @@ // in this config! This config is viewable by VV. // Keep this variable up to date for the parsers to work. - var/list/_variables_to_save = list("last_gamemode", "rounds_since_hard_restart") + var/list/_variables_to_save = list("last_gamemode", "rounds_since_hard_restart", "forced_awaymission") var/last_gamemode = "extended" var/rounds_since_hard_restart = 0 + var/forced_awaymission = FALSE /datum/controller/subsystem/persistent_configuration/Initialize(timeofday) SSpersist_config = src @@ -57,6 +58,7 @@ master_mode = last_gamemode IF_FOUND_CONV(decoded, rounds_since_hard_restart, text2num) + IF_FOUND_USE(decoded, forced_awaymission) #undef IF_FOUND_USE #undef IF_FOUND_CONV diff --git a/code/datums/helper_datums/away_mission.dm b/code/datums/helper_datums/away_mission.dm new file mode 100644 index 00000000000..c0006563a7b --- /dev/null +++ b/code/datums/helper_datums/away_mission.dm @@ -0,0 +1,41 @@ +/datum/away_mission + var/name + var/weight = 1 + var/autoselect = TRUE + var/list/map_files = null + var/list/valid_maps = null + var/list/characteristics = null + + var/base_dir = null + +/datum/away_mission/New(var/list/config, var/i_base_dir) + name = config["name"] + weight = config["weight"] + autoselect = config["autoselect"] + map_files = config["map_files"] + valid_maps = config["valid_maps"] + characteristics = config["characteristics"] + base_dir = i_base_dir + +/datum/away_mission/proc/validate_maps() + for(var/map in map_files) + if(!fexists("[base_dir][map]")) + log_debug("[base_dir][map] does not exist") + return FALSE + return TRUE + +/datum/away_mission/proc/get_contact_report() + var/list/schar = sortList(characteristics) //Sort them alphabetically to avoid metaing based on the order + var/ruintext = "


Icarus Reading Report


" + ruintext += "The NDV Icarus sensors have located an away site with the following possible characteristics:

" + + ruintext += "This reading has been detected within shuttle range of the [current_map.station_name] and deemed safe for survey by [current_map.company_name] personnel. \ + The designated research director, or a captain level decision may determine the goal of any missions to this site. On-site command is deferred to any nearby command staff.
" + + return ruintext diff --git a/code/datums/helper_datums/space_ruin.dm b/code/datums/helper_datums/space_ruin.dm deleted file mode 100644 index 84cc3442c25..00000000000 --- a/code/datums/helper_datums/space_ruin.dm +++ /dev/null @@ -1,26 +0,0 @@ -/datum/space_ruin - var/name - var/file_name - var/weight = 1 - var/list/valid_maps = null - var/list/characteristics = null - -/datum/space_ruin/New(var/i_name, var/i_file_name) - name = i_name - file_name = i_file_name - -/datum/space_ruin/proc/get_contact_report() - var/list/schar = sortList(characteristics) //Sort them alphabetically to avoid metaing based on the order - var/ruintext = "


Icarus Reading Report


" - ruintext += "The Icarus sensors located a away site with the possible characteristics:

" - - ruintext += "This reading has been detected within shuttle range of the [current_map.station_name] and deemed safe for survey by [current_map.company_name] personnel. \ - The designated research director, or a captain level decision may determine the goal of any missions to this site. On-site command is deferred to any nearby command staff.
" - - return ruintext \ No newline at end of file diff --git a/config/example/space_ruins.json b/config/example/space_ruins.json deleted file mode 100644 index ac93d5e6690..00000000000 --- a/config/example/space_ruins.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "derelict": { - "file_name": "derelict.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Abandoned Infrastructure": 100, - "Artificial Intelligence Signals": 20, - "Bluespace Signals": 20, - "Unrecognizable Signals": 20 - } - }, - "listening post": { - "file_name": "listening_post.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Bluespace Signals": 20, - "Artificial Intelligence Signals": 20, - "Unrecognizable Signals": 20 - } - }, - "pra blockade runner": { - "file_name": "pra_blockade_runner.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Bluespace Signals": 20, - "Unrecognizable Signals": 20 - } - }, - "sol corvette": { - "file_name": "sol_corvette.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Life Form Signals": 20, - "Bluespace Signals": 20, - "Unrecognizable Signals": 20 - } - }, - "scrapheap": { - "file_name": "scrapheap.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Unrecognizable Signals": 100, - "Life Form Signals": 20, - "Bluespace Signals": 20 - } - }, - "diona gestalt": { - "file_name": "diona_gestalt.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Large biomass signals": 100, - "Life Form Signals": 20 - } - }, - "spacehulk": { - "file_name": "spacehulk.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Bluespace Signals": 20, - "Unrecognizable Signals": 20 - } - }, - "kataphractchapter": { - "file_name": "kataphract_chapter.dmm", - "valid maps": ["aurora"], - "characteristics": { - "Life Form Signals": 20, - "Bluespace Signals": 20 - } - } -} \ No newline at end of file diff --git a/dynamic_maps/.gitignore b/dynamic_maps/.gitignore index f826bafcfa1..bc6e3db5daa 100644 --- a/dynamic_maps/.gitignore +++ b/dynamic_maps/.gitignore @@ -1 +1,2 @@ -*.dmm \ No newline at end of file +*.dmm +*/config.json \ No newline at end of file diff --git a/maps/_common/mapsystem/map.dm b/maps/_common/mapsystem/map.dm index 5fda01c0117..c14a141492f 100644 --- a/maps/_common/mapsystem/map.dm +++ b/maps/_common/mapsystem/map.dm @@ -65,8 +65,6 @@ var/lobby_icon // The icon which contains the lobby image(s) var/list/lobby_screens = list("title") // The list of lobby screen to pick() from. If left unset the first icon state is always selected. - var/has_space_ruins = FALSE //if this map picks and creates a space ruin - /datum/map/New() if(!map_levels) map_levels = station_levels.Copy() diff --git a/maps/aurora/aurora-4_mainlevel.dmm b/maps/aurora/aurora-4_mainlevel.dmm index 0d3ca85cd1d..049a84d05eb 100644 --- a/maps/aurora/aurora-4_mainlevel.dmm +++ b/maps/aurora/aurora-4_mainlevel.dmm @@ -44861,7 +44861,7 @@ /obj/item/pen, /obj/effect/floor_decal/corner/grey/diagonal, /obj/effect/landmark{ - name = "Space Ruin Paper" + name = "Mission Paper" }, /turf/simulated/floor/tiled/white, /area/rnd/rdoffice) diff --git a/maps/aurora/aurora-6_surface.dmm b/maps/aurora/aurora-6_surface.dmm index 4ff67226691..bdb2c6262c3 100644 --- a/maps/aurora/aurora-6_surface.dmm +++ b/maps/aurora/aurora-6_surface.dmm @@ -14461,7 +14461,7 @@ dir = 6 }, /obj/effect/landmark{ - name = "Space Ruin Paper" + name = "Mission Paper" }, /turf/simulated/floor/tiled, /area/shuttle/research/station) diff --git a/maps/aurora/code/aurora.dm b/maps/aurora/code/aurora.dm index fc6617fd3d4..f5e53baf6e7 100644 --- a/maps/aurora/code/aurora.dm +++ b/maps/aurora/code/aurora.dm @@ -23,8 +23,6 @@ "9" = /turf/space ) - has_space_ruins = TRUE - station_name = "NSS Aurora" station_short = "Aurora" dock_name = "NTCC Odin"