Merge remote-tracking branch 'Citadel-Station-13/master' into Garlic
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
antag_flag = ROLE_BLOODSUCKER
|
||||
false_report_weight = 1
|
||||
restricted_jobs = list("AI","Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
protected_jobs = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
required_players = 20
|
||||
required_enemies = 2
|
||||
recommended_enemies = 4
|
||||
|
||||
@@ -88,13 +88,13 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
|
||||
user.underwear = chosen_prof.underwear
|
||||
user.undie_color = chosen_prof.undie_color
|
||||
user.undershirt = chosen_prof.undershirt
|
||||
user.shirt_color =chosen_prof.shirt_color
|
||||
user.shirt_color = chosen_prof.shirt_color
|
||||
user.socks = chosen_prof.socks
|
||||
user.socks_color =chosen_prof.socks_color
|
||||
|
||||
chosen_dna.transfer_identity(user, 1)
|
||||
user.updateappearance(mutcolor_update=1)
|
||||
user.update_body()
|
||||
user.update_body(TRUE)
|
||||
user.domutcheck()
|
||||
|
||||
//vars hackery. not pretty, but better than the alternative.
|
||||
|
||||
@@ -351,5 +351,5 @@ Credit where due:
|
||||
|
||||
/obj/item/paper/servant_primer/oui_getcontent(mob/target)
|
||||
if(!is_servant_of_ratvar(target) && !isobserver(target))
|
||||
return "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
|
||||
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
|
||||
return ..()
|
||||
|
||||
@@ -54,16 +54,16 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
// Current storyteller
|
||||
var/datum/dynamic_storyteller/storyteller = null
|
||||
// Threat logging vars
|
||||
/// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations
|
||||
/// Target threat level right now. Events and antags will try to keep the round at this level.
|
||||
var/threat_level = 0
|
||||
/// Set at the beginning of the round. Spent by the mode to "purchase" rules.
|
||||
var/threat = 0
|
||||
/// The current antag threat. Recalculated every time a ruletype starts or ends.
|
||||
var/threat = 0
|
||||
/// Starting threat level, for things that increase it but can bring it back down.
|
||||
var/initial_threat_level = 0
|
||||
/// Things that cause a rolling threat adjustment to be displayed at roundend.
|
||||
var/list/threat_tallies = list()
|
||||
/// Running information about the threat. Can store text or datum entries.
|
||||
var/list/threat_log = list()
|
||||
var/list/threat_log = list()
|
||||
/// As above, but with info such as refunds.
|
||||
var/list/threat_log_verbose = list()
|
||||
/// List of roundstart rules used for selecting the rules.
|
||||
@@ -127,6 +127,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
var/only_ruleset_executed = FALSE
|
||||
/// Antags rolled by rules so far, to keep track of and discourage scaling past a certain ratio of crew/antags especially on lowpop.
|
||||
var/antags_rolled = 0
|
||||
// Arbitrary threat addition, for fudging purposes.
|
||||
var/added_threat = 50
|
||||
|
||||
/datum/game_mode/dynamic/New() // i have NO IDEA if this is the proper way to do this.
|
||||
..()
|
||||
@@ -150,11 +152,11 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
GLOB.dynamic_first_midround_delay_max = CONFIG_GET(number/dynamic_first_midround_delay_max)*600
|
||||
|
||||
/datum/game_mode/dynamic/admin_panel()
|
||||
var/list/dat = list("<html><head><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
|
||||
var/list/dat = list("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
|
||||
dat += "Dynamic Mode <a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>\[VV\]</A><a href='?src=\ref[src];[HrefToken()]'>\[Refresh\]</A><BR>"
|
||||
dat += "Threat Level: <b>[threat_level]</b><br/>"
|
||||
dat += "Target threat: <b>[threat_level]</b><br/>"
|
||||
|
||||
dat += "Threat to Spend: <b>[threat]</b> <a href='?src=\ref[src];[HrefToken()];adjustthreat=1'>\[Adjust\]</A> <a href='?src=\ref[src];[HrefToken()];threatlog=1'>\[View Log\]</a><br/>"
|
||||
dat += "Current threat: <b>[threat]</b> <a href='?src=\ref[src];[HrefToken()];adjustthreat=1'>\[Adjust\]</A> <a href='?src=\ref[src];[HrefToken()];threatlog=1'>\[View Log\]</a><br/>"
|
||||
dat += "<br/>"
|
||||
dat += "Storyteller: <b>[storyteller.name]</b><br/>"
|
||||
dat += "Parameters: centre = [GLOB.dynamic_curve_centre] ; width = [GLOB.dynamic_curve_width].<br/>"
|
||||
@@ -172,9 +174,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
else
|
||||
dat += "none.<br>"
|
||||
dat += "<br>Injection Timers: (<b>[storyteller.get_injection_chance(TRUE)]%</b> chance)<BR>"
|
||||
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
|
||||
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
|
||||
dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];forceevent=1'>\[Now!\]</a><BR>"
|
||||
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
|
||||
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
|
||||
dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];forceevent=1'>\[Now!\]</a><BR>"
|
||||
usr << browse(dat.Join(), "window=gamemode_panel;size=500x500")
|
||||
|
||||
/datum/game_mode/dynamic/Topic(href, href_list)
|
||||
@@ -261,11 +263,11 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
. += "<b>Uncharted Space</b></center><BR>"
|
||||
. += "Congratulations and thank you for participating in the NT 'Frontier' space program! Your station is actively orbiting a high value system far from the nearest support stations. Little is known about your region of space, and the opportunity to encounter the unknown invites greater glory. You are encouraged to elevate security as necessary to protect Nanotrasen assets."
|
||||
set_security_level(SEC_LEVEL_BLUE)
|
||||
if(80 to 99)
|
||||
if(80 to 95)
|
||||
. += "<b>Black Orbit</b></center><BR>"
|
||||
. += "As part of a mandatory security protocol, we are required to inform you that as a result of your orbital pattern directly behind an astrological body (oriented from our nearest observatory), your station will be under decreased monitoring and support. It is anticipated that your extreme location and decreased surveillance could pose security risks. Avoid unnecessary risks and attempt to keep your station in one piece."
|
||||
set_security_level(SEC_LEVEL_AMBER)
|
||||
if(100)
|
||||
if(96 to 100)
|
||||
. += "<b>Impending Doom</b></center><BR>"
|
||||
. += "Your station is somehow in the middle of hostile territory, in clear view of any enemy of the corporation. Your likelihood to survive is low, and station destruction is expected and almost inevitable. Secure any sensitive material and neutralize any enemy you will come across. It is important that you at least try to maintain the station.<BR>"
|
||||
. += "Good luck."
|
||||
@@ -330,7 +332,6 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
|
||||
peaceful_percentage = round(LORENTZ_CUMULATIVE_DISTRIBUTION(relative_threat, GLOB.dynamic_curve_centre, GLOB.dynamic_curve_width), 0.01)*100
|
||||
|
||||
threat = threat_level
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",threat_level,"Initial threat level")
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",GLOB.dynamic_curve_centre,"Curve centre")
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",GLOB.dynamic_curve_width,"Curve width")
|
||||
@@ -340,9 +341,10 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
storyteller = new GLOB.dynamic_storyteller_type // this is where all the initialization happens
|
||||
storyteller.on_start()
|
||||
SSblackbox.record_feedback("text","dynamic_storyteller",1,storyteller.name)
|
||||
message_admins("Dynamic mode parameters for the round:")
|
||||
message_admins("Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
|
||||
message_admins("Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
|
||||
message_admins("Dynamic mode parameters for the round:\n\
|
||||
Storyteller is [storyteller.name].\n\
|
||||
Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].\n\
|
||||
Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
|
||||
log_game("DYNAMIC: Dynamic mode parameters for the round:")
|
||||
log_game("DYNAMIC: Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
|
||||
log_game("DYNAMIC: Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
|
||||
@@ -404,7 +406,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
|
||||
/datum/game_mode/dynamic/post_setup(report)
|
||||
update_playercounts()
|
||||
|
||||
|
||||
for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
|
||||
..()
|
||||
@@ -463,7 +465,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
log_game("DYNAMIC: Additional ruleset picked successfully, now [executed_rules.len] picked. [extra_rulesets_amount] remaining.")
|
||||
else
|
||||
|
||||
if(threat >= 50)
|
||||
if(threat_level >= 50)
|
||||
message_admins("DYNAMIC: Picking first roundstart ruleset failed. You should report this.")
|
||||
log_game("DYNAMIC: Picking first roundstart ruleset failed. drafted_rules.len = [drafted_rules.len] and threat = [threat]/[threat_level]")
|
||||
return FALSE
|
||||
@@ -509,10 +511,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
drafted_rules -= starting_rule
|
||||
|
||||
starting_rule.trim_candidates()
|
||||
var/added_threat = starting_rule.scale_up(extra_rulesets_amount, threat)
|
||||
starting_rule.scale_up(extra_rulesets_amount, threat)
|
||||
if (starting_rule.pre_execute())
|
||||
spend_threat(starting_rule.cost + added_threat)
|
||||
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
|
||||
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> [starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
|
||||
if(starting_rule.flags & HIGHLANDER_RULESET)
|
||||
highlander_executed = TRUE
|
||||
else if(starting_rule.flags & ONLY_RULESET)
|
||||
@@ -534,8 +535,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
/datum/game_mode/dynamic/proc/execute_roundstart_rule(sent_rule)
|
||||
var/datum/dynamic_ruleset/rule = sent_rule
|
||||
if(rule.execute())
|
||||
if(rule.persistent)
|
||||
current_rules += rule
|
||||
current_rules += rule
|
||||
SSblackbox.record_feedback("associative","dynamic_rulesets",1,rule.get_blackbox_info())
|
||||
return TRUE
|
||||
rule.clean_up() // Refund threat, delete teams and so on.
|
||||
@@ -607,8 +607,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
if ((forced || (new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat)))
|
||||
new_rule.trim_candidates()
|
||||
if (new_rule.ready(forced))
|
||||
spend_threat(new_rule.cost)
|
||||
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> -[new_rule.cost] threat", verbose = TRUE)
|
||||
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> [new_rule.cost] threat", verbose = TRUE)
|
||||
if (new_rule.execute()) // This should never fail since ready() returned 1
|
||||
if(new_rule.flags & HIGHLANDER_RULESET)
|
||||
highlander_executed = TRUE
|
||||
@@ -617,8 +616,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
log_game("DYNAMIC: Making a call to a specific ruleset...[new_rule.name]!")
|
||||
SSblackbox.record_feedback("associative","dynamic_rulesets",1,new_rule.get_blackbox_info())
|
||||
executed_rules += new_rule
|
||||
if (new_rule.persistent)
|
||||
current_rules += new_rule
|
||||
current_rules += new_rule
|
||||
return TRUE
|
||||
else if (forced)
|
||||
log_game("DYNAMIC: The ruleset [new_rule.name] couldn't be executed due to lack of eligible players.")
|
||||
@@ -629,8 +627,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
var/datum/dynamic_ruleset/rule = sent_rule
|
||||
if (rule.execute())
|
||||
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
|
||||
spend_threat(rule.cost)
|
||||
log_threat("[rule.ruletype] [rule.name] spent [rule.cost]", verbose = TRUE)
|
||||
log_threat("[rule.ruletype] [rule.name] added [rule.cost]", verbose = TRUE)
|
||||
if(rule.flags & HIGHLANDER_RULESET)
|
||||
highlander_executed = TRUE
|
||||
else if(rule.flags & ONLY_RULESET)
|
||||
@@ -649,7 +646,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
return FALSE
|
||||
|
||||
/datum/game_mode/dynamic/process()
|
||||
if (pop_last_updated < world.time - (60 SECONDS))
|
||||
if (pop_last_updated < world.time - (120 SECONDS))
|
||||
pop_last_updated = world.time
|
||||
update_playercounts()
|
||||
|
||||
@@ -658,9 +655,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
current_rules -= rule
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Rulesets finished")
|
||||
SSblackbox.record_feedback("associative","dynamic_rulesets_finished",1,rule.get_blackbox_info())
|
||||
|
||||
|
||||
storyteller.do_process()
|
||||
|
||||
|
||||
if (midround_injection_cooldown < world.time)
|
||||
if (GLOB.dynamic_forced_extended)
|
||||
return
|
||||
@@ -717,7 +714,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
current_players[CURRENT_OBSERVERS].Add(M)
|
||||
continue
|
||||
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
|
||||
|
||||
threat = storyteller.calculate_threat() + added_threat
|
||||
/// Removes type from the list
|
||||
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
|
||||
for(var/I in type_list)
|
||||
@@ -767,25 +764,23 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Successful latejoin injections")
|
||||
latejoin_injection_cooldown = storyteller.get_latejoin_cooldown() + world.time
|
||||
|
||||
/// Refund threat, but no more than threat_level.
|
||||
/datum/game_mode/dynamic/proc/refund_threat(regain)
|
||||
threat = min(threat_level,threat+regain)
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",regain,"Refunded threat")
|
||||
log_threat("[regain] refunded. Threat is now [threat].", verbose = TRUE)
|
||||
|
||||
/// Generate threat and increase the threat_level if it goes beyond, capped at 100
|
||||
/// Increase the threat level.
|
||||
/datum/game_mode/dynamic/proc/create_threat(gain)
|
||||
threat = min(100, threat+gain)
|
||||
if(threat > threat_level)
|
||||
threat_level = threat
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",gain,"Created threat")
|
||||
log_threat("[gain] created. Threat is now [threat] and threat level is now [threat_level].", verbose = TRUE)
|
||||
threat_level += gain
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",gain,"Created threat level")
|
||||
log_threat("[gain] created. Threat level is now [threat_level].", verbose = TRUE)
|
||||
|
||||
/// Expend threat, can't fall under 0.
|
||||
/// Decrease the threat level.
|
||||
/datum/game_mode/dynamic/proc/remove_threat(loss)
|
||||
threat_level -= loss
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",loss,"Removed threat level")
|
||||
log_threat("[loss] removed. Threat level is now [threat_level].", verbose = TRUE)
|
||||
|
||||
/// Fill up more of the threat level.
|
||||
/datum/game_mode/dynamic/proc/spend_threat(cost)
|
||||
threat = max(threat-cost,0)
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",cost,"Threat spent")
|
||||
log_threat("[cost] spent. Threat is now [threat].", verbose = TRUE)
|
||||
added_threat += cost
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",cost,"Threat added")
|
||||
log_threat("[cost] added. Threat is now [threat].", verbose = TRUE)
|
||||
|
||||
/// Turns the value generated by lorentz distribution to threat value between 0 and 100.
|
||||
/datum/game_mode/dynamic/proc/lorentz_to_threat(x)
|
||||
|
||||
@@ -174,8 +174,8 @@
|
||||
|
||||
/// This is called if persistent variable is true everytime SSTicker ticks.
|
||||
/datum/dynamic_ruleset/proc/rule_process()
|
||||
return
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Called on game mode pre_setup for roundstart rulesets.
|
||||
/// Do everything you need to do before job is assigned here.
|
||||
/// IMPORTANT: ASSIGN special_role HERE
|
||||
@@ -201,8 +201,7 @@
|
||||
/// Runs from gamemode process() if ruleset fails to start, like delayed rulesets not getting valid candidates.
|
||||
/// This one only handles refunding the threat, override in ruleset to clean up the rest.
|
||||
/datum/dynamic_ruleset/proc/clean_up()
|
||||
mode.refund_threat(cost + (scaled_times * scaling_cost))
|
||||
mode.log_threat("[ruletype] [name] refunded [cost + (scaled_times * scaling_cost)]",verbose=TRUE)
|
||||
return
|
||||
|
||||
/// Gets weight of the ruleset
|
||||
/// Note that this decreases weight if repeatable is TRUE and repeatable_weight_decrease is higher than 0
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
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)
|
||||
var/threat = CLAMP(round(mode.threat_level/10),1,10)
|
||||
if (job_check < required_enemies[threat])
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough enemy roles")
|
||||
return FALSE
|
||||
@@ -216,7 +216,7 @@
|
||||
var/player_count = mode.current_players[CURRENT_LIVING_PLAYERS].len
|
||||
var/antag_count = mode.current_players[CURRENT_LIVING_ANTAGS].len
|
||||
var/max_traitors = round(player_count / 10) + 1
|
||||
if ((antag_count < max_traitors) && prob(mode.threat_level))//adding traitors if the antag population is getting low
|
||||
if ((antag_count < max_traitors) && prob(min(100,mode.threat_level)))//adding traitors if the antag population is getting low
|
||||
return ..()
|
||||
else
|
||||
return FALSE
|
||||
@@ -315,7 +315,6 @@
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/wizard
|
||||
name = "Wizard"
|
||||
config_tag = "midround_wizard"
|
||||
persistent = TRUE
|
||||
antag_datum = /datum/antagonist/wizard
|
||||
antag_flag = ROLE_WIZARD
|
||||
enemy_roles = list("Security Officer","Detective","Head of Security", "Captain")
|
||||
@@ -344,7 +343,6 @@
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great
|
||||
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
|
||||
@@ -417,7 +415,7 @@
|
||||
required_candidates = 1
|
||||
blocking_rules = list(/datum/dynamic_ruleset/roundstart/clockcult)
|
||||
weight = 4
|
||||
cost = 10
|
||||
cost = 20
|
||||
requirements = list(101,101,101,80,60,50,50,50,50,50)
|
||||
high_population_requirement = 50
|
||||
repeatable = TRUE
|
||||
@@ -666,9 +664,6 @@
|
||||
Mind.transfer_to(Ninja)
|
||||
var/datum/antagonist/ninja/ninjadatum = new
|
||||
ninjadatum.helping_station = pick(TRUE,FALSE)
|
||||
if(ninjadatum.helping_station)
|
||||
mode.refund_threat(cost+5)
|
||||
mode.log_threat("Ninja was helping station; [cost+5] cost refunded.")
|
||||
Mind.add_antag_datum(ninjadatum)
|
||||
|
||||
if(Ninja.mind != Mind) //something has gone wrong!
|
||||
|
||||
@@ -802,11 +802,10 @@
|
||||
/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")
|
||||
protected_roles = list("Chaplain", "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
|
||||
|
||||
@@ -5,17 +5,19 @@
|
||||
var/list/property_weights = list() // See below.
|
||||
var/curve_centre = 0 // As GLOB.dynamic_curve_centre.
|
||||
var/curve_width = 1.8 // As GLOB.dynamic_curve_width.
|
||||
var/forced_threat_level = -1
|
||||
var/forced_threat_level = -1 // As GLOB.dynamic_forced_threat_level
|
||||
/*
|
||||
NO_ASSASSIN: Will not have permanent assassination targets.
|
||||
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
|
||||
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
|
||||
FORCE_IF_WON: If this mode won the vote, forces it
|
||||
*/
|
||||
var/flags = 0
|
||||
var/dead_player_weight = 1 // How much dead players matter for threat calculation
|
||||
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
|
||||
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
|
||||
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
|
||||
var/pop_antag_ratio = 5 // How many non-antags there should be vs antags.
|
||||
var/min_players = -1 // How many players are required for this one to start.
|
||||
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
|
||||
|
||||
/**
|
||||
@@ -39,6 +41,29 @@ Property weights are:
|
||||
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
|
||||
mode.event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
|
||||
|
||||
/datum/dynamic_storyteller/proc/calculate_threat()
|
||||
var/threat = 0
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(A?.owner?.current && A.owner.current.stat != DEAD)
|
||||
threat += A.threat()
|
||||
for(var/r in SSevents.running)
|
||||
var/datum/round_event/R = r
|
||||
threat += R.threat()
|
||||
for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
|
||||
var/turf/T = get_turf(H)
|
||||
if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
|
||||
threat += H.threat()
|
||||
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
if (M?.mind?.assigned_role && M.stat != DEAD)
|
||||
var/datum/job/J = SSjob.GetJob(M.mind.assigned_role)
|
||||
if(J)
|
||||
if(length(M.mind.antag_datums))
|
||||
threat += J.GetThreat()
|
||||
else
|
||||
threat -= J.GetThreat()
|
||||
threat += (mode.current_players[CURRENT_DEAD_PLAYERS].len)*dead_player_weight
|
||||
return round(threat,0.1)
|
||||
|
||||
/datum/dynamic_storyteller/proc/do_process()
|
||||
return
|
||||
|
||||
@@ -83,30 +108,14 @@ Property weights are:
|
||||
if(mode.forced_injection)
|
||||
mode.forced_injection = !dry_run
|
||||
return 100
|
||||
var/chance = 0
|
||||
// If the high pop override is in effect, we reduce the impact of population on the antag injection chance
|
||||
var/high_pop_factor = (mode.current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
|
||||
var/max_pop_per_antag = max(pop_antag_ratio,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
|
||||
if (!mode.current_players[CURRENT_LIVING_ANTAGS].len)
|
||||
chance += 80 // No antags at all? let's boost those odds!
|
||||
else
|
||||
var/current_pop_per_antag = mode.current_players[CURRENT_LIVING_PLAYERS].len / mode.current_players[CURRENT_LIVING_ANTAGS].len
|
||||
if (current_pop_per_antag > max_pop_per_antag)
|
||||
chance += min(50, 25+10*(current_pop_per_antag-max_pop_per_antag))
|
||||
else
|
||||
chance += 25-10*(max_pop_per_antag-current_pop_per_antag)
|
||||
if (mode.current_players[CURRENT_DEAD_PLAYERS].len > mode.current_players[CURRENT_LIVING_PLAYERS].len)
|
||||
chance -= 30 // More than half the crew died? ew, let's calm down on antags
|
||||
if (mode.threat > 70)
|
||||
chance += 15
|
||||
if (mode.threat < 30)
|
||||
chance -= 15
|
||||
return round(max(0,chance))
|
||||
var/threat_perc = mode.threat/mode.threat_level
|
||||
|
||||
return round(max(0,100*(1-(threat_perc*threat_perc*threat_perc))))
|
||||
|
||||
/datum/dynamic_storyteller/proc/roundstart_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
|
||||
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level) && mode.threat >= rule.cost) // If we got the population and threat required
|
||||
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level)) // If we got the population and threat required
|
||||
rule.candidates = mode.candidates.Copy()
|
||||
rule.trim_candidates()
|
||||
if (rule.ready() && rule.candidates.len > 0)
|
||||
@@ -114,32 +123,41 @@ Property weights are:
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
|
||||
drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/midround_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
|
||||
// if there are antags OR the rule is an antag rule, antag_acceptable will be true.
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
// Classic secret : only autotraitor/minor roles
|
||||
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
|
||||
continue
|
||||
rule.trim_candidates()
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
|
||||
pick this particular ruleset.
|
||||
Let's use a toy example: there's 60 threat level and 10 threat spent.
|
||||
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
|
||||
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
|
||||
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
|
||||
is 2.26 times as likely to be picked, all other things considered.
|
||||
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
|
||||
*/
|
||||
var/threat_weight = 1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
|
||||
else if(mode.threat < rule.cost)
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
|
||||
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level - mode.threat))
|
||||
// Classic secret : only autotraitor/minor roles
|
||||
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
|
||||
continue
|
||||
@@ -150,56 +168,54 @@ Property weights are:
|
||||
|
||||
rule.candidates = list(newPlayer)
|
||||
rule.trim_candidates()
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
var/threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
|
||||
else if(mode.threat < rule.cost)
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
|
||||
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/event_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for(var/datum/dynamic_ruleset/event/rule in mode.events)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
|
||||
if(rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
|
||||
else if(mode.threat < rule.cost)
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
|
||||
return drafted_rules
|
||||
|
||||
|
||||
/datum/dynamic_storyteller/cowabunga
|
||||
/datum/dynamic_storyteller/chaotic
|
||||
name = "Chaotic"
|
||||
config_tag = "chaotic"
|
||||
curve_centre = 10
|
||||
desc = "High chaos modes. Revs, wizard, clock cult. Multiple antags at once. Chaos is kept up all round."
|
||||
property_weights = list("extended" = -1, "chaos" = 10)
|
||||
property_weights = list("extended" = -1, "chaos" = 1)
|
||||
weight = 1
|
||||
event_frequency_lower = 2 MINUTES
|
||||
event_frequency_upper = 10 MINUTES
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
pop_antag_ratio = 4
|
||||
flags = WAROPS_ALWAYS_ALLOWED | FORCE_IF_WON
|
||||
min_players = 40
|
||||
var/refund_cooldown = 0
|
||||
|
||||
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
|
||||
/datum/dynamic_storyteller/chaotic/do_process()
|
||||
if(refund_cooldown < world.time)
|
||||
mode.create_threat(20)
|
||||
mode.log_threat("Chaotic storyteller ramped up the chaos. Threat level is now [mode.threat_level].")
|
||||
refund_cooldown = world.time + 20 MINUTES
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/get_midround_cooldown()
|
||||
return ..() / 4
|
||||
|
||||
/datum/dynamic_storyteller/cowabunga/get_latejoin_cooldown()
|
||||
/datum/dynamic_storyteller/chaotic/get_latejoin_cooldown()
|
||||
return ..() / 4
|
||||
|
||||
/datum/dynamic_storyteller/cowabunga/do_process()
|
||||
if(refund_cooldown < world.time)
|
||||
mode.refund_threat(40)
|
||||
mode.log_threat("Chaotic storyteller refunded 40 threat. Threat is now [mode.threat].")
|
||||
refund_cooldown = world.time + 1200 SECONDS
|
||||
|
||||
/datum/dynamic_storyteller/team
|
||||
name = "Teamwork"
|
||||
config_tag = "teamwork"
|
||||
@@ -207,6 +223,7 @@ Property weights are:
|
||||
curve_centre = 2
|
||||
curve_width = 1.5
|
||||
weight = 2
|
||||
min_players = 30
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
property_weights = list("valid" = 3, "trust" = 5)
|
||||
|
||||
@@ -223,23 +240,93 @@ Property weights are:
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
property_weights = list("valid" = 1, "conversion" = 20)
|
||||
|
||||
/datum/dynamic_storyteller/classic
|
||||
/datum/dynamic_storyteller/random
|
||||
name = "Random"
|
||||
config_tag = "random"
|
||||
desc = "No special weights attached. Anything goes."
|
||||
weight = 4
|
||||
curve_width = 4
|
||||
pop_antag_ratio = 7
|
||||
flags = USE_PREF_WEIGHTS
|
||||
weight = 1
|
||||
desc = "No weighting at all; every ruleset has the same chance of happening. Cooldowns vary wildly. As random as it gets."
|
||||
forced_threat_level = 100
|
||||
|
||||
/datum/dynamic_storyteller/random/get_midround_cooldown()
|
||||
return rand(GLOB.dynamic_midround_delay_min/2, GLOB.dynamic_midround_delay_max*2)
|
||||
|
||||
/datum/dynamic_storyteller/random/get_event_cooldown()
|
||||
return rand(GLOB.dynamic_event_delay_min/2, GLOB.dynamic_event_delay_max*2)
|
||||
|
||||
/datum/dynamic_storyteller/random/get_latejoin_cooldown()
|
||||
return rand(GLOB.dynamic_latejoin_delay_min/2, GLOB.dynamic_latejoin_delay_max*2)
|
||||
|
||||
/datum/dynamic_storyteller/random/get_injection_chance()
|
||||
return 50 // i would do rand(0,100) but it's actually the same thing when you do the math
|
||||
|
||||
/datum/dynamic_storyteller/random/calculate_threat()
|
||||
return 0 // what IS threat
|
||||
|
||||
/datum/dynamic_storyteller/random/roundstart_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
|
||||
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level)) // If we got the population and threat required
|
||||
rule.candidates = mode.candidates.Copy()
|
||||
rule.trim_candidates()
|
||||
if (rule.ready() && rule.candidates.len > 0)
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/random/midround_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
// Classic secret : only autotraitor/minor roles
|
||||
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
|
||||
continue
|
||||
rule.trim_candidates()
|
||||
if (rule.ready())
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/random/latejoin_draft(mob/living/carbon/human/newPlayer)
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
// Classic secret : only autotraitor/minor roles
|
||||
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
|
||||
continue
|
||||
// No stacking : only one round-ender, unless threat level > stacking_limit.
|
||||
if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
|
||||
if(rule.flags & HIGHLANDER_RULESET && mode.highlander_executed)
|
||||
continue
|
||||
rule.candidates = list(newPlayer)
|
||||
rule.trim_candidates()
|
||||
if (rule.ready())
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/random/event_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for(var/datum/dynamic_ruleset/event/rule in mode.events)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
if(rule.ready())
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/story
|
||||
name = "Story"
|
||||
config_tag = "story"
|
||||
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
|
||||
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies. Has a buildup-climax-falling action threat curve."
|
||||
weight = 2
|
||||
curve_width = 2
|
||||
pop_antag_ratio = 7
|
||||
property_weights = list("story_potential" = 10)
|
||||
property_weights = list("story_potential" = 2)
|
||||
|
||||
|
||||
/datum/dynamic_storyteller/story/do_process()
|
||||
var/current_time = (world.time / SSautotransfer.targettime)*180
|
||||
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.5),0.1)
|
||||
|
||||
/datum/dynamic_storyteller/classic
|
||||
name = "Classic"
|
||||
config_tag = "classic"
|
||||
desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight."
|
||||
flags = USE_PREF_WEIGHTS
|
||||
|
||||
/datum/dynamic_storyteller/suspicion
|
||||
name = "Intrigue"
|
||||
@@ -247,8 +334,8 @@ Property weights are:
|
||||
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
|
||||
weight = 2
|
||||
curve_width = 2
|
||||
pop_antag_ratio = 7
|
||||
property_weights = list("trust" = -5)
|
||||
dead_player_weight = 2
|
||||
property_weights = list("trust" = -3)
|
||||
|
||||
/datum/dynamic_storyteller/liteextended
|
||||
name = "Calm"
|
||||
@@ -256,10 +343,10 @@ Property weights are:
|
||||
desc = "Low-chaos round. Few antags. No conversion."
|
||||
curve_centre = -3
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN
|
||||
flags = NO_ASSASSIN | FORCE_IF_WON
|
||||
weight = 1
|
||||
pop_antag_ratio = 10
|
||||
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
|
||||
dead_player_weight = 5
|
||||
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
|
||||
|
||||
/datum/dynamic_storyteller/no_antag
|
||||
name = "Extended"
|
||||
@@ -267,7 +354,7 @@ Property weights are:
|
||||
desc = "No standard antags. Threatening events may still spawn."
|
||||
curve_centre = -5
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN
|
||||
flags = NO_ASSASSIN | FORCE_IF_WON
|
||||
weight = 1
|
||||
property_weights = list("extended" = 2)
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
var/free_tickets = CONFIG_GET(number/default_antag_tickets)
|
||||
//Max extra tickets you can use
|
||||
var/additional_tickets = CONFIG_GET(number/max_tickets_per_roll)
|
||||
|
||||
|
||||
var/list/ckey_to_mind = list() //this is admittedly shitcode but I'm webediting
|
||||
var/list/prev_tickets = SSpersistence.antag_rep //cache for hyper-speed in theory. how many tickets someone has stored
|
||||
var/list/curr_tickets = list() //how many tickets someone has for *this* antag roll, so with the free tickets
|
||||
@@ -337,7 +337,7 @@
|
||||
continue
|
||||
curr_tickets[mind_ckey] = amount
|
||||
ckey_to_mind[mind_ckey] = M //make sure we can look them up after picking
|
||||
|
||||
|
||||
if(!return_list) //return a single guy
|
||||
var/ckey
|
||||
if(length(curr_tickets))
|
||||
@@ -584,7 +584,7 @@
|
||||
//By default nuke just ends the round
|
||||
/datum/game_mode/proc/OnNukeExplosion(off_station)
|
||||
nuke_off_station = off_station
|
||||
if(off_station < 2)
|
||||
if(!off_station)
|
||||
station_was_nuked = TRUE //Will end the round on next check.
|
||||
|
||||
//Additional report section in roundend report
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
can_coexist_with_others = FALSE
|
||||
job_rank = ROLE_GANG
|
||||
antagpanel_category = "Gang"
|
||||
threat = 2
|
||||
var/hud_type = "gangster"
|
||||
var/message_name = "Gangster"
|
||||
var/datum/team/gang/gang
|
||||
@@ -167,6 +168,7 @@
|
||||
name = "Gang boss"
|
||||
hud_type = "gang_boss"
|
||||
message_name = "Leader"
|
||||
threat = 10
|
||||
|
||||
/datum/antagonist/gang/boss/on_gain()
|
||||
..()
|
||||
@@ -474,4 +476,4 @@
|
||||
|
||||
|
||||
#undef MAXIMUM_RECALLS
|
||||
#undef INFLUENCE_INTERVAL
|
||||
#undef INFLUENCE_INTERVAL
|
||||
|
||||
Reference in New Issue
Block a user