Files
GS13NG/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
Putnam cf77f7b18e Balance pass (see description)
1. Made bloodsuckers more likely on calm, story, slightly more common on intrigue
2. Made intrigue no longer have low threat by default
3. Made abductors have lower weights in general, making them less likely to show up
4. Made sentient disease, revenant less likely on calm
5. Added a new storyteller, "Conversion", which rolls conversion antags.
2019-12-31 02:40:50 -08:00

836 lines
31 KiB
Plaintext

//////////////////////////////////////////////
// //
// SYNDICATE TRAITORS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/traitor
name = "Traitors"
config_tag = "traitor"
persistent = TRUE
antag_flag = ROLE_TRAITOR
antag_datum = /datum/antagonist/traitor/
minimum_required_age = 0
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster", "Cyborg")
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
weight = 5
cost = 10 // Avoid raising traitor threat above 10, as it is the default low cost ruleset.
scaling_cost = 10
requirements = list(50,50,50,50,50,50,50,50,50,50)
high_population_requirement = 40
antag_cap = list(1,1,1,1,2,2,2,2,3,3)
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1, "valid" = 1)
always_max_weight = TRUE
var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec)
/datum/dynamic_ruleset/roundstart/traitor/pre_execute()
var/num_traitors = antag_cap[indice_pop] * (scaled_times + 1)
for (var/i = 1 to num_traitors)
var/mob/M = pick_n_take(candidates)
assigned += M.mind
M.mind.special_role = ROLE_TRAITOR
M.mind.restricted_roles = restricted_roles
return TRUE
/datum/dynamic_ruleset/roundstart/traitor/rule_process()
if (autotraitor_cooldown > 0)
autotraitor_cooldown--
else
autotraitor_cooldown = 450 // 15 minutes
message_admins("Checking if we can turn someone into a traitor.")
log_game("DYNAMIC: Checking if we can turn someone into a traitor.")
mode.picking_specific_rule(/datum/dynamic_ruleset/midround/autotraitor)
//////////////////////////////////////////
// //
// BLOOD BROTHERS //
// //
//////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/traitorbro
name = "Blood Brothers"
config_tag = "traitorbro"
antag_flag = ROLE_BROTHER
antag_datum = /datum/antagonist/brother
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 2
weight = 4
cost = 10
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
antag_cap = list(2,2,2,2,2,2,2,2,2,2) // Can pick 3 per team, but rare enough it doesn't matter.
property_weights = list("story_potential" = 1, "trust" = -1, "extended" = 1, "valid" = 1)
var/list/datum/team/brother_team/pre_brother_teams = list()
var/const/min_team_size = 2
/datum/dynamic_ruleset/roundstart/traitorbro/pre_execute()
var/num_teams = (antag_cap[indice_pop]/min_team_size) * (scaled_times + 1) // 1 team per scaling
for(var/j = 1 to num_teams)
if(candidates.len < min_team_size || candidates.len < required_candidates)
break
var/datum/team/brother_team/team = new
var/team_size = prob(10) ? min(3, candidates.len) : 2
for(var/k = 1 to team_size)
var/mob/bro = pick_n_take(candidates)
assigned += bro.mind
team.add_member(bro.mind)
bro.mind.special_role = "brother"
bro.mind.restricted_roles = restricted_roles
pre_brother_teams += team
return TRUE
/datum/dynamic_ruleset/roundstart/traitorbro/execute()
for(var/datum/team/brother_team/team in pre_brother_teams)
team.pick_meeting_area()
team.forge_brother_objectives()
for(var/datum/mind/M in team.members)
M.add_antag_datum(/datum/antagonist/brother, team)
team.update_name()
mode.brother_teams += pre_brother_teams
return TRUE
//////////////////////////////////////////////
// //
// CHANGELINGS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/changeling
name = "Changelings"
config_tag = "changeling"
antag_flag = ROLE_CHANGELING
antag_datum = /datum/antagonist/changeling
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 1
weight = 3
cost = 15
scaling_cost = 15
requirements = list(101,101,101,101,101,101,101,101,101,101)
property_weights = list("trust" = -2, "valid" = 2)
high_population_requirement = 10
antag_cap = list(1,1,1,1,1,2,2,2,2,3)
var/team_mode_probability = 30
/datum/dynamic_ruleset/roundstart/changeling/pre_execute()
var/num_changelings = antag_cap[indice_pop] * (scaled_times + 1)
for (var/i = 1 to num_changelings)
var/mob/M = pick_n_take(candidates)
assigned += M.mind
M.mind.restricted_roles = restricted_roles
M.mind.special_role = ROLE_CHANGELING
return TRUE
/datum/dynamic_ruleset/roundstart/changeling/execute()
var/team_mode = FALSE
if(prob(team_mode_probability))
team_mode = TRUE
var/list/team_objectives = subtypesof(/datum/objective/changeling_team_objective)
var/list/possible_team_objectives = list()
for(var/T in team_objectives)
var/datum/objective/changeling_team_objective/CTO = T
if(assigned.len >= initial(CTO.min_lings))
possible_team_objectives += T
if(possible_team_objectives.len && prob(20*assigned.len))
GLOB.changeling_team_objective_type = pick(possible_team_objectives)
for(var/datum/mind/changeling in assigned)
var/datum/antagonist/changeling/new_antag = new antag_datum()
new_antag.team_mode = team_mode
changeling.add_antag_datum(new_antag)
return TRUE
//////////////////////////////////////////////
// //
// WIZARDS //
// //
//////////////////////////////////////////////
// Dynamic is a wonderful thing that adds wizards to every round and then adds even more wizards during the round.
/datum/dynamic_ruleset/roundstart/wizard
name = "Wizard"
config_tag = "wizard"
persistent = TRUE
antag_flag = ROLE_WIZARD
antag_datum = /datum/antagonist/wizard
minimum_required_age = 14
restricted_roles = list("Head of Security", "Captain") // Just to be sure that a wizard getting picked won't ever imply a Captain or HoS not getting drafted
required_candidates = 1
weight = 1
cost = 30
requirements = list(101,101,101,60,50,50,50,50,50,50)
high_population_requirement = 50
property_weights = list("story_potential" = 2, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2)
var/list/roundstart_wizards = list()
/datum/dynamic_ruleset/roundstart/wizard/acceptable(population=0, threat=0)
if(GLOB.wizardstart.len == 0)
log_admin("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.")
message_admins("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.")
return FALSE
return ..()
/datum/dynamic_ruleset/roundstart/wizard/pre_execute()
if(GLOB.wizardstart.len == 0)
return FALSE
mode.antags_rolled += 1
var/mob/M = pick_n_take(candidates)
if (M)
assigned += M.mind
M.mind.assigned_role = ROLE_WIZARD
M.mind.special_role = ROLE_WIZARD
return TRUE
/datum/dynamic_ruleset/roundstart/wizard/execute()
for(var/datum/mind/M in assigned)
M.current.forceMove(pick(GLOB.wizardstart))
M.add_antag_datum(new antag_datum())
roundstart_wizards += M
return TRUE
/datum/dynamic_ruleset/roundstart/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great
for(var/datum/mind/wizard in roundstart_wizards)
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
return FALSE
for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead()
if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard))
return FALSE
if(SSevents.wizardmode) //If summon events was active, turn it off
SSevents.toggleWizardmode()
SSevents.resetFrequency()
return RULESET_STOP_PROCESSING
//////////////////////////////////////////////
// //
// BLOOD CULT //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/bloodcult
name = "Blood Cult"
config_tag = "cult"
antag_flag = ROLE_CULTIST
antag_datum = /datum/antagonist/cult
minimum_required_age = 14
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 2
weight = 3
cost = 30
requirements = list(101,101,101,80,70,60,50,50,50,50)
property_weights = list("story_potential" = -1, "trust" = -1, "chaos" = 1, "conversion" = 1, "extended" = -2, "valid" = 2)
high_population_requirement = 50
flags = HIGHLANDER_RULESET
antag_cap = list(2,2,2,3,3,4,4,4,4,4)
var/datum/team/cult/main_cult
/datum/dynamic_ruleset/roundstart/bloodcult/ready(forced = FALSE)
required_candidates = antag_cap[indice_pop]
. = ..()
/datum/dynamic_ruleset/roundstart/bloodcult/pre_execute()
var/cultists = antag_cap[indice_pop]
mode.antags_rolled += cultists
for(var/cultists_number = 1 to cultists)
if(candidates.len <= 0)
break
var/mob/M = pick_n_take(candidates)
assigned += M.mind
M.mind.special_role = ROLE_CULTIST
M.mind.restricted_roles = restricted_roles
return TRUE
/datum/dynamic_ruleset/roundstart/bloodcult/execute()
main_cult = new
for(var/datum/mind/M in assigned)
var/datum/antagonist/cult/new_cultist = new antag_datum()
new_cultist.cult_team = main_cult
new_cultist.give_equipment = TRUE
M.add_antag_datum(new_cultist)
main_cult.setup_objectives()
return TRUE
/datum/dynamic_ruleset/roundstart/bloodcult/round_result()
..()
if(main_cult.check_cult_victory())
SSticker.mode_result = "win - cult win"
SSticker.news_report = CULT_SUMMON
else
SSticker.mode_result = "loss - staff stopped the cult"
SSticker.news_report = CULT_FAILURE
//////////////////////////////////////////////
// //
// NUCLEAR OPERATIVES //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/nuclear
name = "Nuclear Emergency"
config_tag = "nuclear"
antag_flag = ROLE_OPERATIVE
antag_datum = /datum/antagonist/nukeop
var/datum/antagonist/antag_leader_datum = /datum/antagonist/nukeop/leader
minimum_required_age = 14
restricted_roles = list("Head of Security", "Captain") // Just to be sure that a nukie getting picked won't ever imply a Captain or HoS not getting drafted
required_candidates = 5
weight = 3
cost = 40
requirements = list(100,90,80,70,60,50,50,50,50,50)
high_population_requirement = 50
flags = HIGHLANDER_RULESET
antag_cap = list(1,1,2,3,4,5,5,5,5,5)
property_weights = list("story_potential" = 2, "trust" = 2, "chaos" = 2, "extended" = -2, "valid" = 2)
var/datum/team/nuclear/nuke_team
/datum/dynamic_ruleset/roundstart/nuclear/ready(forced = FALSE)
required_candidates = antag_cap[indice_pop]
. = ..()
/datum/dynamic_ruleset/roundstart/nuclear/pre_execute()
// If ready() did its job, candidates should have 5 or more members in it
var/operatives = antag_cap[indice_pop]
mode.antags_rolled += operatives
for(var/operatives_number = 1 to operatives)
if(candidates.len <= 0)
break
var/mob/M = pick_n_take(candidates)
assigned += M.mind
M.mind.assigned_role = "Nuclear Operative"
M.mind.special_role = "Nuclear Operative"
return TRUE
/datum/dynamic_ruleset/roundstart/nuclear/execute()
var/leader = TRUE
for(var/datum/mind/M in assigned)
if (leader)
leader = FALSE
var/datum/antagonist/nukeop/leader/new_op = M.add_antag_datum(antag_leader_datum)
nuke_team = new_op.nuke_team
else
var/datum/antagonist/nukeop/new_op = new antag_datum()
M.add_antag_datum(new_op)
return TRUE
/datum/dynamic_ruleset/roundstart/nuclear/round_result()
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_NUKED
if(NUKE_RESULT_NOSURVIVORS)
SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time"
SSticker.news_report = STATION_NUKED
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
//////////////////////////////////////////////
// //
// REVS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/revs
name = "Revolution"
config_tag = "revolution"
persistent = TRUE
antag_flag = ROLE_REV_HEAD
antag_flag_override = ROLE_REV
antag_datum = /datum/antagonist/rev/head
minimum_required_age = 14
restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 3
weight = 2
delay = 7 MINUTES
cost = 35
requirements = list(101,101,101,60,50,50,50,50,50,50)
high_population_requirement = 50
antag_cap = list(3,3,3,3,3,3,3,3,3,3)
flags = HIGHLANDER_RULESET
// I give up, just there should be enough heads with 35 players...
minimum_players = 35
property_weights = list("trust" = -2, "chaos" = 2, "extended" = -2, "valid" = 2, "conversion" = 1)
var/datum/team/revolution/revolution
var/finished = FALSE
/datum/dynamic_ruleset/roundstart/revs/pre_execute()
var/max_candidates = antag_cap[indice_pop]
mode.antags_rolled += max_candidates
for(var/i = 1 to max_candidates)
if(candidates.len <= 0)
break
var/mob/M = pick_n_take(candidates)
assigned += M.mind
M.mind.restricted_roles = restricted_roles
M.mind.special_role = antag_flag
return TRUE
/datum/dynamic_ruleset/roundstart/revs/execute()
var/success = TRUE
revolution = new()
for(var/datum/mind/M in assigned)
if(check_eligible(M))
var/datum/antagonist/rev/head/new_head = new antag_datum()
new_head.give_flash = TRUE
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
M.add_antag_datum(new_head,revolution)
else
assigned -= M
log_game("DYNAMIC: [ruletype] [name] discarded [M.name] from head revolutionary due to ineligibility.")
if(!revolution.members.len)
success = FALSE
log_game("DYNAMIC: [ruletype] [name] failed to get any eligible headrevs. Refunding [cost] threat.")
if(success)
revolution.update_objectives()
revolution.update_heads()
SSshuttle.registerHostileEnvironment(src)
return TRUE
return FALSE
/datum/dynamic_ruleset/roundstart/revs/clean_up()
qdel(revolution)
..()
/datum/dynamic_ruleset/roundstart/revs/rule_process()
if(check_rev_victory())
finished = REVOLUTION_VICTORY
return RULESET_STOP_PROCESSING
else if (check_heads_victory())
finished = STATION_VICTORY
SSshuttle.clearHostileEnvironment(src)
priority_announce("It appears the mutiny has been quelled. Please return yourself and your incapacitated colleagues to work. \
We have remotely blacklisted the head revolutionaries from your cloning software to prevent accidental cloning.", null, "attention", null, "Central Command Loyalty Monitoring Division")
for(var/datum/mind/M in revolution.members) // Remove antag datums and prevents podcloned or exiled headrevs restarting rebellions.
if(M.has_antag_datum(/datum/antagonist/rev/head))
var/datum/antagonist/rev/head/R = M.has_antag_datum(/datum/antagonist/rev/head)
R.remove_revolutionary(FALSE, "gamemode")
var/mob/living/carbon/C = M.current
if(C.stat == DEAD)
C.makeUncloneable()
if(M.has_antag_datum(/datum/antagonist/rev))
var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev)
R.remove_revolutionary(FALSE, "gamemode")
return RULESET_STOP_PROCESSING
/// Checks for revhead loss conditions and other antag datums.
/datum/dynamic_ruleset/roundstart/revs/proc/check_eligible(var/datum/mind/M)
var/turf/T = get_turf(M.current)
if(!considered_afk(M) && considered_alive(M) && is_station_level(T.z) && !M.antag_datums?.len && !HAS_TRAIT(M, TRAIT_MINDSHIELD))
return TRUE
return FALSE
/datum/dynamic_ruleset/roundstart/revs/check_finished()
if(finished == REVOLUTION_VICTORY)
return TRUE
else
return ..()
/datum/dynamic_ruleset/roundstart/revs/proc/check_rev_victory()
for(var/datum/objective/mutiny/objective in revolution.objectives)
if(!(objective.check_completion()))
return FALSE
return TRUE
/datum/dynamic_ruleset/roundstart/revs/proc/check_heads_victory()
for(var/datum/mind/rev_mind in revolution.head_revolutionaries())
var/turf/T = get_turf(rev_mind.current)
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(T.z))
if(ishuman(rev_mind.current) || ismonkey(rev_mind.current))
return FALSE
return TRUE
/datum/dynamic_ruleset/roundstart/revs/round_result()
if(finished == REVOLUTION_VICTORY)
SSticker.mode_result = "win - heads killed"
SSticker.news_report = REVS_WIN
else if(finished == STATION_VICTORY)
SSticker.mode_result = "loss - rev heads killed"
SSticker.news_report = REVS_LOSE
// Admin only rulesets. The threat requirement is 101 so it is not possible to roll them.
//////////////////////////////////////////////
// //
// EXTENDED //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/extended
name = "Extended"
config_tag = "extended"
antag_flag = null
antag_datum = null
restricted_roles = list()
required_candidates = 0
weight = 3
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
property_weights = list("extended" = 2)
high_population_requirement = 101
/datum/dynamic_ruleset/roundstart/extended/pre_execute()
message_admins("Starting a round of extended.")
log_game("Starting a round of extended.")
mode.spend_threat(mode.threat)
return TRUE
//////////////////////////////////////////////
// //
// CLOCKCULT //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/clockcult
name = "Clockcult"
config_tag = "clockwork_cult"
antag_flag = ROLE_SERVANT_OF_RATVAR
antag_datum = /datum/antagonist/clockcult
restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 4
weight = 3
cost = 35
requirements = list(101,101,101,80,70,60,50,50,50,50)
high_population_requirement = 50
flags = HIGHLANDER_RULESET
antag_cap = list(2,3,3,4,4,4,4,4,4,4)
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "conversion" = 1, "valid" = 2)
var/ark_time
/datum/dynamic_ruleset/roundstart/clockcult/pre_execute()
var/list/errorList = list()
var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE)
if(errorList.len)
message_admins("Reebe failed to load!")
log_game("Reebe failed to load!")
return FALSE
for(var/datum/parsed_map/PM in reebes)
PM.initTemplateBounds()
var/starter_servants = antag_cap[indice_pop]
var/number_players = mode.roundstart_pop_ready
if(number_players > 30)
number_players -= 30
starter_servants += min(round(number_players / 10), 5)
mode.antags_rolled += starter_servants
GLOB.clockwork_vitality += 50 * starter_servants
for (var/i in 1 to starter_servants)
var/mob/servant = pick_n_take(candidates)
assigned += servant.mind
servant.mind.assigned_role = ROLE_SERVANT_OF_RATVAR
servant.mind.special_role = ROLE_SERVANT_OF_RATVAR
ark_time = 30 + round((number_players / 5))
ark_time = min(ark_time, 35)
return TRUE
/datum/dynamic_ruleset/roundstart/clockcult/execute()
var/list/spread_out_spawns = GLOB.servant_spawns.Copy()
for(var/datum/mind/servant in assigned)
var/mob/S = servant.current
if(!spread_out_spawns.len)
spread_out_spawns = GLOB.servant_spawns.Copy()
log_game("[key_name(servant)] was made an initial servant of Ratvar")
var/turf/T = pick_n_take(spread_out_spawns)
S.forceMove(T)
greet_servant(S)
equip_servant(S)
add_servant_of_ratvar(S, TRUE)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar //that's a mouthful
G.final_countdown(ark_time)
return TRUE
/datum/dynamic_ruleset/roundstart/clockcult/proc/greet_servant(mob/M) //Description of their role
if(!M)
return 0
to_chat(M, "<span class='bold large_brass'>You are a servant of Ratvar, the Clockwork Justiciar!</span>")
to_chat(M, "<span class='brass'>You have approximately <b>[ark_time]</b> minutes until the Ark activates.</span>")
to_chat(M, "<span class='brass'>Unlock <b>Script</b> scripture by converting a new servant.</span>")
to_chat(M, "<span class='brass'><b>Application</b> scripture will be unlocked halfway until the Ark's activation.</span>")
M.playsound_local(get_turf(M), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE)
return 1
/datum/dynamic_ruleset/roundstart/clockcult/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob, with one of each component
if(!M || !ishuman(M))
return FALSE
var/mob/living/carbon/human/L = M
L.equipOutfit(/datum/outfit/servant_of_ratvar)
var/obj/item/clockwork/slab/S = new
var/slot = "At your feet"
var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK, "On your belt" = SLOT_BELT)
if(ishuman(L))
var/mob/living/carbon/human/H = L
slot = H.equip_in_one_of_slots(S, slots)
if(slot == "In your backpack")
slot = "In your [H.back.name]"
if(slot == "At your feet")
if(!S.forceMove(get_turf(L)))
qdel(S)
if(S && !QDELETED(S))
to_chat(L, "<span class='bold large_brass'>There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.</span>")
to_chat(L, "<span class='alloy'>[slot] is a <b>clockwork slab</b>, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
as a servant, you can find a concise tutorial in the Recollection category of its interface.</span>")
to_chat(L, "<span class='alloy italics'>If you want more information, you can read <a href=\"https://tgstation13.org/wiki/Clockwork_Cult\">the wiki page</a> to learn more.</span>")
return TRUE
return FALSE
/datum/dynamic_ruleset/roundstart/clockcult/round_result()
if(GLOB.clockwork_gateway_activated)
SSticker.news_report = CLOCK_SUMMON
SSticker.mode_result = "win - servants completed their objective (summon ratvar)"
else
SSticker.news_report = CULT_FAILURE
SSticker.mode_result = "loss - servants failed their objective (summon ratvar)"
//////////////////////////////////////////////
// //
// CLOWN OPS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/nuclear/clown_ops
name = "Clown Ops"
config_tag = "clownops"
antag_datum = /datum/antagonist/nukeop/clownop
antag_leader_datum = /datum/antagonist/nukeop/leader/clownop
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "story_potential" = 2, "valid" = 2)
/datum/dynamic_ruleset/roundstart/nuclear/clown_ops/pre_execute()
. = ..()
if(.)
for(var/obj/machinery/nuclearbomb/syndicate/S in GLOB.nuke_list)
var/turf/T = get_turf(S)
if(T)
qdel(S)
new /obj/machinery/nuclearbomb/syndicate/bananium(T)
for(var/datum/mind/V in assigned)
V.assigned_role = "Clown Operative"
V.special_role = "Clown Operative"
//////////////////////////////////////////////
// //
// DEVIL //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/devil
name = "Devil"
config_tag = "devil"
antag_flag = ROLE_DEVIL
antag_datum = /datum/antagonist/devil
restricted_roles = list("Lawyer", "Curator", "Chaplain", "Head of Security", "Captain", "AI")
required_candidates = 1
weight = 3
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
antag_cap = list(1,1,1,2,2,2,3,3,3,4)
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/roundstart/devil/pre_execute()
var/num_devils = antag_cap[indice_pop]
mode.antags_rolled += num_devils
for(var/j = 0, j < num_devils, j++)
if (!candidates.len)
break
var/mob/devil = pick_n_take(candidates)
assigned += devil.mind
devil.mind.special_role = ROLE_DEVIL
devil.mind.restricted_roles = restricted_roles
log_game("[key_name(devil)] has been selected as a devil")
return TRUE
/datum/dynamic_ruleset/roundstart/devil/execute()
for(var/datum/mind/devil in assigned)
add_devil(devil.current, ascendable = TRUE)
add_devil_objectives(devil,2)
return TRUE
/datum/dynamic_ruleset/roundstart/devil/proc/add_devil_objectives(datum/mind/devil_mind, quantity)
var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target)
var/datum/antagonist/devil/D = devil_mind.has_antag_datum(/datum/antagonist/devil)
for(var/i = 1 to quantity)
var/type = pick(validtypes)
var/datum/objective/devil/objective = new type(null)
objective.owner = devil_mind
D.objectives += objective
if(!istype(objective, /datum/objective/devil/buy_target))
validtypes -= type
else
objective.find_target()
//////////////////////////////////////////////
// //
// MONKEY //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/monkey
name = "Monkey"
config_tag = "monkey"
antag_flag = ROLE_MONKEY
antag_datum = /datum/antagonist/monkey/leader
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
weight = 3
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
property_weights = list("extended" = -2, "chaos" = 2, "conversion" = 1, "valid" = 2)
var/players_per_carrier = 30
var/monkeys_to_win = 1
var/escaped_monkeys = 0
var/datum/team/monkey/monkey_team
/datum/dynamic_ruleset/roundstart/monkey/pre_execute()
var/carriers_to_make = max(round(mode.roundstart_pop_ready / players_per_carrier, 1), 1)
mode.antags_rolled += carriers_to_make
for(var/j = 0, j < carriers_to_make, j++)
if (!candidates.len)
break
var/mob/carrier = pick_n_take(candidates)
assigned += carrier.mind
carrier.mind.special_role = "Monkey Leader"
carrier.mind.restricted_roles = restricted_roles
log_game("[key_name(carrier)] has been selected as a Jungle Fever carrier")
return TRUE
/datum/dynamic_ruleset/roundstart/monkey/execute()
for(var/datum/mind/carrier in assigned)
var/datum/antagonist/monkey/M = add_monkey_leader(carrier)
if(M)
monkey_team = M.monkey_team
return TRUE
/datum/dynamic_ruleset/roundstart/monkey/proc/check_monkey_victory()
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
return FALSE
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
if (M.HasDisease(D))
if(M.onCentCom() || M.onSyndieBase())
escaped_monkeys++
if(escaped_monkeys >= monkeys_to_win)
return TRUE
else
return FALSE
// This does not get called. Look into making it work.
/datum/dynamic_ruleset/roundstart/monkey/round_result()
if(check_monkey_victory())
SSticker.mode_result = "win - monkey win"
else
SSticker.mode_result = "loss - staff stopped the monkeys"
//////////////////////////////////////////////
// //
// METEOR //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/meteor
name = "Meteor"
config_tag = "meteor"
persistent = TRUE
required_candidates = 0
weight = 3
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
property_weights = list("extended" = -2, "chaos" = 2, "trust" = 2)
var/meteordelay = 2000
var/nometeors = 0
var/rampupdelta = 5
/datum/dynamic_ruleset/roundstart/meteor/rule_process()
if(nometeors || meteordelay > world.time - SSticker.round_start_time)
return
var/list/wavetype = GLOB.meteors_normal
var/meteorminutes = (world.time - SSticker.round_start_time - meteordelay) / 10 / 60
if (prob(meteorminutes))
wavetype = GLOB.meteors_threatening
if (prob(meteorminutes/2))
wavetype = GLOB.meteors_catastrophic
var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
spawn_meteors(ramp_up_final, wavetype)
//////////////////////////////////////////////
// //
// BLOODSUCKERS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/bloodsucker
name = "Bloodsuckers"
config_tag = "bloodsucker"
persistent = TRUE
antag_flag = ROLE_BLOODSUCKER
antag_datum = ANTAG_DATUM_BLOODSUCKER
minimum_required_age = 0
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
weight = 2
cost = 15
scaling_cost = 10
property_weights = list("story_potential" = 1, "extended" = 1, "trust" = -2, "valid" = 1)
requirements = list(70,65,60,55,50,50,50,50,50,50)
high_population_requirement = 50
antag_cap = list(1,1,1,1,1,2,2,2,2,2)
/datum/dynamic_ruleset/roundstart/bloodsucker/pre_execute()
var/num_bloodsuckers = antag_cap[indice_pop] * (scaled_times + 1)
for (var/i = 1 to num_bloodsuckers)
var/mob/M = pick_n_take(candidates)
assigned += M.mind
M.mind.special_role = ROLE_BLOODSUCKER
M.mind.restricted_roles = restricted_roles
return TRUE
/datum/dynamic_ruleset/roundstart/bloodsucker/execute()
mode.check_start_sunlight()
for(var/datum/mind/M in assigned)
if(mode.make_bloodsucker(M))
mode.bloodsuckers += M
return TRUE