mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 18:22:14 +00:00
## About The Pull Request Fixes all instances of numbers being used as assoc list keys in things that aren't alists, either by turning them into alists or changing the keys to something else. Also adds new macros to support creating global alists, as a few global lists became alists. Most of these are pretty simple and self-explanatory but - The GLOB.huds one necessitated rewriting because code depended on it being a non-assoc list, which it technically was because the defines it used as keys were numbers so BYOND turned it into a regular list, most of this was for loops through all the subtypes of `/datum/atom_hud/data/diagnostic` of which there's only one, so I just changed it to get that type directly by key - NT Frontier used number indexes which it looped through for some reason and also passed to TGUI, changed these to strings and adjusted the TGUI to match, I tested this and it works fine ## Why It's Good For The Game Makes the code compile, I couldn't test everything but I tried to check all usages of affected vars to make sure they wouldn't break from being switched to alists, a TM might be in order just to be sure nothing's fucked ## Changelog 🆑 refactor: rewrote all cases of numbers being used as keys in non-alist associative lists /🆑
434 lines
16 KiB
Plaintext
434 lines
16 KiB
Plaintext
/datum/dynamic_ruleset/roundstart
|
|
// We can pick multiple of a roundstart ruleset to "scale up" (spawn more of the same type of antag)
|
|
// Set this to FALSE if you DON'T want this ruleset to "scale up"
|
|
repeatable = TRUE
|
|
/// If TRUE, the ruleset will be the only one selected for roundstart
|
|
var/solo = FALSE
|
|
|
|
/datum/dynamic_ruleset/roundstart/is_valid_candidate(mob/candidate, client/candidate_client)
|
|
if(isnull(candidate.mind))
|
|
return FALSE
|
|
// Checks that any other roundstart ruleset hasn't already picked this guy
|
|
for(var/datum/dynamic_ruleset/roundstart/ruleset as anything in SSdynamic.queued_rulesets)
|
|
if(candidate.mind in ruleset.selected_minds)
|
|
return FALSE
|
|
return ..()
|
|
|
|
/// Helpful proc - to use if your ruleset forces a job - which ensures a candidate can play the passed job typepath
|
|
/datum/dynamic_ruleset/roundstart/proc/ruleset_forced_job_check(mob/candidate, client/candidate_client, datum/job/job_typepath)
|
|
// Malf AI can only go to people who want to be AI
|
|
if(!candidate_client.prefs.job_preferences[job_typepath::title])
|
|
return FALSE
|
|
// And only to people who can actually be AI this round
|
|
if(SSjob.check_job_eligibility(candidate, SSjob.get_job_type(job_typepath), "[name] Candidacy") != JOB_AVAILABLE)
|
|
return FALSE
|
|
// (Something else forced us to play a job that isn't AI)
|
|
var/forced_job = LAZYACCESS(SSjob.forced_occupations, candidate)
|
|
if(forced_job && forced_job != job_typepath)
|
|
return FALSE
|
|
// (Something else forced us NOT to play AI)
|
|
if(job_typepath::title in LAZYACCESS(SSjob.prevented_occupations, candidate))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/dynamic_ruleset/roundstart/traitor
|
|
name = "Traitors"
|
|
config_tag = "Roundstart Traitor"
|
|
preview_antag_datum = /datum/antagonist/traitor
|
|
pref_flag = ROLE_TRAITOR
|
|
weight = 10
|
|
min_pop = 3
|
|
max_antag_cap = list("denominator" = 24)
|
|
|
|
/datum/dynamic_ruleset/roundstart/traitor/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/traitor)
|
|
|
|
/datum/dynamic_ruleset/roundstart/malf_ai
|
|
name = "Malfunctioning AI"
|
|
config_tag = "Roundstart Malfunctioning AI"
|
|
pref_flag = ROLE_MALF
|
|
preview_antag_datum = /datum/antagonist/malf_ai
|
|
ruleset_flags = RULESET_HIGH_IMPACT
|
|
weight = alist(
|
|
DYNAMIC_TIER_LOW = 0,
|
|
DYNAMIC_TIER_LOWMEDIUM = 1,
|
|
DYNAMIC_TIER_MEDIUMHIGH = 3,
|
|
DYNAMIC_TIER_HIGH = 3,
|
|
)
|
|
min_pop = 30
|
|
max_antag_cap = 1
|
|
repeatable = FALSE
|
|
|
|
/datum/dynamic_ruleset/roundstart/malf_ai/get_always_blacklisted_roles()
|
|
return list()
|
|
|
|
/datum/dynamic_ruleset/roundstart/malf_ai/is_valid_candidate(mob/candidate, client/candidate_client)
|
|
return ..() && ruleset_forced_job_check(candidate, candidate_client, /datum/job/ai)
|
|
|
|
/datum/dynamic_ruleset/roundstart/malf_ai/prepare_for_role(datum/mind/candidate)
|
|
LAZYSET(SSjob.forced_occupations, candidate, /datum/job/ai)
|
|
|
|
/datum/dynamic_ruleset/roundstart/malf_ai/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/malf_ai)
|
|
|
|
/datum/dynamic_ruleset/roundstart/malf_ai/can_be_selected()
|
|
return ..() && !HAS_TRAIT(SSstation, STATION_TRAIT_HUMAN_AI)
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_brother
|
|
name = "Blood Brothers"
|
|
config_tag = "Roundstart Blood Brothers"
|
|
preview_antag_datum = /datum/antagonist/brother
|
|
pref_flag = ROLE_BROTHER
|
|
weight = 5
|
|
max_antag_cap = list("denominator" = 29)
|
|
min_pop = 10
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_brother/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/brother)
|
|
|
|
/datum/dynamic_ruleset/roundstart/changeling
|
|
name = "Changelings"
|
|
config_tag = "Roundstart Changeling"
|
|
preview_antag_datum = /datum/antagonist/changeling
|
|
pref_flag = ROLE_CHANGELING
|
|
weight = 3
|
|
min_pop = 15
|
|
max_antag_cap = list("denominator" = 29)
|
|
|
|
/datum/dynamic_ruleset/roundstart/changeling/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/changeling)
|
|
|
|
/datum/dynamic_ruleset/roundstart/heretic
|
|
name = "Heretics"
|
|
config_tag = "Roundstart Heretics"
|
|
preview_antag_datum = /datum/antagonist/heretic
|
|
pref_flag = ROLE_HERETIC
|
|
weight = 3
|
|
max_antag_cap = list("denominator" = 24)
|
|
min_pop = 30 // Ensures good spread of sacrifice targets
|
|
|
|
/datum/dynamic_ruleset/roundstart/heretic/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/heretic)
|
|
|
|
/datum/dynamic_ruleset/roundstart/wizard
|
|
name = "Wizard"
|
|
config_tag = "Roundstart Wizard"
|
|
preview_antag_datum = /datum/antagonist/wizard
|
|
pref_flag = ROLE_WIZARD
|
|
ruleset_flags = RULESET_INVADER|RULESET_HIGH_IMPACT
|
|
weight = alist(
|
|
DYNAMIC_TIER_LOW = 0,
|
|
DYNAMIC_TIER_LOWMEDIUM = 0,
|
|
DYNAMIC_TIER_MEDIUMHIGH = 1,
|
|
DYNAMIC_TIER_HIGH = 2,
|
|
)
|
|
max_antag_cap = 1
|
|
min_pop = 30
|
|
ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_WIZARDDEN)
|
|
repeatable = FALSE
|
|
|
|
/datum/dynamic_ruleset/roundstart/wizard/prepare_for_role(datum/mind/candidate)
|
|
LAZYSET(SSjob.forced_occupations, candidate, /datum/job/space_wizard)
|
|
|
|
/datum/dynamic_ruleset/roundstart/wizard/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/wizard) // moves to lair for us
|
|
|
|
/datum/dynamic_ruleset/roundstart/wizard/round_result()
|
|
for(var/datum/mind/wiz as anything in selected_minds)
|
|
if(considered_alive(wiz) && !considered_exiled(wiz))
|
|
return FALSE
|
|
|
|
SSticker.news_report = WIZARD_KILLED
|
|
return TRUE
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_cult
|
|
name = "Blood Cult"
|
|
config_tag = "Roundstart Blood Cult"
|
|
preview_antag_datum = /datum/antagonist/cult
|
|
pref_flag = ROLE_CULTIST
|
|
ruleset_flags = RULESET_HIGH_IMPACT
|
|
weight = alist(
|
|
DYNAMIC_TIER_LOW = 0,
|
|
DYNAMIC_TIER_LOWMEDIUM = 1,
|
|
DYNAMIC_TIER_MEDIUMHIGH = 3,
|
|
DYNAMIC_TIER_HIGH = 3,
|
|
)
|
|
min_pop = 30
|
|
blacklisted_roles = list(
|
|
JOB_HEAD_OF_PERSONNEL,
|
|
)
|
|
min_antag_cap = list("denominator" = 20, "offset" = 1)
|
|
repeatable = FALSE
|
|
/// Ratio of cultists getting on the shuttle to be considered a minor win
|
|
var/ratio_to_be_considered_escaped = 0.5
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_cult/get_always_blacklisted_roles()
|
|
return ..() | JOB_CHAPLAIN
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_cult/create_execute_args()
|
|
return list(
|
|
new /datum/team/cult(),
|
|
get_most_experienced(selected_minds, pref_flag),
|
|
)
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_cult/execute()
|
|
. = ..()
|
|
// future todo, find a cleaner way to get this from execute args
|
|
var/datum/team/cult/main_cult = locate() in GLOB.antagonist_teams
|
|
main_cult.setup_objectives()
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_cult/assign_role(datum/mind/candidate, datum/team/cult/cult, datum/mind/most_experienced)
|
|
var/datum/antagonist/cult/cultist = new()
|
|
cultist.give_equipment = TRUE
|
|
candidate.add_antag_datum(cultist, cult)
|
|
if(most_experienced == candidate)
|
|
cultist.make_cult_leader()
|
|
|
|
/datum/dynamic_ruleset/roundstart/blood_cult/round_result()
|
|
var/datum/team/cult/main_cult = locate() in GLOB.antagonist_teams
|
|
if(main_cult.check_cult_victory())
|
|
SSticker.mode_result = "win - cult win"
|
|
SSticker.news_report = CULT_SUMMON
|
|
return TRUE
|
|
|
|
var/num_cultists = main_cult.size_at_maximum || 100
|
|
var/ratio_to_be_considered_escaped = 0.5
|
|
var/escaped_cultists = 0
|
|
for(var/datum/mind/escapee as anything in main_cult.members)
|
|
if(considered_escaped(escapee))
|
|
escaped_cultists++
|
|
|
|
SSticker.mode_result = "loss - staff stopped the cult"
|
|
SSticker.news_report = (escaped_cultists / num_cultists) >= ratio_to_be_considered_escaped ? CULT_ESCAPE : CULT_FAILURE
|
|
return TRUE
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies
|
|
name = "Nuclear Operatives"
|
|
config_tag = "Roundstart Nukeops"
|
|
preview_antag_datum = /datum/antagonist/nukeop
|
|
pref_flag = ROLE_OPERATIVE
|
|
ruleset_flags = RULESET_INVADER|RULESET_HIGH_IMPACT
|
|
weight = alist(
|
|
DYNAMIC_TIER_LOW = 0,
|
|
DYNAMIC_TIER_LOWMEDIUM = 1,
|
|
DYNAMIC_TIER_MEDIUMHIGH = 3,
|
|
DYNAMIC_TIER_HIGH = 3,
|
|
)
|
|
min_pop = 30
|
|
min_antag_cap = list("denominator" = 18, "offset" = 1)
|
|
ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_NUKIEBASE)
|
|
repeatable = FALSE
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/prepare_for_role(datum/mind/candidate)
|
|
LAZYSET(SSjob.forced_occupations, candidate, /datum/job/nuclear_operative)
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/create_execute_args()
|
|
return list(
|
|
new /datum/team/nuclear(),
|
|
get_most_experienced(selected_minds, pref_flag),
|
|
)
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/assign_role(datum/mind/candidate, datum/team/nuke_team, datum/mind/most_experienced)
|
|
if(most_experienced == candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/nukeop/leader, nuke_team)
|
|
else
|
|
candidate.add_antag_datum(/datum/antagonist/nukeop, nuke_team)
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/round_result()
|
|
var/datum/antagonist/nukeop/nukie = selected_minds[1].has_antag_datum(/datum/antagonist/nukeop)
|
|
var/datum/team/nuclear/nuke_team = nukie.get_team()
|
|
var/result = nuke_team.get_result()
|
|
switch(result)
|
|
if(NUKE_RESULT_FLUKE)
|
|
SSticker.mode_result = "loss - syndicate nuked - disk secured"
|
|
SSticker.news_report = NUKE_SYNDICATE_BASE
|
|
if(NUKE_RESULT_NUKE_WIN)
|
|
SSticker.mode_result = "win - syndicate nuke"
|
|
SSticker.news_report = STATION_DESTROYED_NUKE
|
|
if(NUKE_RESULT_NOSURVIVORS)
|
|
SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time"
|
|
SSticker.news_report = STATION_DESTROYED_NUKE
|
|
if(NUKE_RESULT_WRONG_STATION)
|
|
SSticker.mode_result = "halfwin - blew wrong station"
|
|
SSticker.news_report = NUKE_MISS
|
|
if(NUKE_RESULT_WRONG_STATION_DEAD)
|
|
SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time"
|
|
SSticker.news_report = NUKE_MISS
|
|
if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD)
|
|
SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead"
|
|
SSticker.news_report = OPERATIVES_KILLED
|
|
if(NUKE_RESULT_CREW_WIN)
|
|
SSticker.mode_result = "loss - evacuation - disk secured"
|
|
SSticker.news_report = OPERATIVES_KILLED
|
|
if(NUKE_RESULT_DISK_LOST)
|
|
SSticker.mode_result = "halfwin - evacuation - disk not secured"
|
|
SSticker.news_report = OPERATIVE_SKIRMISH
|
|
if(NUKE_RESULT_DISK_STOLEN)
|
|
SSticker.mode_result = "halfwin - detonation averted"
|
|
SSticker.news_report = OPERATIVE_SKIRMISH
|
|
else
|
|
SSticker.mode_result = "halfwin - interrupted"
|
|
SSticker.news_report = OPERATIVE_SKIRMISH
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/clown
|
|
name = "Clown Operatives"
|
|
config_tag = "Roundstart Clownops"
|
|
preview_antag_datum = /datum/antagonist/nukeop/clownop
|
|
pref_flag = ROLE_CLOWN_OPERATIVE
|
|
weight = 0
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/clown/prepare_for_role(datum/mind/candidate)
|
|
LAZYSET(SSjob.forced_occupations, candidate, /datum/job/nuclear_operative/clown_operative)
|
|
|
|
/datum/dynamic_ruleset/roundstart/nukies/clown/assign_role(datum/mind/candidate, datum/team/nuke_team, datum/mind/most_experienced)
|
|
if(most_experienced == candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/nukeop/leader/clownop)
|
|
else
|
|
candidate.add_antag_datum(/datum/antagonist/nukeop/clownop)
|
|
|
|
/datum/dynamic_ruleset/roundstart/revolution
|
|
name = "Revolution"
|
|
config_tag = "Roundstart Revolution"
|
|
preview_antag_datum = /datum/antagonist/rev/head
|
|
pref_flag = ROLE_REV_HEAD
|
|
ruleset_flags = RULESET_HIGH_IMPACT
|
|
weight = alist(
|
|
DYNAMIC_TIER_LOW = 0,
|
|
DYNAMIC_TIER_LOWMEDIUM = 1,
|
|
DYNAMIC_TIER_MEDIUMHIGH = 3,
|
|
DYNAMIC_TIER_HIGH = 3,
|
|
)
|
|
min_pop = 30
|
|
min_antag_cap = 1
|
|
max_antag_cap = 3
|
|
repeatable = FALSE
|
|
/// If we have fewer heads of staff than this 7 minutes into the round, we'll cancel the revolution
|
|
var/heads_necessary = 2
|
|
|
|
/datum/dynamic_ruleset/roundstart/revolution/get_always_blacklisted_roles()
|
|
. = ..()
|
|
for(var/datum/job/job as anything in SSjob.all_occupations)
|
|
if(job.job_flags & JOB_HEAD_OF_STAFF)
|
|
. |= job.title
|
|
|
|
/datum/dynamic_ruleset/roundstart/revolution/assign_role(datum/mind/candidate)
|
|
LAZYADD(candidate.special_roles, "Dormant Head Revolutionary")
|
|
addtimer(CALLBACK(src, PROC_REF(reveal_head), candidate), 7 MINUTES, TIMER_DELETE_ME)
|
|
|
|
/// Reveals the headrev after a set amount of time
|
|
/datum/dynamic_ruleset/roundstart/revolution/proc/reveal_head(datum/mind/candidate)
|
|
LAZYREMOVE(candidate.special_roles, "Dormant Head Revolutionary")
|
|
|
|
var/head_check = 0
|
|
for(var/mob/player as anything in get_active_player_list(alive_check = TRUE, afk_check = TRUE))
|
|
if(player.mind?.assigned_role.job_flags & JOB_HEAD_OF_STAFF)
|
|
head_check++
|
|
|
|
if(head_check < heads_necessary)
|
|
log_dynamic("[config_tag]: Not enough heads of staff were present to start a revolution.")
|
|
addtimer(CALLBACK(src, PROC_REF(revs_execution_failed)), 1 MINUTES, TIMER_UNIQUE|TIMER_DELETE_ME)
|
|
return
|
|
|
|
if(!can_be_headrev(candidate))
|
|
log_dynamic("[config_tag]: [key_name(candidate)] was not eligible to be a headrev after the timer expired - finding a replacement.")
|
|
find_another_headrev()
|
|
return
|
|
|
|
GLOB.revolution_handler ||= new()
|
|
var/datum/antagonist/rev/head/new_head = new()
|
|
new_head.give_flash = TRUE
|
|
new_head.give_hud = TRUE
|
|
new_head.remove_clumsy = TRUE
|
|
candidate.add_antag_datum(new_head, GLOB.revolution_handler.revs)
|
|
GLOB.revolution_handler.start_revolution()
|
|
|
|
/datum/dynamic_ruleset/roundstart/revolution/proc/find_another_headrev()
|
|
for(var/mob/living/carbon/human/upstanding_citizen in GLOB.player_list)
|
|
if(!can_be_headrev(upstanding_citizen.mind))
|
|
continue
|
|
reveal_head(upstanding_citizen.mind)
|
|
log_dynamic("[config_tag]: [key_name(upstanding_citizen)] was selected as a replacement headrev.")
|
|
return
|
|
|
|
log_dynamic("[config_tag]: Failed to find a replacement headrev.")
|
|
addtimer(CALLBACK(src, PROC_REF(revs_execution_failed)), 1 MINUTES, TIMER_UNIQUE|TIMER_DELETE_ME)
|
|
|
|
/datum/dynamic_ruleset/roundstart/revolution/proc/revs_execution_failed()
|
|
if(GLOB.revolution_handler)
|
|
return
|
|
// Execution is effectively cancelled by this point, but it's not like we can go back and refund it
|
|
SSdynamic.unreported_rulesets += src
|
|
name += " (Canceled)"
|
|
log_dynamic("[config_tag]: All headrevs were ineligible after the timer expired, and no replacements could be found. Ruleset canceled.")
|
|
message_admins("[config_tag]: All headrevs were ineligible after the timer expired, and no replacements could be found. Ruleset canceled.")
|
|
|
|
/datum/dynamic_ruleset/roundstart/spies
|
|
name = "Spies"
|
|
config_tag = "Roundstart Spies"
|
|
preview_antag_datum = /datum/antagonist/spy
|
|
pref_flag = ROLE_SPY
|
|
weight = alist(
|
|
DYNAMIC_TIER_LOW = 0,
|
|
DYNAMIC_TIER_LOWMEDIUM = 1,
|
|
DYNAMIC_TIER_MEDIUMHIGH = 3,
|
|
DYNAMIC_TIER_HIGH = 3,
|
|
)
|
|
min_pop = 10
|
|
min_antag_cap = list("denominator" = 20, "offset" = 1)
|
|
|
|
/datum/dynamic_ruleset/roundstart/spies/assign_role(datum/mind/candidate)
|
|
candidate.add_antag_datum(/datum/antagonist/spy)
|
|
|
|
/datum/dynamic_ruleset/roundstart/extended
|
|
name = "Extended"
|
|
config_tag = "Extended"
|
|
weight = 0
|
|
min_antag_cap = 0
|
|
repeatable = FALSE
|
|
solo = TRUE
|
|
|
|
/datum/dynamic_ruleset/roundstart/extended/execute()
|
|
// No midrounds no latejoins
|
|
for(var/category in SSdynamic.rulesets_to_spawn)
|
|
SSdynamic.rulesets_to_spawn[category] = 0
|
|
|
|
/datum/dynamic_ruleset/roundstart/meteor
|
|
name = "Meteor"
|
|
config_tag = "Meteor"
|
|
weight = 0
|
|
min_antag_cap = 0
|
|
repeatable = FALSE
|
|
|
|
/datum/dynamic_ruleset/roundstart/meteor/execute()
|
|
GLOB.meteor_mode ||= new()
|
|
GLOB.meteor_mode.start_meteor()
|
|
|
|
/datum/dynamic_ruleset/roundstart/nations
|
|
name = "Nations"
|
|
config_tag = "Nations"
|
|
weight = 0
|
|
min_antag_cap = 0
|
|
repeatable = FALSE
|
|
solo = TRUE
|
|
|
|
/datum/dynamic_ruleset/roundstart/nations/execute()
|
|
// No midrounds no latejoins
|
|
for(var/category in SSdynamic.rulesets_to_spawn)
|
|
SSdynamic.rulesets_to_spawn[category] = 0
|
|
|
|
//notably assistant is not in this list to prevent the round turning into BARBARISM instantly, and silicon is in this list for UN
|
|
var/list/department_types = list(
|
|
/datum/job_department/silicon, //united nations
|
|
/datum/job_department/cargo,
|
|
/datum/job_department/engineering,
|
|
/datum/job_department/medical,
|
|
/datum/job_department/science,
|
|
/datum/job_department/security,
|
|
/datum/job_department/service,
|
|
)
|
|
|
|
for(var/department_type in department_types)
|
|
create_separatist_nation(department_type, announcement = FALSE, dangerous = FALSE, message_admins = FALSE)
|
|
|
|
GLOB.round_default_lawset = /datum/ai_laws/united_nations
|