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.
228 lines
9.4 KiB
Plaintext
228 lines
9.4 KiB
Plaintext
//////////////////////////////////////////////
|
|
// //
|
|
// LATEJOIN RULESETS //
|
|
// //
|
|
//////////////////////////////////////////////
|
|
|
|
/datum/dynamic_ruleset/latejoin/trim_candidates()
|
|
for(var/mob/P in candidates)
|
|
if (!P.client || !P.mind || !P.mind.assigned_role) // Are they connected?
|
|
candidates.Remove(P)
|
|
continue
|
|
if(!mode.check_age(P.client, minimum_required_age))
|
|
candidates.Remove(P)
|
|
continue
|
|
if(antag_flag_override)
|
|
if(!(antag_flag_override in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag_override)))
|
|
candidates.Remove(P)
|
|
continue
|
|
else
|
|
if(!(antag_flag in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag, ROLE_SYNDICATE)))
|
|
candidates.Remove(P)
|
|
continue
|
|
if (P.mind.assigned_role in restricted_roles) // Does their job allow for it?
|
|
candidates.Remove(P)
|
|
continue
|
|
if ((exclusive_roles.len > 0) && !(P.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job?
|
|
candidates.Remove(P)
|
|
continue
|
|
|
|
/datum/dynamic_ruleset/latejoin/ready(forced = 0)
|
|
if (!forced)
|
|
var/job_check = 0
|
|
if (enemy_roles.len > 0)
|
|
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
|
if (M.stat == DEAD)
|
|
continue // Dead players cannot count as opponents
|
|
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles) && (!(M in candidates) || (M.mind.assigned_role in restricted_roles)))
|
|
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it
|
|
var/threat = round(mode.threat_level/10)
|
|
if (job_check < required_enemies[threat])
|
|
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough enemy roles")
|
|
return FALSE
|
|
return ..()
|
|
|
|
/datum/dynamic_ruleset/latejoin/execute()
|
|
var/mob/M = pick(candidates)
|
|
assigned += M.mind
|
|
M.mind.special_role = antag_flag
|
|
M.mind.add_antag_datum(antag_datum)
|
|
return TRUE
|
|
|
|
//////////////////////////////////////////////
|
|
// //
|
|
// SYNDICATE TRAITORS //
|
|
// //
|
|
//////////////////////////////////////////////
|
|
|
|
/datum/dynamic_ruleset/latejoin/infiltrator
|
|
name = "Syndicate Infiltrator"
|
|
config_tag = "latejoin_traitor"
|
|
antag_datum = /datum/antagonist/traitor
|
|
antag_flag = ROLE_TRAITOR
|
|
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 = 7
|
|
cost = 5
|
|
requirements = list(40,30,20,15,15,15,15,15,15,15)
|
|
high_population_requirement = 15
|
|
repeatable = TRUE
|
|
flags = TRAITOR_RULESET
|
|
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1)
|
|
always_max_weight = TRUE
|
|
|
|
/datum/dynamic_ruleset/latejoin/infiltrator/execute()
|
|
. = ..()
|
|
for(var/datum/mind/M in assigned)
|
|
log_admin("[M.name] was made into a traitor by dynamic.")
|
|
message_admins("[M.name] was made into a traitor by dynamic.")
|
|
|
|
//////////////////////////////////////////////
|
|
// //
|
|
// REVOLUTIONARY PROVOCATEUR //
|
|
// //
|
|
//////////////////////////////////////////////
|
|
|
|
/datum/dynamic_ruleset/latejoin/provocateur
|
|
name = "Provocateur"
|
|
persistent = TRUE
|
|
config_tag = "latejoin_revolution"
|
|
antag_datum = /datum/antagonist/rev/head
|
|
antag_flag = ROLE_REV_HEAD
|
|
antag_flag_override = ROLE_REV
|
|
restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
|
enemy_roles = list("AI", "Cyborg", "Security Officer","Detective","Head of Security", "Captain", "Warden")
|
|
required_enemies = list(4,4,3,3,3,3,3,2,2,1)
|
|
required_candidates = 1
|
|
weight = 2
|
|
delay = 1 MINUTES // Prevents rule start while head is offstation.
|
|
cost = 20
|
|
requirements = list(101,101,70,40,40,40,40,40,40,40)
|
|
high_population_requirement = 40
|
|
flags = HIGHLANDER_RULESET
|
|
property_weights = list("trust" = -2, "chaos" = 2, "extended" = -2, "valid" = 2, "conversion" = 1)
|
|
var/required_heads_of_staff = 3
|
|
var/finished = FALSE
|
|
var/datum/team/revolution/revolution
|
|
|
|
/datum/dynamic_ruleset/latejoin/provocateur/ready(forced=FALSE)
|
|
if (forced)
|
|
required_heads_of_staff = 1
|
|
if(!..())
|
|
return FALSE
|
|
var/head_check = 0
|
|
for(var/mob/player in mode.current_players[CURRENT_LIVING_PLAYERS])
|
|
if (player.mind.assigned_role in GLOB.command_positions)
|
|
head_check++
|
|
return (head_check >= required_heads_of_staff)
|
|
|
|
/datum/dynamic_ruleset/latejoin/provocateur/execute()
|
|
var/mob/M = pick(candidates) // This should contain a single player, but in case.
|
|
if(check_eligible(M.mind)) // Didnt die/run off z-level/get implanted since leaving shuttle.
|
|
assigned += M.mind
|
|
M.mind.special_role = antag_flag
|
|
revolution = new()
|
|
var/datum/antagonist/rev/head/new_head = new()
|
|
new_head.give_flash = TRUE
|
|
new_head.give_hud = TRUE
|
|
new_head.remove_clumsy = TRUE
|
|
new_head = M.mind.add_antag_datum(new_head, revolution)
|
|
revolution.update_objectives()
|
|
revolution.update_heads()
|
|
SSshuttle.registerHostileEnvironment(src)
|
|
log_admin("[M.name] was made into a revolutionary by dynamic.")
|
|
message_admins("[M.name] was made into a revolutionary by dynamic.")
|
|
return TRUE
|
|
else
|
|
log_game("DYNAMIC: [ruletype] [name] discarded [M.name] from head revolutionary due to ineligibility.")
|
|
log_game("DYNAMIC: [ruletype] [name] failed to get any eligible headrevs. Refunding [cost] threat.")
|
|
return FALSE
|
|
|
|
/datum/dynamic_ruleset/latejoin/provocateur/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 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 prevent headrev cloning then 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/latejoin/provocateur/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/latejoin/provocateur/check_finished()
|
|
if(finished == REVOLUTION_VICTORY)
|
|
return TRUE
|
|
else
|
|
return ..()
|
|
|
|
/datum/dynamic_ruleset/latejoin/provocateur/proc/check_rev_victory()
|
|
for(var/datum/objective/mutiny/objective in revolution.objectives)
|
|
if(!(objective.check_completion()))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/dynamic_ruleset/latejoin/provocateur/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/latejoin/provocateur/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
|
|
|
|
//////////////////////////////////////////////
|
|
// //
|
|
// BLOODSUCKERS //
|
|
// //
|
|
//////////////////////////////////////////////
|
|
|
|
/datum/dynamic_ruleset/latejoin/bloodsucker
|
|
name = "Bloodsucker Infiltrator"
|
|
config_tag = "latejoin_bloodsucker"
|
|
antag_datum = ANTAG_DATUM_BLOODSUCKER
|
|
antag_flag = ROLE_TRAITOR
|
|
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 = 10
|
|
property_weights = list("story_potential" = 2, "extended" = 2, "trust" = -2, "valid" = 1)
|
|
requirements = list(70,65,60,55,50,45,40,35,30,30)
|
|
high_population_requirement = 30
|
|
repeatable = TRUE
|
|
|
|
/datum/dynamic_ruleset/latejoin/bloodsucker/execute()
|
|
var/mob/M = pick(candidates)
|
|
assigned += M.mind
|
|
M.mind.special_role = antag_flag
|
|
if(mode.make_bloodsucker(M.mind))
|
|
mode.bloodsuckers += M
|
|
log_admin("[M.name] was made into a bloodsucker by dynamic.")
|
|
message_admins("[M.name] was made into a bloodsucker by dynamic.")
|
|
return TRUE
|