////////////////////////////////////////////// // // // 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) log_admin("[M.name] was made into a [name] by dynamic.") message_admins("[M.name] was made into a [name] by dynamic.") 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 ////////////////////////////////////////////// // // // 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 ////////////////////////////////////////////// // // // COLLECTOR // // // ////////////////////////////////////////////// /datum/dynamic_ruleset/latejoin/collector name = "Contraband Collector" config_tag = "latejoin_collector" antag_datum = /datum/antagonist/collector antag_flag = ROLE_MINOR_ANTAG 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 = 5 cost = 1 requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE flags = TRAITOR_RULESET property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 2)