From eea37d024dbfac4f65ce69d9acd2047852a7b9ad Mon Sep 17 00:00:00 2001 From: Neerti Date: Sun, 5 Apr 2020 17:33:48 -0400 Subject: [PATCH] Does some of the things Ater wants. --- code/controllers/subsystems/game_master.dm | 137 ------------------ code/datums/game_masters/_common.dm | 6 + code/datums/game_masters/default.dm | 89 ++++++++++++ .../datums/game_masters/other_game_masters.dm | 42 ++++++ .../event2/events/command/money_hacker.dm | 2 +- .../events/engineering/camera_damage.dm | 2 +- polaris.dme | 3 + 7 files changed, 142 insertions(+), 139 deletions(-) create mode 100644 code/datums/game_masters/_common.dm create mode 100644 code/datums/game_masters/default.dm create mode 100644 code/datums/game_masters/other_game_masters.dm diff --git a/code/controllers/subsystems/game_master.dm b/code/controllers/subsystems/game_master.dm index b27b6e578e..df00799805 100644 --- a/code/controllers/subsystems/game_master.dm +++ b/code/controllers/subsystems/game_master.dm @@ -153,143 +153,6 @@ SUBSYSTEM_DEF(game_master) /datum/game_master/New(datum/controller/subsystem/game_master/new_ticker) ticker = new_ticker -// Push button, receive event. -// Returns a selected event datum. -/datum/game_master/proc/choose_event() - -/datum/game_master/proc/log_game_master(message) - SSgame_master.log_game_master(message) - -// The default game master tries to choose events with these goals in mind. -// * Don't choose an event if the crew can't take it. E.g. no meteors after half of the crew died. -// * Try to involve lots of people, particuarly in active departments. -// * Avoid giving events to the same department multiple times in a row. -/datum/game_master/default - // If an event was done for a specific department, it is written here, so it doesn't do it again. - var/last_department_used = null - - -/datum/game_master/default/choose_event() - log_game_master("Now starting event decision.") - - var/list/most_active_departments = metric.assess_all_departments(3, list(last_department_used)) - var/list/best_events = decide_best_events(most_active_departments) - - if(LAZYLEN(best_events)) - log_game_master("Got [best_events.len] choice\s for the next event.") - var/list/weighted_events = list() - - for(var/E in best_events) - var/datum/event2/meta/event = E - var/weight = event.get_weight() - if(weight <= 0) - continue - weighted_events[event] = weight - log_game_master("Filtered down to [weighted_events.len] choice\s.") - - var/datum/event2/meta/choice = pickweight(weighted_events) - - if(choice) - log_game_master("[choice.name] was chosen, and is now being ran.") - last_department_used = LAZYACCESS(choice.departments, 1) - return choice - -/datum/game_master/default/proc/decide_best_events(list/most_active_departments) - if(!LAZYLEN(most_active_departments)) // Server's empty? - log_game_master("Game Master failed to find any active departments.") - return list() - - var/list/best_events = list() - if(most_active_departments.len >= 2) - var/list/top_two = list(most_active_departments[1], most_active_departments[2]) - best_events = filter_events_by_departments(top_two) - - if(LAZYLEN(best_events)) // We found something for those two, let's do it. - return best_events - - // Otherwise we probably couldn't find something for the second highest group, so let's ignore them. - best_events = filter_events_by_departments(most_active_departments[1]) - - if(LAZYLEN(best_events)) - return best_events - - // At this point we should expand our horizons. - best_events = filter_events_by_departments(list(DEPARTMENT_EVERYONE)) - - if(LAZYLEN(best_events)) - return best_events - - // Just give a random event if for some reason it still can't make up its mind. - best_events = filter_events_by_departments() - - if(LAZYLEN(best_events)) - return best_events - - log_game_master("Game Master failed to find a suitable event, something very wrong is going on.") - return list() - -// Filters the available events down to events for specific departments. -// Pass DEPARTMENT_EVERYONE if you want events that target the general population, like gravity failure. -// If no list is passed, all the events will be returned. -/datum/game_master/default/proc/filter_events_by_departments(list/departments) - . = list() - for(var/E in ticker.available_events) - var/datum/event2/meta/event = E - if(!event.enabled) - continue - if(event.chaotic_threshold && !ignore_round_chaos) - if(ticker.danger > event.chaotic_threshold) - continue - // An event has to involve all of these departments to pass. - var/viable = TRUE - if(LAZYLEN(departments)) - for(var/department in departments) - if(!LAZYFIND(departments, department)) - viable = FALSE - break - if(viable) - . += event - - -// The `classic` game master tries to act like the old system, choosing events without any specific goals. -// * Has no goals, and instead operates purely off of the weights of the events it has. -// * Does not react to danger at all. -/datum/game_master/classic/choose_event() - var/list/weighted_events = list() - for(var/E in ticker.available_events) - var/datum/event2/meta/event = E - weighted_events[event] = event.get_weight() - - var/datum/event2/meta/choice = pickweight(weighted_events) - - if(choice) - log_game_master("[choice.name] was chosen, and is now being ran.") - return choice - -// The `super_random` game master chooses events purely at random, ignoring weights entirely. -// * Has no goals, and instead chooses randomly, ignoring weights. -// * Does not react to danger at all. -/datum/game_master/super_random/choose_event() - return pick(ticker.available_events) - -// The `brutal` game master tries to run dangerous events frequently. -// * Chaotic events have their weights artifically boosted. -// * Ignores accumulated danger. -/datum/game_master/brutal - ignore_round_chaos = TRUE - -/datum/game_master/brutal/choose_event() - var/list/weighted_events = list() - for(var/E in ticker.available_events) - var/datum/event2/meta/event = E - weighted_events[event] = event.get_weight() + (event.chaos * 2) - - var/datum/event2/meta/choice = pickweight(weighted_events) - - if(choice) - log_game_master("[choice.name] was chosen, and is now being ran.") - return choice - /client/proc/show_gm_status() set category = "Debug" set name = "Show GM Status" diff --git a/code/datums/game_masters/_common.dm b/code/datums/game_masters/_common.dm new file mode 100644 index 0000000000..1d1fd24e0a --- /dev/null +++ b/code/datums/game_masters/_common.dm @@ -0,0 +1,6 @@ +// Push button, receive event. +// Returns a selected event datum. +/datum/game_master/proc/choose_event() + +/datum/game_master/proc/log_game_master(message) + SSgame_master.log_game_master(message) \ No newline at end of file diff --git a/code/datums/game_masters/default.dm b/code/datums/game_masters/default.dm new file mode 100644 index 0000000000..d846d9c7c1 --- /dev/null +++ b/code/datums/game_masters/default.dm @@ -0,0 +1,89 @@ +// The default game master tries to choose events with these goals in mind. +// * Don't choose an event if the crew can't take it. E.g. no meteors after half of the crew died. +// * Try to involve lots of people, particuarly in active departments. +// * Avoid giving events to the same department multiple times in a row. +/datum/game_master/default + // If an event was done for a specific department, it is written here, so it doesn't do it again. + var/last_department_used = null + + +/datum/game_master/default/choose_event() + log_game_master("Now starting event decision.") + + var/list/most_active_departments = metric.assess_all_departments(3, list(last_department_used)) + var/list/best_events = decide_best_events(most_active_departments) + + if(LAZYLEN(best_events)) + log_game_master("Got [best_events.len] choice\s for the next event.") + var/list/weighted_events = list() + + for(var/E in best_events) + var/datum/event2/meta/event = E + var/weight = event.get_weight() + if(weight <= 0) + continue + weighted_events[event] = weight + log_game_master("Filtered down to [weighted_events.len] choice\s.") + + var/datum/event2/meta/choice = pickweight(weighted_events) + + if(choice) + log_game_master("[choice.name] was chosen, and is now being ran.") + last_department_used = LAZYACCESS(choice.departments, 1) + return choice + +/datum/game_master/default/proc/decide_best_events(list/most_active_departments) + if(!LAZYLEN(most_active_departments)) // Server's empty? + log_game_master("Game Master failed to find any active departments.") + return list() + + var/list/best_events = list() + if(most_active_departments.len >= 2) + var/list/top_two = list(most_active_departments[1], most_active_departments[2]) + best_events = filter_events_by_departments(top_two) + + if(LAZYLEN(best_events)) // We found something for those two, let's do it. + return best_events + + // Otherwise we probably couldn't find something for the second highest group, so let's ignore them. + best_events = filter_events_by_departments(most_active_departments[1]) + + if(LAZYLEN(best_events)) + return best_events + + // At this point we should expand our horizons. + best_events = filter_events_by_departments(list(DEPARTMENT_EVERYONE)) + + if(LAZYLEN(best_events)) + return best_events + + // Just give a random event if for some reason it still can't make up its mind. + best_events = filter_events_by_departments() + + if(LAZYLEN(best_events)) + return best_events + + log_game_master("Game Master failed to find a suitable event, something very wrong is going on.") + return list() + +// Filters the available events down to events for specific departments. +// Pass DEPARTMENT_EVERYONE if you want events that target the general population, like gravity failure. +// If no list is passed, all the events will be returned. +/datum/game_master/default/proc/filter_events_by_departments(list/departments) + . = list() + for(var/E in ticker.available_events) + var/datum/event2/meta/event = E + if(!event.enabled) + continue + if(event.chaotic_threshold && !ignore_round_chaos) + if(ticker.danger > event.chaotic_threshold) + continue + // An event has to involve all of these departments to pass. + var/viable = TRUE + if(LAZYLEN(departments)) + for(var/department in departments) + if(!LAZYFIND(departments, department)) + viable = FALSE + break + if(viable) + . += event diff --git a/code/datums/game_masters/other_game_masters.dm b/code/datums/game_masters/other_game_masters.dm new file mode 100644 index 0000000000..ab8bb727f7 --- /dev/null +++ b/code/datums/game_masters/other_game_masters.dm @@ -0,0 +1,42 @@ +// The `classic` game master tries to act like the old system, choosing events without any specific goals. +// * Has no goals, and instead operates purely off of the weights of the events it has. +// * Does not react to danger at all. +/datum/game_master/classic/choose_event() + var/list/weighted_events = list() + for(var/E in ticker.available_events) + var/datum/event2/meta/event = E + weighted_events[event] = event.get_weight() + + var/datum/event2/meta/choice = pickweight(weighted_events) + + if(choice) + log_game_master("[choice.name] was chosen, and is now being ran.") + return choice + + +// The `super_random` game master chooses events purely at random, ignoring weights entirely. +// * Has no goals, and instead chooses randomly, ignoring weights. +// * Does not react to danger at all. +/datum/game_master/super_random/choose_event() + return pick(ticker.available_events) + + +// The `brutal` game master tries to run dangerous events frequently. +// * Chaotic events have their weights artifically boosted. +// * Ignores accumulated danger. +/datum/game_master/brutal + ignore_round_chaos = TRUE + +/datum/game_master/brutal/choose_event() + var/list/weighted_events = list() + for(var/E in ticker.available_events) + var/datum/event2/meta/event = E + if(!E.enabled) + continue + weighted_events[event] = event.get_weight() + (event.chaos * 2) + + var/datum/event2/meta/choice = pickweight(weighted_events) + + if(choice) + log_game_master("[choice.name] was chosen, and is now being ran.") + return choice \ No newline at end of file diff --git a/code/modules/gamemaster/event2/events/command/money_hacker.dm b/code/modules/gamemaster/event2/events/command/money_hacker.dm index c9a1212cf6..a1dbd1e18b 100644 --- a/code/modules/gamemaster/event2/events/command/money_hacker.dm +++ b/code/modules/gamemaster/event2/events/command/money_hacker.dm @@ -97,7 +97,7 @@ "69,420t" )) - var/date1 = "31 December, 1999" + var/date1 = "1 January 1970" // Unix epoch. var/date2 = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], [rand(1000,3000)]" T.date = pick("", current_date_string, date1, date2,"Nowhen") diff --git a/code/modules/gamemaster/event2/events/engineering/camera_damage.dm b/code/modules/gamemaster/event2/events/engineering/camera_damage.dm index 3fdeb3de00..c24fbb06f3 100644 --- a/code/modules/gamemaster/event2/events/engineering/camera_damage.dm +++ b/code/modules/gamemaster/event2/events/engineering/camera_damage.dm @@ -38,4 +38,4 @@ /datum/event2/event/camera_damage/proc/is_valid_camera(var/obj/machinery/camera/C) // Only return a functional camera, not installed in a silicon/hardsuit/circuit/etc, and that exists somewhere players have access var/turf/T = get_turf(C) - return T && C.can_use() && istype(C.loc, /turf) && (T.z in using_map.player_levels) \ No newline at end of file + return T && C?.can_use() && istype(C.loc, /turf) && (T.z in using_map.player_levels) \ No newline at end of file diff --git a/polaris.dme b/polaris.dme index 60a1455991..855816fda7 100644 --- a/polaris.dme +++ b/polaris.dme @@ -267,6 +267,9 @@ #include "code\datums\autolathe\general.dm" #include "code\datums\autolathe\medical.dm" #include "code\datums\autolathe\tools.dm" +#include "code\datums\game_masters\_common.dm" +#include "code\datums\game_masters\default.dm" +#include "code\datums\game_masters\other_game_masters.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\getrev.dm"