From e1f0c52b96f0cf90fb95f9fa7343617c10809660 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 14:13:23 -0800 Subject: [PATCH 001/141] that's storytellers. time for voting --- code/game/gamemodes/dynamic/dynamic.dm | 3 +- .../gamemodes/dynamic/dynamic_rulesets.dm | 2 + .../dynamic/dynamic_rulesets_events.dm | 19 ++++ .../dynamic/dynamic_rulesets_latejoin.dm | 3 + .../dynamic/dynamic_rulesets_midround.dm | 12 +++ .../dynamic/dynamic_rulesets_roundstart.dm | 14 +++ .../storytellers/dynamic_storytellers.dm | 93 +++++++++++++++++++ 7 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index cd9500284b..6566d41e21 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -60,7 +60,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) announce_text = "Dynamic mode!" // This needs to be changed maybe reroll_friendly = FALSE; - + // 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 var/threat_level = 0 diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm index 0c8ec0a2b8..e26eaa03c4 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm @@ -80,6 +80,8 @@ /// Delay for when execute will get called from the time of post_setup (roundstart) or process (midround/latejoin). /// Make sure your ruleset works with execute being called during the game when using this, and that the clean_up proc reverts it properly in case of faliure. var/delay = 0 + /// List of tags for use in storytellers. + var/list/property_weights = list() /datum/dynamic_ruleset/New() ..() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm index 4ac8cc91d3..0c0dbee820 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm @@ -46,6 +46,7 @@ cost = 10 blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear) requirements = list(70,60,50,50,40,40,40,30,20,15) + property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1) high_population_requirement = 15 /datum/dynamic_ruleset/event/pirates/ready(forced = FALSE) @@ -69,6 +70,7 @@ cost = 10 requirements = list(70,60,50,50,40,40,40,30,20,15) high_population_requirement = 15 + property_weights = list("chaos" = 1, "valid" = 1) ////////////////////////////////////////////// // // @@ -88,6 +90,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) // yes, can happen on fake-extended high_population_requirement = 5 repeatable = TRUE + property_weights = list("chaos" = 1, "extended" = 2) /datum/dynamic_ruleset/event/ventclog/ready() if(mode.threat_level > 30 && mode.threat >= 5 && prob(20)) @@ -125,6 +128,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("story_potential" = 5, "extended" = 1) ////////////////////////////////////////////// // // @@ -143,6 +147,7 @@ repeatable_weight_decrease = 2 requirements = list(60,50,40,30,30,30,30,30,30,30) high_population_requirement = 30 + property_weights = list("extended" = -2) /datum/dynamic_ruleset/event/meteor_wave/ready() if(mode.threat_level > 40 && mode.threat >= 25 && prob(20)) @@ -174,6 +179,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_flux name = "Anomaly: Hyper-Energetic Flux" @@ -187,6 +193,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_gravitational name = "Anomaly: Gravitational" @@ -198,6 +205,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_pyroclastic name = "Anomaly: Pyroclastic" @@ -211,6 +219,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/anomaly_vortex name = "Anomaly: Vortex" @@ -224,6 +233,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) ////////////////////////////////////////////// // // @@ -243,6 +253,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = -1, "chaos" = 1) /datum/dynamic_ruleset/event/carp_migration name = "Carp Migration" @@ -254,6 +265,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/communications_blackout name = "Communications Blackout" @@ -267,6 +279,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1, "chaos" = 1) /datum/dynamic_ruleset/event/processor_overload name = "Processor Overload" @@ -280,6 +293,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1, "chaos" = 1) /datum/dynamic_ruleset/event/space_dust name = "Minor Space Dust" @@ -293,6 +307,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/major_dust name = "Major Space Dust" @@ -306,6 +321,7 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/electrical_storm name = "Electrical Storm" @@ -319,6 +335,7 @@ requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/heart_attack name = "Random Heart Attack" @@ -332,6 +349,7 @@ requirements = list(101,101,101,5,5,5,5,5,5,5) high_population_requirement = 5 repeatable = TRUE + property_weights = list("extended" = 1) /datum/dynamic_ruleset/event/radiation_storm name = "Radiation Storm" @@ -343,3 +361,4 @@ required_enemies = list(1,1,1,1,1,1,1,1,1,1) requirements = list(5,5,5,5,5,5,5,5,5,5) high_population_requirement = 5 + property_weights = list("extended" = 1,"chaos" = 1) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 5810fd0ae0..8d9d14b473 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -69,6 +69,8 @@ high_population_requirement = 15 repeatable = TRUE flags = TRAITOR_RULESET + property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1) + ////////////////////////////////////////////// // // @@ -93,6 +95,7 @@ requirements = list(101,101,70,40,40,40,40,40,40,40) high_population_requirement = 40 flags = HIGHLANDER_RULESET + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) var/required_heads_of_staff = 3 var/finished = FALSE var/datum/team/revolution/revolution diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 8cda402ebf..1c077aec55 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -189,6 +189,7 @@ repeatable = TRUE high_population_requirement = 15 flags = TRAITOR_RULESET + property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1) /datum/dynamic_ruleset/midround/autotraitor/acceptable(population = 0, threat = 0) var/player_count = mode.current_players[CURRENT_LIVING_PLAYERS].len @@ -245,6 +246,7 @@ requirements = list(101,101,70,50,50,50,40,30,30,30) high_population_requirement = 30 required_type = /mob/living/silicon/ai + property_weights = list("story_potential" = 2, "trust" = 1, "chaos" = 3) var/ion_announce = 33 var/removeDontImproveChance = 10 @@ -297,6 +299,7 @@ requirements = list(90,90,70,50,50,50,50,40,30,30) high_population_requirement = 30 repeatable = TRUE + property_weights = list("story_potential" = 5, "trust" = 1, "chaos" = 3, "extended" = -2) var/datum/mind/wizard /datum/dynamic_ruleset/midround/from_ghosts/wizard/ready(forced = FALSE) @@ -344,6 +347,7 @@ cost = 35 requirements = list(90,90,90,80,70,60,50,40,40,40) high_population_requirement = 40 + property_weights = list("story_potential" = 3, "trust" = 5, "chaos" = 2, "extended" = -5, "valid" = 10) var/operative_cap = list(2,2,3,3,4,5,5,5,5,5) var/datum/team/nuclear/nuke_team flags = HIGHLANDER_RULESET @@ -396,6 +400,7 @@ requirements = list(101,101,101,80,60,50,50,50,50,50) high_population_requirement = 50 repeatable = TRUE + property_weights = list("story_potential" = -1, "trust" = 5, "chaos" = 3, "extended" = -5, "valid" = 4) /datum/dynamic_ruleset/midround/from_ghosts/blob/ready(forced = FALSE) if (required_candidates > (dead_players.len + list_observers.len)) @@ -426,6 +431,7 @@ high_population_requirement = 50 repeatable_weight_decrease = 2 repeatable = TRUE + property_weights = list("story_potential" = -1, "trust" = 5, "chaos" = 2, "extended" = -2, "valid" = 2) var/list/vents = list() /datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready(forced = FALSE) @@ -480,6 +486,7 @@ high_population_requirement = 50 repeatable_weight_decrease = 2 repeatable = TRUE + property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 5) var/list/spawn_locs = list() /datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute() @@ -525,6 +532,7 @@ weight = 4 cost = 5 requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"! + property_weights = list("story_potential" = 3, "extended" = 5, "valid" = -5, "integrity" = 2) high_population_requirement = 5 /datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/ready(forced = FALSE) @@ -558,6 +566,7 @@ cost = 5 requirements = list(30,30,30,30,20,15,15,15,15,15) high_population_requirement = 15 + property_weights = list("story_potential" = -3, "extended" = 5, "integrity" = 5) var/list/spawn_locs = list() /datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE) @@ -609,6 +618,7 @@ weight = 4 cost = 15 requirements = list(101,101,101,90,80,70,60,50,40,30) + property_weights = list("story_potential" = -3, "extended" = -5, "integrity" = 5, "valid" = 5, "trust" = 3) high_population_requirement = 30 var/list/spawn_locs = list() @@ -660,6 +670,7 @@ blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear) high_population_requirement = 15 var/datum/team/abductor_team/team + property_weights = list("story_potential" = 10, "extended" = 1, "valid" = 1, "trust" = -3) repeatable_weight_decrease = 4 repeatable = TRUE @@ -699,6 +710,7 @@ cost = 15 requirements = list(101,101,101,90,80,70,60,50,40,30) high_population_requirement = 30 + property_weights = list("story_potential" = 1, "extended" = -3, "valid" = 3) var/list/spawn_locs = list() var/spawn_loc diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 56b02a1364..0a5fead01b 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -21,6 +21,7 @@ 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) var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec) /datum/dynamic_ruleset/roundstart/traitor/pre_execute() @@ -60,6 +61,7 @@ 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 @@ -107,6 +109,7 @@ cost = 15 scaling_cost = 15 requirements = list(101,101,101,101,101,101,101,101,101,101) + property_weights = list("trust" = -2, "valid" = 3) high_population_requirement = 10 antag_cap = list(1,1,1,1,1,2,2,2,2,3) var/team_mode_probability = 30 @@ -159,6 +162,7 @@ cost = 30 requirements = list(101,101,101,60,50,50,50,50,50,50) high_population_requirement = 50 + property_weights = list("story_potential" = 5, "trust" = 1, "chaos" = 3, "extended" = -2, "valid" = 10) var/list/roundstart_wizards = list() /datum/dynamic_ruleset/roundstart/wizard/acceptable(population=0, threat=0) @@ -221,6 +225,7 @@ 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" = -5, "valid" = 5) high_population_requirement = 50 flags = HIGHLANDER_RULESET antag_cap = list(2,2,2,3,3,4,4,4,4,4) @@ -282,6 +287,7 @@ 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" = 3, "trust" = 5, "chaos" = 2, "extended" = -5, "valid" = 10) var/datum/team/nuclear/nuke_team /datum/dynamic_ruleset/roundstart/nuclear/ready(forced = FALSE) @@ -372,6 +378,7 @@ flags = HIGHLANDER_RULESET // I give up, just there should be enough heads with 35 players... minimum_players = 35 + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) var/datum/team/revolution/revolution var/finished = FALSE @@ -489,6 +496,7 @@ weight = 3 cost = 0 requirements = list(101,101,101,101,101,101,101,101,101,101) + property_weights = list("extended" = 1000) high_population_requirement = 101 /datum/dynamic_ruleset/roundstart/extended/pre_execute() @@ -516,6 +524,7 @@ high_population_requirement = 50 flags = HIGHLANDER_RULESET antag_cap = list(2,3,3,4,4,4,4,4,4,4) + property_weights = list("trust" = 3, "chaos" = 5, "extended" = -5, "conversion" = 1, "valid" = 10) var/ark_time /datum/dynamic_ruleset/roundstart/clockcult/pre_execute() @@ -615,6 +624,8 @@ 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" = 5, "chaos" = 5, "extended" = -5, "story_potential" = 10, "valid" = 10) + /datum/dynamic_ruleset/roundstart/nuclear/clown_ops/pre_execute() . = ..() @@ -646,6 +657,7 @@ 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] @@ -697,6 +709,7 @@ cost = 0 requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 + property_weights = list("extended" = -10, "chaos" = 5, "conversion" = 1, "valid" = 10) var/players_per_carrier = 30 var/monkeys_to_win = 1 var/escaped_monkeys = 0 @@ -758,6 +771,7 @@ cost = 0 requirements = list(101,101,101,101,101,101,101,101,101,101) high_population_requirement = 101 + property_weights = list("extended" = -10, "chaos" = 5, "trust" = 5) var/meteordelay = 2000 var/nometeors = 0 var/rampupdelta = 5 diff --git a/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm new file mode 100644 index 0000000000..c0a943a87e --- /dev/null +++ b/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm @@ -0,0 +1,93 @@ +/datum/dynamic_storyteller + var/name = "none" + var/desc = "A coder's idiocy." + var/list/property_weights = list() + var/datum/game_mode/dynamic/mode = null + +/** +Property weights are: +"story_potential" -- essentially how many different ways the antag can be played. +"trust" -- How much it makes the crew trust each other. Negative values means they're suspicious. Team antags are like this. +"chaos" -- How chaotic it makes the round. Has some overlap with "valid" and somewhat contradicts "extended". +"valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to + let everyone into the armory, wizard moving around and being a nuisance, nightmare busting lights. +"extended" -- How much the antag is conducive to a long round. Nukies and cults are bad for this; Wizard is less bad; and so on. +"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason. +*/ + +/datum/dynamic_storyteller/New() + ..() + if (istype(SSticker.mode, /datum/game_mode/dynamic)) + mode = SSticker.mode + else if (GLOB.master_mode != "dynamic") + qdel(src) + +/datum/dynamic_storyteller/proc/do_process() + continue + +/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) + // 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()) + var/property_weight = 0 + 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_weight[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + 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(current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) + // 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 && highlander_executed) + continue + + rule.candidates = list(newPlayer) + rule.trim_candidates() + if (rule.ready()) + var/property_weight = 0 + 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_weight[property] * property_weights[property] + drafted_rules[rule] = rule.get_weight() + property_weight + +/datum/dynamic_storyteller/team + name = "Teamwork" + desc = "Rules that are likely to get the crew to work together against a common enemy." + property_weights = list("valid" = 3, "trust" = 5) + +/datum/dynamic_storyteller/liteextended + name = "Extended-lite" + desc = "Rules that are likely to lead to rounds that reach their finish at the shuttle autocall." + property_weights = list("extended" = 5, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10) + +/datum/dynamic_storyteller/memes + name = "Story" + desc = "Rules that might lead to fun stories to tell." + property_weights = list("story_potential" = 10) + +/datum/dynamic_storyteller/cowabunga + name = "Cowabunga" + desc = "The most chaotic rules only. A validhunter's dream." + property_weights = list("extended" = -1, "chaos" = 10) + +/datum/dynamic_storyteller/suspicion + name = "Intrigue" + desc = "Rules that lead the crew to distrust one another." + property_weights = list("trust" = -5, "valid" = -1) + +/datum/dynamic_storyteller/classic + name = "Classic" + desc = "Uses default dynamic weights and nothing else. The most variety." From 0deaebc4ca9c9ad5d4bee056465983b3de1331a5 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 14:16:02 -0800 Subject: [PATCH 002/141] voting makes everything dumb --- code/game/gamemodes/dynamic/dynamic.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 6566d41e21..72a6457b96 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -52,6 +52,8 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset) // Forced threat level, setting this to zero or higher forces the roundstart threat to the value. GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) +GLOBAL_VAR_INIT(dynamic_storyteller, /datum/dynamic_storyteller/classic) + /datum/game_mode/dynamic name = "dynamic mode" config_tag = "dynamic" @@ -60,8 +62,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) announce_text = "Dynamic mode!" // This needs to be changed maybe reroll_friendly = FALSE; - // 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 var/threat_level = 0 From 967bcce38ee534c9ea7f4571d3d20a6e8b3a7f2b Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 14:17:05 -0800 Subject: [PATCH 003/141] actually i still need this --- code/game/gamemodes/dynamic/dynamic.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 72a6457b96..65c8cb347e 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -52,7 +52,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset) // Forced threat level, setting this to zero or higher forces the roundstart threat to the value. GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) -GLOBAL_VAR_INIT(dynamic_storyteller, /datum/dynamic_storyteller/classic) +GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) /datum/game_mode/dynamic name = "dynamic mode" @@ -62,6 +62,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller, /datum/dynamic_storyteller/classic) announce_text = "Dynamic mode!" // This needs to be changed maybe reroll_friendly = FALSE; + // 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 var/threat_level = 0 From b96d36e7192001897a51757d7a24a30bf9ffc8ca Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 20:01:30 -0800 Subject: [PATCH 004/141] alright that's that --- .../configuration/configuration.dm | 11 +++ code/controllers/subsystem/ticker.dm | 2 +- code/game/gamemodes/dynamic/dynamic.dm | 54 +++---------- .../dynamic_storytellers.dm | 78 +++++++++++++------ tgstation.dme | 1 + 5 files changed, 78 insertions(+), 68 deletions(-) rename code/game/gamemodes/dynamic/{storytellers => }/dynamic_storytellers.dm (55%) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index a5d27819b8..14954524fa 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -14,6 +14,7 @@ var/list/modes // allowed modes var/list/gamemode_cache var/list/votable_modes // votable modes + var/list/storyteller_cache var/list/mode_names var/list/mode_reports var/list/mode_false_report_weight @@ -37,6 +38,7 @@ CRASH("/datum/controller/configuration/Load() called more than once!") InitEntries() LoadModes() + storyteller_cache = typecacheof(/datum/dynamic_storyteller, TRUE) if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1) var/list/legacy_configs = list("game_options.txt", "dbconfig.txt", "comms.txt") for(var/I in legacy_configs) @@ -227,6 +229,7 @@ for(var/T in gamemode_cache) // I wish I didn't have to instance the game modes in order to look up // their information, but it is the only way (at least that I know of). + // for future reference: just use initial() lol var/datum/game_mode/M = new T() if(M.config_tag) @@ -317,6 +320,14 @@ return new T return new /datum/game_mode/extended() +/datum/controller/configuration/proc/pick_storyteller(storyteller_name) + for(var/T in storyteller_cache) + var/datum/dynamic_storyteller/S = T + var/name = initial(S.name) + if(name && name == storyteller_name) + return T + return /datum/dynamic_storyteller/classic + /datum/controller/configuration/proc/get_runnable_modes() var/list/datum/game_mode/runnable_modes = new var/list/probabilities = Get(/datum/config_entry/keyed_list/probability) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 6f619fef0b..baaa78e56f 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -480,7 +480,7 @@ SUBSYSTEM_DEF(ticker) SSticker.timeLeft = 900 SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) - SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE) + SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic) /datum/controller/subsystem/ticker/Recover() current_state = SSticker.current_state diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 65c8cb347e..ea780d47fe 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -52,7 +52,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset) // Forced threat level, setting this to zero or higher forces the roundstart threat to the value. GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) -GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) +GLOBAL_VAR_INIT(dynamic_storyteller_type, null) /datum/game_mode/dynamic name = "dynamic mode" @@ -373,6 +373,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) if("Event") if(ruleset.weight) events += ruleset + storyteller = new GLOB.dynamic_storyteller_type for(var/mob/dead/new_player/player in GLOB.player_list) if(player.ready == PLAYER_READY_TO_PLAY && player.mind) roundstart_pop_ready++ @@ -422,13 +423,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) if (GLOB.dynamic_forced_extended) log_game("DYNAMIC: Starting a round of forced extended.") return TRUE - var/list/drafted_rules = list() - for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules) - if (rule.acceptable(roundstart_pop_ready, threat_level) && threat >= rule.cost) // If we got the population and threat required - rule.candidates = candidates.Copy() - rule.trim_candidates() - if (rule.ready() && rule.candidates.len > 0) - drafted_rules[rule] = rule.weight + var/list/drafted_rules = storyteller.roundstart_draft() if(!drafted_rules.len) message_admins("Not enough threat level for roundstart antags!") log_game("DYNAMIC: Not enough threat level for roundstart antags!") @@ -655,7 +650,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) for (var/datum/dynamic_ruleset/rule in current_rules) if(rule.rule_process() == RULESET_STOP_PROCESSING) // If rule_process() returns 1 (RULESET_STOP_PROCESSING), stop processing. current_rules -= rule - + + storyteller.do_process() + if (midround_injection_cooldown < world.time) if (GLOB.dynamic_forced_extended) return @@ -673,21 +670,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) update_playercounts() if (get_injection_chance()) - var/cur_threat_frac = threat/threat_level - var/list/drafted_rules = list() - var/antag_num = current_players[CURRENT_LIVING_ANTAGS].len - for (var/datum/dynamic_ruleset/midround/rule in midround_rules) - // if there are antags OR the rule is an antag rule, antag_acceptable will be true. - if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost) - // 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()) - if(!antag_num) - drafted_rules[rule] = round(rule.get_weight() + (rule.cost * cur_threat_frac)) - else - drafted_rules[rule] = rule.get_weight() + var/list/drafted_rules = storyteller.midround_draft() if (drafted_rules.len > 0) picking_midround_latejoin_rule(drafted_rules) else @@ -699,11 +682,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) message_admins("DYNAMIC: Doing event injection.") log_game("DYNAMIC: Doing event injection.") update_playercounts() - var/list/drafted_rules = list() - for(var/datum/dynamic_ruleset/event/rule in events) - if(rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost) - if(rule.ready()) - drafted_rules[rule] = rule.get_weight() + var/list/drafted_rules = storyteller.event_draft() if(drafted_rules.len > 0) picking_midround_latejoin_rule(drafted_rules) @@ -795,22 +774,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) forced_latejoin_rule = null else if (latejoin_injection_cooldown < world.time && prob(get_injection_chance())) - var/list/drafted_rules = list() - for (var/datum/dynamic_ruleset/latejoin/rule in latejoin_rules) - if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost) - // 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 (threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) - if(rule.flags & HIGHLANDER_RULESET && highlander_executed) - continue - - rule.candidates = list(newPlayer) - rule.trim_candidates() - if (rule.ready()) - drafted_rules[rule] = rule.get_weight() - + var/list/drafted_rules = storyteller.latejoin_draft(newPlayer) if (drafted_rules.len > 0 && picking_midround_latejoin_rule(drafted_rules)) var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min) latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max)) + world.time diff --git a/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm similarity index 55% rename from code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm rename to code/game/gamemodes/dynamic/dynamic_storytellers.dm index c0a943a87e..de15c03080 100644 --- a/code/game/gamemodes/dynamic/storytellers/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -2,6 +2,8 @@ var/name = "none" var/desc = "A coder's idiocy." var/list/property_weights = list() + var/curve_centre = 0 + var/curve_width = 1.8 var/datum/game_mode/dynamic/mode = null /** @@ -19,11 +21,23 @@ Property weights are: ..() if (istype(SSticker.mode, /datum/game_mode/dynamic)) mode = SSticker.mode - else if (GLOB.master_mode != "dynamic") - qdel(src) /datum/dynamic_storyteller/proc/do_process() - continue + return + +/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 + rule.candidates = mode.candidates.Copy() + rule.trim_candidates() + if (rule.ready() && rule.candidates.len > 0) + var/property_weight = 0 + 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 + return drafted_rules /datum/dynamic_storyteller/proc/midround_draft() var/list/drafted_rules = list() @@ -37,55 +51,75 @@ Property weights are: if (rule.ready()) var/property_weight = 0 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_weight[property] * property_weights[property] + if(property in rule.property_weights) + property_weight += rule.property_weights[property] * property_weights[property] drafted_rules[rule] = rule.get_weight() + property_weight 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(current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost) - // Classic secret : only autotraitor/minor roles - if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) + 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) + // 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 - // 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 && highlander_executed) - continue - rule.candidates = list(newPlayer) - rule.trim_candidates() - if (rule.ready()) - var/property_weight = 0 - 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_weight[property] * property_weights[property] - drafted_rules[rule] = rule.get_weight() + property_weight + rule.candidates = list(newPlayer) + rule.trim_candidates() + 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 + 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.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 + return drafted_rules /datum/dynamic_storyteller/team name = "Teamwork" desc = "Rules that are likely to get the crew to work together against a common enemy." + curve_centre = 2 + curve_width = 1.5 property_weights = list("valid" = 3, "trust" = 5) /datum/dynamic_storyteller/liteextended name = "Extended-lite" desc = "Rules that are likely to lead to rounds that reach their finish at the shuttle autocall." + curve_centre = -5 + curve_width = 0.5 property_weights = list("extended" = 5, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10) /datum/dynamic_storyteller/memes name = "Story" desc = "Rules that might lead to fun stories to tell." + curve_width = 4 property_weights = list("story_potential" = 10) /datum/dynamic_storyteller/cowabunga name = "Cowabunga" + curve_centre = 10 desc = "The most chaotic rules only. A validhunter's dream." property_weights = list("extended" = -1, "chaos" = 10) /datum/dynamic_storyteller/suspicion name = "Intrigue" desc = "Rules that lead the crew to distrust one another." + curve_width = 4 property_weights = list("trust" = -5, "valid" = -1) /datum/dynamic_storyteller/classic diff --git a/tgstation.dme b/tgstation.dme index 4c7e29739f..98a998b2e2 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -573,6 +573,7 @@ #include "code\game\gamemodes\dynamic\dynamic_rulesets_latejoin.dm" #include "code\game\gamemodes\dynamic\dynamic_rulesets_midround.dm" #include "code\game\gamemodes\dynamic\dynamic_rulesets_roundstart.dm" +#include "code\game\gamemodes\dynamic\dynamic_storytellers.dm" #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\meteor\meteor.dm" #include "code\game\gamemodes\meteor\meteors.dm" From 74e4391cee917bfc672fc3e40361b74576deb01a Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 20:01:38 -0800 Subject: [PATCH 005/141] uh, vote changes necessary too --- code/controllers/subsystem/vote.dm | 106 ++++++++++++++++------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index dee10e4998..9c2f4814ac 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -1,3 +1,6 @@ +#define PLURALITY 0 +#define APPROVAL 1 + SUBSYSTEM_DEF(vote) name = "Vote" wait = 10 @@ -10,8 +13,10 @@ SUBSYSTEM_DEF(vote) var/started_time = null var/time_remaining = 0 var/mode = null + var/vote_system = PLURALITY var/question = null var/list/choices = list() + var/list/choice_descs = list() // optional descriptions var/list/voted = list() var/list/voting = list() var/list/generated_actions = list() @@ -124,9 +129,6 @@ SUBSYSTEM_DEF(vote) message_admins(admintext) return . -#define PEACE "calm" -#define CHAOS "chaotic" - /datum/controller/subsystem/vote/proc/result() . = announce_result() var/restart = 0 @@ -153,32 +155,15 @@ SUBSYSTEM_DEF(vote) if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started. return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.") GLOB.master_mode = "dynamic" - if("extended" in choices) - if(. == "extended") - GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff - choices[PEACE] += choices["extended"] - var/mean = 0 - var/voters = 0 - for(var/client/c in GLOB.clients) - var/vote = c.prefs.preferred_chaos - if(vote) - voters += 1 - switch(vote) - if(CHAOS_NONE) - mean -= 0.1 - if(CHAOS_LOW) - mean -= 0.05 - if(CHAOS_HIGH) - mean += 0.05 - if(CHAOS_MAX) - mean += 0.1 - mean/=voters - if(voted.len != 0) - mean += (choices[PEACE]*-1+choices[CHAOS])/voted.len - GLOB.dynamic_curve_centre = mean*20 - GLOB.dynamic_curve_width = CLAMP(2-abs(mean*5),0.5,4) - to_chat(world,"Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width].") - log_admin("Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width]") + if(. == "extended") + GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff + GLOB.dynamic_storyteller_type = /datum/dynamic_storyteller/liteextended + GLOB.dynamic_forced_threat_level = 15 + else + var/datum/dynamic_storyteller/S = config.pick_storyteller(.) + GLOB.dynamic_storyteller_type = S + GLOB.dynamic_curve_centre = initial(S.curve_centre) + GLOB.dynamic_curve_width = initial(S.curve_width) if("map") var/datum/map_config/VM = config.maplist[.] message_admins("The map has been voted for and will change to: [VM.map_name]") @@ -203,20 +188,36 @@ SUBSYSTEM_DEF(vote) if(mode) if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !usr.client.holder) return 0 - if(!(usr.ckey in voted)) - if(vote && 1<=vote && vote<=choices.len) - voted += usr.ckey - voted[usr.ckey] = vote - choices[choices[vote]]++ //check this - return vote - else if(vote && 1<=vote && vote<=choices.len) - choices[choices[voted[usr.ckey]]]-- - voted[usr.ckey] = vote - choices[choices[vote]]++ - return vote + if(vote && vote >= 1 && vote <= choices.len) + switch(vote_system) + if(PLURALITY) + if(usr.ckey in voted) + choices[choices[voted[usr.ckey]]]-- + voted[usr.ckey] = vote + choices[choices[vote]]++ + return vote + else + voted += usr.ckey + voted[usr.ckey] = vote + choices[choices[vote]]++ //check this + return vote + if(APPROVAL) + if(usr.ckey in voted) + if(vote in voted[usr.ckey]) + voted[usr.ckey] -= vote + choices[choices[vote]]-- + else + voted[usr.ckey].Add(vote) + choices[choices[vote]]++ + else + voted += usr.ckey + voted[usr.ckey] = list(vote) + choices[choices[vote]]++ + return vote return 0 -/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes +/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes + vote_system = votesystem if(!mode) if(started_time) var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay)) @@ -259,9 +260,11 @@ SUBSYSTEM_DEF(vote) if("dynamic") var/saved_threats = SSpersistence.saved_threat_levels if((saved_threats[1]+saved_threats[2]+saved_threats[3])>150) - choices.Add("extended",PEACE,CHAOS) - else - choices.Add(PEACE,CHAOS) + choices.Add("extended") + for(var/T in config.storyteller_cache) + var/datum/dynamic_storyteller/S = T + choices.Add(initial(S.name)) + choice_descs.Add(initial(S.desc)) if("custom") question = stripped_input(usr,"What is the vote for?") if(!question) @@ -311,13 +314,21 @@ SUBSYSTEM_DEF(vote) . += "

Vote: '[question]'

" else . += "

Vote: [capitalize(mode)]

" + . += "

Vote [vote_system == PLURALITY ? "your top choice" : "all that apply"].

" . += "Time Left: [time_remaining] s
    " for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] - var/ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i) ? TRUE : FALSE) + var/ivotedforthis = FALSE + switch(vote_system) + if(PLURALITY) + ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) + if(APPROVAL) + ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) if(!votes) votes = 0 . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes + if(choice_descs.len >= i) + . += "
  • [choice_descs[i]]
  • " . += "

" if(admin) . += "(Cancel Vote) " @@ -392,7 +403,7 @@ SUBSYSTEM_DEF(vote) set category = "OOC" set name = "Vote" - var/datum/browser/popup = new(src, "vote", "Voting Panel") + var/datum/browser/popup = new(src, "vote", "Voting Panel",nwidth=600,nheight=600) popup.set_window_options("can_close=0") popup.set_content(SSvote.interface(client)) popup.open(0) @@ -419,6 +430,3 @@ SUBSYSTEM_DEF(vote) var/datum/player_details/P = GLOB.player_details[owner.ckey] if(P) P.player_actions -= src - -#undef PEACE -#undef CHAOS From e44566038b9e949a92a40f208cb8a15dc89c7c04 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 14 Dec 2019 20:32:34 -0800 Subject: [PATCH 006/141] linter is correct --- code/controllers/subsystem/vote.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 9c2f4814ac..b34713254d 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -207,7 +207,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] -= vote choices[choices[vote]]-- else - voted[usr.ckey].Add(vote) + voted[usr.ckey] += vote choices[choices[vote]]++ else voted += usr.ckey From f943bcb3b573bce3aa1f7090cd4ce48d1968cef7 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 12:17:07 -0800 Subject: [PATCH 007/141] make cowabunga description less, uh, bad --- code/game/gamemodes/dynamic/dynamic_storytellers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index de15c03080..8e33c94a24 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -113,7 +113,7 @@ Property weights are: /datum/dynamic_storyteller/cowabunga name = "Cowabunga" curve_centre = 10 - desc = "The most chaotic rules only. A validhunter's dream." + desc = "The most chaotic rules are weighted heavily here. Rounds are nasty, brutish and short." property_weights = list("extended" = -1, "chaos" = 10) /datum/dynamic_storyteller/suspicion From 3d0d1de94c912eaaa01ea47faf4aaa1d62942a72 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 14:49:32 -0800 Subject: [PATCH 008/141] Added bloodsucker weights. --- .../dynamic/dynamic_rulesets_midround.dm | 37 ++++++++++--------- .../dynamic/dynamic_rulesets_roundstart.dm | 1 + 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index be497b3cce..84d33ce669 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -754,23 +754,24 @@ ////////////////////////////////////////////// /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 - requirements = list(90,80,70,60,55,50,45,40,35,30) - high_population_requirement = 30 - repeatable = TRUE + 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("extended" = 2, "chaos" = -1, "trust" = -3, "story_potential" = -2, "conversion" = 1, "valid" = 1) + requirements = list(90,80,70,60,55,50,45,40,35,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 - return TRUE + var/mob/M = pick(candidates) + assigned += M.mind + M.mind.special_role = antag_flag + if(mode.make_bloodsucker(M.mind)) + mode.bloodsuckers += M + return TRUE diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 80146b8657..1abdcef3f1 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -812,6 +812,7 @@ weight = 2 cost = 15 scaling_cost = 10 + property_weights = list("extended" = 2, "chaos" = -1, "trust" = -3, "story_potential" = -2, "conversion" = 1) requirements = list(90,80,70,60,50,50,50,50,50,50) high_population_requirement = 50 antag_cap = list(1,1,1,1,1,2,2,2,2,2) From 138f2d05f06410c5f2f534d2c9140f720dcde01c Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 14:49:43 -0800 Subject: [PATCH 009/141] Made intrigue not care about valid. --- code/game/gamemodes/dynamic/dynamic_storytellers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index 8e33c94a24..1f0abc7312 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -120,7 +120,7 @@ Property weights are: name = "Intrigue" desc = "Rules that lead the crew to distrust one another." curve_width = 4 - property_weights = list("trust" = -5, "valid" = -1) + property_weights = list("trust" = -5) /datum/dynamic_storyteller/classic name = "Classic" From f244ac84b21a6bbf9a2cf53b4b265d2fa0aa1b27 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 15 Dec 2019 15:25:47 -0800 Subject: [PATCH 010/141] whoops --- code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 84d33ce669..6b03bb3fb3 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -773,5 +773,5 @@ assigned += M.mind M.mind.special_role = antag_flag if(mode.make_bloodsucker(M.mind)) - mode.bloodsuckers += M + mode.bloodsuckers += M return TRUE From 5bf252a58c408b8b5f9a70acd6b70bdcc1e81766 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Tue, 17 Dec 2019 01:57:56 +0100 Subject: [PATCH 011/141] Ports "Fixes ChangeTurf CHANGETURF_INHERIT_AIR flag and add it to all calls." --- code/game/mecha/equipment/tools/work_tools.dm | 6 +- .../effects/effect_system/effects_foam.dm | 2 +- code/game/objects/items/stacks/stack.dm | 9 ++- code/game/objects/items/twohanded.dm | 2 +- code/game/objects/structures/lattice.dm | 2 +- code/game/objects/structures/stairs.dm | 4 +- code/game/turfs/change_turf.dm | 15 ++-- code/game/turfs/closed.dm | 2 +- code/game/turfs/open.dm | 2 +- code/game/turfs/openspace/openspace.dm | 2 +- code/game/turfs/simulated/chasm.dm | 4 +- code/game/turfs/simulated/floor.dm | 22 +++--- code/game/turfs/simulated/floor/plating.dm | 12 +-- .../game/turfs/simulated/floor/reinf_floor.dm | 14 ++-- code/game/turfs/simulated/lava.dm | 2 +- code/game/turfs/space/space.dm | 4 +- code/game/turfs/turf.dm | 4 +- .../clock_items/replica_fabricator.dm | 2 +- .../clockcult/clock_structures/wall_gear.dm | 2 +- .../antagonists/cult/cult_structures.dm | 4 +- code/modules/buildmode/submodes/basic.dm | 6 +- .../mining/lavaland/necropolis_chests.dm | 4 +- .../mob/living/simple_animal/bot/floorbot.dm | 8 +- .../hostile/megafauna/colossus.dm | 5 +- .../hostile/mining_mobs/necropolis_tendril.dm | 2 +- code/modules/projectiles/projectile/magic.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 77 ++++--------------- .../reagents/pyrotechnic_reagents.dm | 2 +- .../ruins/objects_and_mobs/sin_ruins.dm | 2 +- code/modules/spells/spell_types/conjure.dm | 2 +- code/modules/spells/spell_types/devil.dm | 4 +- .../reagents/chemistry/reagents/astrogen.dm | 2 +- 32 files changed, 91 insertions(+), 141 deletions(-) diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 36708fcf90..ca8e8cecd9 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -262,14 +262,14 @@ occupant_message("Deconstructing [W]...") if(do_after_cooldown(W)) chassis.spark_system.start() - W.ScrapeAway() + W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) playsound(W, 'sound/items/deconstruct.ogg', 50, 1) else if(isfloorturf(target)) var/turf/open/floor/F = target occupant_message("Deconstructing [F]...") if(do_after_cooldown(target)) chassis.spark_system.start() - F.ScrapeAway() + F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) playsound(F, 'sound/items/deconstruct.ogg', 50, 1) else if (istype(target, /obj/machinery/door/airlock)) occupant_message("Deconstructing [target]...") @@ -282,7 +282,7 @@ var/turf/open/space/S = target occupant_message("Building Floor...") if(do_after_cooldown(S)) - S.PlaceOnTop(/turf/open/floor/plating) + S.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) playsound(S, 'sound/items/deconstruct.ogg', 50, 1) chassis.spark_system.start() else if(isfloorturf(target)) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 10ee73915c..b6deaa1d06 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -123,7 +123,7 @@ if(metal) var/turf/T = get_turf(src) if(isspaceturf(T)) //Block up any exposed space - T.PlaceOnTop(/turf/open/floor/plating/foam) + T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR) for(var/direction in GLOB.cardinals) var/turf/cardinal_turf = get_step(T, direction) if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index e8bd50f19b..d2ddd493b2 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -192,9 +192,14 @@ var/obj/O if(R.max_res_amount > 1) //Is it a stack? O = new R.result_type(usr.drop_location(), R.res_amount * multiplier) - else + else if(ispath(R.result_type, /turf)) + var/turf/T = usr.drop_location() + if(!isturf(T)) + return + T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR) O = new R.result_type(usr.drop_location()) - O.setDir(usr.dir) + if(O) + O.setDir(usr.dir) use(R.req_amount * multiplier) //START: oh fuck i'm so sorry diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index dd7d46d0d7..d7891feaa0 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -872,7 +872,7 @@ user.visible_message("[user] blasts \the [target] with \the [src]!") playsound(target, 'sound/magic/disintegrate.ogg', 100, 1) W.break_wall() - W.ScrapeAway() + W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return //HF blade diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index b946a06432..a7eaea0d16 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -60,7 +60,7 @@ to_chat(user, "You build a floor.") var/turf/T = src.loc if(isspaceturf(T)) - T.PlaceOnTop(/turf/open/floor/plating) + T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) qdel(src) return TRUE return FALSE diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm index bd657fe1e8..f2c4e628e0 100644 --- a/code/game/objects/structures/stairs.dm +++ b/code/game/objects/structures/stairs.dm @@ -102,13 +102,13 @@ /obj/structure/stairs/proc/force_open_above() var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) if(T && !istype(T)) - T.ChangeTurf(/turf/open/openspace) + T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR) /obj/structure/stairs/proc/on_multiz_new(turf/source, dir) if(dir == UP) var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) if(T && !istype(T)) - T.ChangeTurf(/turf/open/openspace) + T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR) /obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1) . = ..() diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 6a055bbd35..990ec91eeb 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -128,16 +128,15 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/open/ChangeTurf(path, list/new_baseturfs, flags) if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open)) SSair.remove_from_active(src) - var/stashed_air = air - air = null // so that it doesn't get deleted + var/datum/gas_mixture/stashed_air = new() + stashed_air.copy_from(air) . = ..() - if (!. || . == src) // changeturf failed or didn't do anything - air = stashed_air + if (!.) // changeturf failed or didn't do anything + QDEL_NULL(stashed_air) return var/turf/open/newTurf = . - if (!istype(newTurf.air, /datum/gas_mixture/immutable/space)) - QDEL_NULL(newTurf.air) - newTurf.air = stashed_air + newTurf.air.copy_from(stashed_air) + QDEL_NULL(stashed_air) SSair.add_to_active(newTurf) else if(ispath(path,/turf/closed)) @@ -315,5 +314,5 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( SSair.add_to_active(src) /turf/proc/ReplaceWithLattice() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) new /obj/structure/lattice(locate(x, y, z)) diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 6297cadc63..9e593cafce 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -23,7 +23,7 @@ icon = 'icons/turf/walls.dmi' explosion_block = 50 -/turf/closed/indestructible/TerraformTurf(path, defer_change = FALSE, ignore_air = FALSE) +/turf/closed/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE) return /turf/closed/indestructible/acid_act(acidpwr, acid_volume, acid_id) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 4bdb13effc..577c45a7f0 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -58,7 +58,7 @@ /turf/open/indestructible/singularity_act() return -/turf/open/indestructible/TerraformTurf(path, defer_change = FALSE, ignore_air = FALSE) +/turf/open/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE) return /turf/open/indestructible/sound diff --git a/code/game/turfs/openspace/openspace.dm b/code/game/turfs/openspace/openspace.dm index e68aabcd08..66507e7053 100644 --- a/code/game/turfs/openspace/openspace.dm +++ b/code/game/turfs/openspace/openspace.dm @@ -106,7 +106,7 @@ qdel(L) playsound(src, 'sound/weapons/genhit.ogg', 50, 1) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You need one floor tile to build a floor!") else diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm index 0a7b507488..dab0c1c376 100644 --- a/code/game/turfs/simulated/chasm.dm +++ b/code/game/turfs/simulated/chasm.dm @@ -38,7 +38,7 @@ switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE @@ -70,7 +70,7 @@ playsound(src, 'sound/weapons/genhit.ogg', 50, 1) to_chat(user, "You build a floor.") // Create a floor, which has this chasm underneath it - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You need one floor tile to build a floor!") else diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 194014b61a..4973e68a68 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -62,29 +62,29 @@ if(severity != 1 && shielded && target != src) return if(target == src) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return if(target != null) severity = 3 switch(severity) if(1) - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) if(2) switch(pick(1,2;75,3)) if(1) if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) ReplaceWithLattice() else - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) if(prob(33)) new /obj/item/stack/sheet/metal(src) if(2) - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) if(3) if(prob(80)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else break_tile() hotspot_expose(1000,CELL_VOLUME) @@ -135,7 +135,7 @@ burnt = 1 /turf/open/floor/proc/make_plating() - return ScrapeAway() + return ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/ChangeTurf(path, new_baseturf, flags) if(!isfloorturf(src)) @@ -213,15 +213,15 @@ /turf/open/floor/narsie_act(force, ignore_mobs, probability = 20) . = ..() if(.) - ChangeTurf(/turf/open/floor/engine/cult) + ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/ratvar_act(force, ignore_mobs) . = ..() if(.) - ChangeTurf(/turf/open/floor/clockwork) + ChangeTurf(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/acid_melt() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) switch(the_rcd.mode) @@ -267,7 +267,7 @@ A.autoclose = TRUE return TRUE if(RCD_DECONSTRUCT) - if(ScrapeAway() == src) + if(ScrapeAway(flags = CHANGETURF_INHERIT_AIR) == src) return FALSE to_chat(user, "You deconstruct [src].") return TRUE diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index ae67edf073..a6d8ec5db2 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -61,7 +61,7 @@ to_chat(user, "You begin reinforcing the floor...") if(do_after(user, 30, target = src)) if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine)) - PlaceOnTop(/turf/open/floor/engine) + PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR) playsound(src, 'sound/items/deconstruct.ogg', 80, 1) R.use(2) to_chat(user, "You reinforce the floor.") @@ -76,7 +76,7 @@ var/obj/item/stack/tile/W = C if(!W.use(1)) return - var/turf/open/floor/T = PlaceOnTop(W.turf_type) + var/turf/open/floor/T = PlaceOnTop(W.turf_type, flags = CHANGETURF_INHERIT_AIR) if(istype(W, /obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow var/obj/item/stack/tile/light/L = W var/turf/open/floor/light/F = T @@ -117,7 +117,7 @@ qdel(L) to_chat(user, "You reinforce the foamed plating with tiling.") playsound(src, 'sound/weapons/Genhit.ogg', 50, TRUE) - ChangeTurf(/turf/open/floor/plating) + ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else playsound(src, 'sound/weapons/tap.ogg', 100, TRUE) //The attack sound is muffled by the foam itself user.changeNext_move(CLICK_CD_MELEE) @@ -125,7 +125,7 @@ if(prob(I.force * 20 - 25)) user.visible_message("[user] smashes through [src]!", \ "You smash through [src] with [I]!") - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You hit [src], to no effect!") @@ -136,13 +136,13 @@ /turf/open/floor/plating/foam/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) if(passed_mode == RCD_FLOORWALL) to_chat(user, "You build a floor.") - ChangeTurf(/turf/open/floor/plating) + ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE /turf/open/floor/plating/foam/ex_act() ..() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/plating/foam/tool_act(mob/living/user, obj/item/I, tool_type) return diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index b04f89f8be..28ffbbd1ff 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -43,7 +43,7 @@ return TRUE if(floor_tile) new floor_tile(src, 2) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return TRUE /turf/open/floor/engine/acid_act(acidpwr, acid_volume) @@ -56,23 +56,23 @@ if(severity != 1 && shielded && target != src) return if(target == src) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return switch(severity) if(1) if(prob(80)) if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) ReplaceWithLattice() else - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) else if(prob(50)) - ScrapeAway(2) + ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR) else - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) if(2) if(prob(50)) - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/engine/singularity_pull(S, current_size) ..() diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 362b410cbb..2f8ae0cb93 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -54,7 +54,7 @@ switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index f38f13e657..5278374abd 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -125,7 +125,7 @@ qdel(L) playsound(src, 'sound/weapons/genhit.ogg', 50, 1) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else to_chat(user, "You need one floor tile to build a floor!") else @@ -212,7 +212,7 @@ switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") - PlaceOnTop(/turf/open/floor/plating) + PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) return TRUE return FALSE diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d618e457b0..81757ab7f5 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -391,7 +391,7 @@ continue if(O.invisibility == INVISIBILITY_MAXIMUM) O.singularity_act() - ScrapeAway() + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return(2) /turf/proc/can_have_cabling() @@ -564,4 +564,4 @@ //Whatever happens after high temperature fire dies out or thermite reaction works. //Should return new turf /turf/proc/Melt() - return ScrapeAway() + return ScrapeAway(flags = CHANGETURF_INHERIT_AIR) diff --git a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm index 0365ae63af..501bcdc1c4 100644 --- a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm +++ b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm @@ -139,7 +139,7 @@ var/new_thing_type = fabrication_values["new_obj_type"] if(isturf(target)) //if our target is a turf, we're just going to ChangeTurf it and assume it'll work out. var/turf/T = target - T.ChangeTurf(new_thing_type) + T.ChangeTurf(new_thing_type, flags = CHANGETURF_INHERIT_AIR) else if(new_thing_type) if(fabrication_values["dir_in_new"]) diff --git a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm index 32b1b61dd1..d823f19d4a 100644 --- a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm +++ b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm @@ -59,7 +59,7 @@ if(anchored) T.PlaceOnTop(/turf/closed/wall/clockwork) else - T.PlaceOnTop(/turf/open/floor/clockwork) + T.PlaceOnTop(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR) new /obj/structure/falsewall/brass(T) qdel(src) else diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm index f38f379abe..6f340b9271 100644 --- a/code/modules/antagonists/cult/cult_structures.dm +++ b/code/modules/antagonists/cult/cult_structures.dm @@ -239,9 +239,9 @@ var/turf/T = safepick(validturfs) if(T) if(istype(T, /turf/open/floor/plating)) - T.PlaceOnTop(/turf/open/floor/engine/cult) + T.PlaceOnTop(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR) else - T.ChangeTurf(/turf/open/floor/engine/cult) + T.ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR) else var/turf/open/floor/engine/cult/F = safepick(cultturfs) if(F) diff --git a/code/modules/buildmode/submodes/basic.dm b/code/modules/buildmode/submodes/basic.dm index 4f7b176691..fe3d831d81 100644 --- a/code/modules/buildmode/submodes/basic.dm +++ b/code/modules/buildmode/submodes/basic.dm @@ -22,9 +22,9 @@ if(istype(object,/turf) && left_click && !alt_click && !ctrl_click) var/turf/T = object if(isspaceturf(object)) - T.PlaceOnTop(/turf/open/floor/plating) + T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else if(isplatingturf(object)) - T.PlaceOnTop(/turf/open/floor/plasteel) + T.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) else if(isfloorturf(object)) T.PlaceOnTop(/turf/closed/wall) else if(iswallturf(object)) @@ -35,7 +35,7 @@ log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]") if(isturf(object)) var/turf/T = object - T.ScrapeAway() + T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else if(isobj(object)) qdel(object) return diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index ab3b20ac9f..7bef9b652a 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -926,7 +926,7 @@ timer = world.time + create_delay + 1 if(do_after(user, create_delay, target = T)) var/old_name = T.name - if(T.TerraformTurf(turf_type)) + if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR)) user.visible_message("[user] turns \the [old_name] into [transform_string]!") message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]") log_game("[key_name(user)] fired the lava staff at [AREACOORD(T)].") @@ -937,7 +937,7 @@ qdel(L) else var/old_name = T.name - if(T.TerraformTurf(reset_turf_type)) + if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR)) user.visible_message("[user] turns \the [old_name] into [reset_string]!") timer = world.time + reset_cooldown playsound(T,'sound/magic/fireball.ogg', 200, 1) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 396c6de166..cae707ce46 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -318,9 +318,9 @@ sleep(50) if(mode == BOT_REPAIRING && src.loc == target_turf) if(autotile) //Build the floor and include a tile. - target_turf.PlaceOnTop(/turf/open/floor/plasteel) + target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) else //Build a hull plating without a floor tile. - target_turf.PlaceOnTop(/turf/open/floor/plating) + target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else var/turf/open/floor/F = target_turf @@ -334,7 +334,7 @@ if(mode == BOT_REPAIRING && F && src.loc == F) F.broken = 0 F.burnt = 0 - F.PlaceOnTop(/turf/open/floor/plasteel) + F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F)) anchored = TRUE @@ -345,7 +345,7 @@ if(mode == BOT_REPAIRING && F && src.loc == F) F.broken = 0 F.burnt = 0 - F.PlaceOnTop(initial(tiletype.turf_type)) + F.PlaceOnTop(initial(tiletype.turf_type), flags = CHANGETURF_INHERIT_AIR) specialtiles -= 1 if(specialtiles == 0) speak("Requesting refill of custom floortiles to continue replacing.") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 51a9d8d62b..c2c9f5a71f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -486,10 +486,7 @@ Difficulty: Very Hard if(isturf(Stuff)) var/turf/T = Stuff if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors) - var/turf/open/O = T.ChangeTurf(NewTerrainFloors) - if(O.air) - var/datum/gas_mixture/G = O.air - G.copy_from_turf(O) + var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR) if(prob(florachance) && NewFlora.len && !is_blocked_turf(O, TRUE)) var/atom/Picked = pick(NewFlora) new Picked(O) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm index e3c81b2639..27ebb71c0e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm @@ -91,5 +91,5 @@ visible_message("The tendril falls inward, the ground around it widening into a yawning chasm!") for(var/turf/T in range(2,src)) if(!T.density) - T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland) + T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland, flags = CHANGETURF_INHERIT_AIR) qdel(src) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 173d9721a9..791db320a2 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -93,7 +93,7 @@ /obj/item/projectile/magic/door/proc/CreateDoor(turf/T) var/door_type = pick(door_types) var/obj/structure/mineral_door/D = new door_type(T) - T.ChangeTurf(/turf/open/floor/plating) + T.ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) D.Open() /obj/item/projectile/magic/door/proc/OpenDoor(var/obj/machinery/door/D) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index eceb1cdd29..7aae6cc3a5 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1870,133 +1870,82 @@ reagent_state = LIQUID color = "#b51d05" taste_description = "carpet" // Your tounge feels furry. + var/carpet_type = /turf/open/floor/carpet /datum/reagent/carpet/reaction_turf(turf/T, reac_volume) if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet) + F.PlaceOnTop(carpet_type, flags = CHANGETURF_INHERIT_AIR) ..() /datum/reagent/carpet/black name = "Liquid Black Carpet" id = "blackcarpet" color = "#363636" - -/datum/reagent/carpet/black/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/black) - ..() + carpet_type = /turf/open/floor/carpet/black /datum/reagent/carpet/blackred name = "Liquid Red Black Carpet" id = "blackredcarpet" color = "#342125" - -/datum/reagent/carpet/blackred/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/blackred) - ..() + carpet_type = /turf/open/floor/carpet/blackred /datum/reagent/carpet/monochrome name = "Liquid Monochrome Carpet" id = "monochromecarpet" color = "#b4b4b4" - -/datum/reagent/carpet/monochrome/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/monochrome) - ..() + carpet_type = /turf/open/floor/carpet/monochrome /datum/reagent/carpet/blue name = "Liquid Blue Carpet" id = "bluecarpet" color = "#1256ff" - -/datum/reagent/carpet/blue/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/blue) - ..() + carpet_type = /turf/open/floor/carpet/blue /datum/reagent/carpet/cyan name = "Liquid Cyan Carpet" id = "cyancarpet" color = "#3acfb9" - -/datum/reagent/carpet/cyan/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/cyan) - ..() + carpet_type = /turf/open/floor/carpet/cyan /datum/reagent/carpet/green name = "Liquid Green Carpet" id = "greencarpet" color = "#619b62" - -/datum/reagent/carpet/green/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/green) - ..() + carpet_type = /turf/open/floor/carpet/green /datum/reagent/carpet/orange name = "Liquid Orange Carpet" id = "orangecarpet" color = "#cc7900" - -/datum/reagent/carpet/orange/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/orange) - ..() + carpet_type = /turf/open/floor/carpet/orange /datum/reagent/carpet/purple name = "Liquid Purple Carpet" id = "purplecarpet" color = "#6d3392" + carpet_type = /turf/open/floor/carpet/purple -/datum/reagent/carpet/purple/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/purple) - ..() /datum/reagent/carpet/red name = "Liquid Red Carpet" id = "redcarpet" color = "#871515" + carpet_type = /turf/open/floor/carpet/red -/datum/reagent/carpet/red/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/red) - ..() /datum/reagent/carpet/royalblack name = "Liquid Royal Black Carpet" id = "royalblackcarpet" color = "#483d05" + carpet_type = /turf/open/floor/carpet/royalblack -/datum/reagent/carpet/royalblack/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/royalblack) - ..() /datum/reagent/carpet/royalblue name = "Liquid Royal Blue Carpet" id = "royalbluecarpet" color = "#24227e" - -/datum/reagent/carpet/royalblue/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet/royalblue) - ..() + carpet_type = /turf/open/floor/carpet/royalblue // Virology virus food chems. diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index c170858d98..36621aa662 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -53,7 +53,7 @@ if(isplatingturf(T)) var/turf/open/floor/plating/F = T if(prob(10 + F.burnt + 5*F.broken)) //broken or burnt plating is more susceptible to being destroyed - F.ScrapeAway() + F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) if(isfloorturf(T)) var/turf/open/floor/F = T if(prob(reac_volume)) diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm index caa2ca7adf..76897b5276 100644 --- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm +++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm @@ -108,7 +108,7 @@ if (levels.len) dest = locate(T.x, T.y, pick(levels)) - T.ChangeTurf(/turf/open/chasm) + T.ChangeTurf(/turf/open/chasm, flags = CHANGETURF_INHERIT_AIR) var/turf/open/chasm/C = T C.set_target(dest) C.drop(user) diff --git a/code/modules/spells/spell_types/conjure.dm b/code/modules/spells/spell_types/conjure.dm index 3ebded7487..38a2d5bddd 100644 --- a/code/modules/spells/spell_types/conjure.dm +++ b/code/modules/spells/spell_types/conjure.dm @@ -31,7 +31,7 @@ if(ispath(summoned_object_type, /turf)) var/turf/O = spawn_place var/N = summoned_object_type - O.ChangeTurf(N) + O.ChangeTurf(N, flags = CHANGETURF_INHERIT_AIR) else var/atom/summoned_object = new summoned_object_type(spawn_place) diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm index 8b8328abbe..d97d466e4d 100644 --- a/code/modules/spells/spell_types/devil.dm +++ b/code/modules/spells/spell_types/devil.dm @@ -234,7 +234,7 @@ dancefloor_exists = FALSE for(var/i in 1 to dancefloor_turfs.len) var/turf/T = dancefloor_turfs[i] - T.ChangeTurf(dancefloor_turfs_types[i]) + T.ChangeTurf(dancefloor_turfs_types[i], flags = CHANGETURF_INHERIT_AIR) else var/list/funky_turfs = RANGE_TURFS(1, user) for(var/turf/closed/solid in funky_turfs) @@ -248,7 +248,7 @@ var/turf/T = t dancefloor_turfs[i] = T dancefloor_turfs_types[i] = T.type - T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b) + T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b, flags = CHANGETURF_INHERIT_AIR) i++ /datum/effect_system/smoke_spread/transparent/dancefloor_devil diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm index d7ff42a9eb..7e094eddda 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm @@ -54,7 +54,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die /datum/reagent/fermi/astral/reaction_turf(turf/T, reac_volume) if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/fakespace) + F.PlaceOnTop(/turf/open/floor/fakespace, flags = CHANGETURF_INHERIT_AIR) ..() /datum/reagent/fermi/astral/reaction_obj(obj/O, reac_volume) From 9f21fca798df0aac5e5b3d62422b12c1d366c049 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 14:18:13 -0800 Subject: [PATCH 012/141] workin on IRV --- code/__DEFINES/citadel_defines.dm | 5 ++ code/controllers/subsystem/ticker.dm | 2 +- code/controllers/subsystem/vote.dm | 77 +++++++++++++++++++++------- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index e3cafd4613..f954abf453 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -119,3 +119,8 @@ //belly sound pref things #define NORMIE_HEARCHECK 4 + +// Voting stuff (move this somewhere else eventually probs) +#define PLURALITY 0 +#define APPROVAL 1 +#define IRV 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index baaa78e56f..9ca252b1dc 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -480,7 +480,7 @@ SUBSYSTEM_DEF(ticker) SSticker.timeLeft = 900 SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) - SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic) + SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic ? PLURALITY : IRV) /datum/controller/subsystem/ticker/Recover() current_state = SSticker.current_state diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index b34713254d..8daf140121 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -1,6 +1,3 @@ -#define PLURALITY 0 -#define APPROVAL 1 - SUBSYSTEM_DEF(vote) name = "Vote" wait = 10 @@ -89,8 +86,23 @@ SUBSYSTEM_DEF(vote) . += option return . +/datum/controller/subsystem/vote/proc/get_result_runoff() + for(var/i in 1 to choices.len) // if it takes more than this something REALLY wrong happened + for(var/ckey in voted) + choices[voted[ckey][1]]++ + var/least_vote = 100000 + var/least_voted + for(var/option in choices) + if(choices[option] > voted.len/2) + return option + else if(choices[option] < least_vote) + least_vote = choices[option] + least_voted = option + for(var/ckey in voted) + voted[ckey] -= least_voted + /datum/controller/subsystem/vote/proc/announce_result() - var/list/winners = get_result() + var/list/winners = vote_system == IRV ? get_result_runoff() : get_result() var/text var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -214,6 +226,14 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote + if(IRV) + if(usr.ckey in voted) + if(vote in voted[usr.ckey]) + voted[usr.ckey] -= vote + else + voted += usr.ckey + voted[usr.ckey] = list() + voted[usr.ckey] += vote return 0 /datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes @@ -314,21 +334,42 @@ SUBSYSTEM_DEF(vote) . += "

Vote: '[question]'

" else . += "

Vote: [capitalize(mode)]

" - . += "

Vote [vote_system == PLURALITY ? "your top choice" : "all that apply"].

" + switch(vote_system) + if(PLURALITY) + . += "

Vote one.

" + if(APPROVAL) + . += "

Vote any number of choices.

" + if(IRV) + . += "

Vote by order of preference. Revoting will demote to the bottom.

" . += "Time Left: [time_remaining] s
    " - for(var/i=1,i<=choices.len,i++) - var/votes = choices[choices[i]] - var/ivotedforthis = FALSE - switch(vote_system) - if(PLURALITY) - ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) - if(APPROVAL) - ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) - if(!votes) - votes = 0 - . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes - if(choice_descs.len >= i) - . += "
  • [choice_descs[i]]
  • " + switch(vote_system) + if(PLURALITY, APPROVAL) + for(var/i=1,i<=choices.len,i++) + var/votes = choices[choices[i]] + var/ivotedforthis = FALSE + switch(vote_system) + if(PLURALITY) + ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) + if(APPROVAL) + ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) + if(!votes) + votes = 0 + . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes + if(choice_descs.len >= i) + . += "
  • [choice_descs[i]]
  • " + if(IRV) + var/list/display_choices = choices.Copy() + if(C.ckey in voted) + for(var/vote in voted[C.ckey]) + display_choices.Cut(vote,vote+1) + . += "
  • [choices[vote]]
  • " // no reasonable way to show votes with IRV + if(choice_descs.len >= vote) + . += "
  • [choice_descs[vote]]
  • " + for(var/choice in display_choices) + var/index = choices.Find(choice) + . += "
  • [choices[index]]
  • " + if(choice_descs.len >= index) + . += "
  • [choice_descs[index]]
  • " . += "

" if(admin) . += "(Cancel Vote) " From 04f82f3153b4eb4f98ed04b28172b50cf9d00314 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 15:48:28 -0800 Subject: [PATCH 013/141] it works --- code/__DEFINES/citadel_defines.dm | 6 +-- code/controllers/subsystem/ticker.dm | 5 ++- code/controllers/subsystem/vote.dm | 65 +++++++++++++++------------- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index f954abf453..7cad6b5be7 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -121,6 +121,6 @@ #define NORMIE_HEARCHECK 4 // Voting stuff (move this somewhere else eventually probs) -#define PLURALITY 0 -#define APPROVAL 1 -#define IRV 2 +#define PLURALITY_VOTING 0 +#define APPROVAL_VOTING 1 +#define INSTANT_RUNOFF_VOTING 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index d676b2df40..cbd7dfdd52 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -480,7 +480,10 @@ SUBSYSTEM_DEF(ticker) SSticker.timeLeft = 900 SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) - SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE,dynamic ? PLURALITY : IRV) + if(dynamic) + SSvote.initiate_vote("dynamic","server",TRUE,INSTANT_RUNOFF_VOTING) + else + SSvote.initiate_vote("roundtype","server",TRUE,PLURALITY_VOTING) /datum/controller/subsystem/ticker/Recover() current_state = SSticker.current_state diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 8daf140121..6ea13c832d 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -10,7 +10,7 @@ SUBSYSTEM_DEF(vote) var/started_time = null var/time_remaining = 0 var/mode = null - var/vote_system = PLURALITY + var/vote_system = PLURALITY_VOTING var/question = null var/list/choices = list() var/list/choice_descs = list() // optional descriptions @@ -87,22 +87,29 @@ SUBSYSTEM_DEF(vote) return . /datum/controller/subsystem/vote/proc/get_result_runoff() - for(var/i in 1 to choices.len) // if it takes more than this something REALLY wrong happened + var/already_lost_runoff = list() + for(var/n in 1 to choices.len) // if it takes more than this something REALLY wrong happened for(var/ckey in voted) - choices[voted[ckey][1]]++ + choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying var/least_vote = 100000 var/least_voted - for(var/option in choices) + for(var/i in 1 to choices.len) + var/option = choices[i] if(choices[option] > voted.len/2) - return option - else if(choices[option] < least_vote) + message_admins("[option] has a majority, returning...") + return list(option) + else if(choices[option] < least_vote && !(option in already_lost_runoff)) least_vote = choices[option] - least_voted = option + least_voted = i + message_admins("[choices[least_voted]] lost the runoff, running again...") + already_lost_runoff += choices[least_voted] for(var/ckey in voted) voted[ckey] -= least_voted + for(var/option in choices) + choices[option] = 0 /datum/controller/subsystem/vote/proc/announce_result() - var/list/winners = vote_system == IRV ? get_result_runoff() : get_result() + var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_result_runoff() : get_result() var/text var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -202,7 +209,7 @@ SUBSYSTEM_DEF(vote) return 0 if(vote && vote >= 1 && vote <= choices.len) switch(vote_system) - if(PLURALITY) + if(PLURALITY_VOTING) if(usr.ckey in voted) choices[choices[voted[usr.ckey]]]-- voted[usr.ckey] = vote @@ -213,7 +220,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = vote choices[choices[vote]]++ //check this return vote - if(APPROVAL) + if(APPROVAL_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -226,7 +233,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote - if(IRV) + if(INSTANT_RUNOFF_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -236,7 +243,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] += vote return 0 -/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes +/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, hideresults, votesystem = PLURALITY_VOTING)//CIT CHANGE - adds hideresults argument to votes to allow for obfuscated votes vote_system = votesystem if(!mode) if(started_time) @@ -335,41 +342,37 @@ SUBSYSTEM_DEF(vote) else . += "

Vote: [capitalize(mode)]

" switch(vote_system) - if(PLURALITY) + if(PLURALITY_VOTING) . += "

Vote one.

" - if(APPROVAL) + if(APPROVAL_VOTING) . += "

Vote any number of choices.

" - if(IRV) + if(INSTANT_RUNOFF_VOTING) . += "

Vote by order of preference. Revoting will demote to the bottom.

" . += "Time Left: [time_remaining] s
    " switch(vote_system) - if(PLURALITY, APPROVAL) + if(PLURALITY_VOTING, APPROVAL_VOTING) for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] var/ivotedforthis = FALSE switch(vote_system) - if(PLURALITY) + if(PLURALITY_VOTING) ivotedforthis = ((C.ckey in voted) && (voted[C.ckey] == i)) - if(APPROVAL) + if(APPROVAL_VOTING) ivotedforthis = ((C.ckey in voted) && (i in voted[C.ckey])) if(!votes) votes = 0 . += "
  • [ivotedforthis ? "" : ""][choices[i]] ([obfuscated ? (admin ? "??? ([votes])" : "???") : votes] votes)[ivotedforthis ? "" : ""]
  • " // CIT CHANGE - adds obfuscated votes if(choice_descs.len >= i) . += "
  • [choice_descs[i]]
  • " - if(IRV) - var/list/display_choices = choices.Copy() - if(C.ckey in voted) - for(var/vote in voted[C.ckey]) - display_choices.Cut(vote,vote+1) - . += "
  • [choices[vote]]
  • " // no reasonable way to show votes with IRV - if(choice_descs.len >= vote) - . += "
  • [choice_descs[vote]]
  • " - for(var/choice in display_choices) - var/index = choices.Find(choice) - . += "
  • [choices[index]]
  • " - if(choice_descs.len >= index) - . += "
  • [choice_descs[index]]
  • " + if(INSTANT_RUNOFF_VOTING) + for(var/i=1,i<=choices.len,i++) + var/vote = ((C.ckey in voted) ? (voted[C.ckey].Find(i)) : 0) + if(vote) + . += "
  • [choices[i]] ([vote])
  • " + else + . += "
  • [choices[i]]
  • " + if(choice_descs.len >= i) + . += "
  • [choice_descs[i]]
  • " . += "

" if(admin) . += "(Cancel Vote) " From 5ef7d9cbf736865999dfc167d2dfc5db72d7786b Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 16:09:40 -0800 Subject: [PATCH 014/141] why did i not have revs as conversion --- code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm | 2 +- code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 8d9d14b473..f014504a68 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -95,7 +95,7 @@ requirements = list(101,101,70,40,40,40,40,40,40,40) high_population_requirement = 40 flags = HIGHLANDER_RULESET - property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2, "conversion" = 1) var/required_heads_of_staff = 3 var/finished = FALSE var/datum/team/revolution/revolution diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 1abdcef3f1..f7cf9cd78e 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -378,7 +378,7 @@ flags = HIGHLANDER_RULESET // I give up, just there should be enough heads with 35 players... minimum_players = 35 - property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2) + property_weights = list("trust" = -3, "chaos" = 5, "extended" = -5, "valid" = 2, "conversion" = 1) var/datum/team/revolution/revolution var/finished = FALSE From f25d75fed9c205c178382ca1f1f80fe3b292503e Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 16:29:24 -0800 Subject: [PATCH 015/141] thanks linter --- code/controllers/subsystem/vote.dm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 6ea13c832d..ed589ca3c8 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -366,7 +366,12 @@ SUBSYSTEM_DEF(vote) . += "
  • [choice_descs[i]]
  • " if(INSTANT_RUNOFF_VOTING) for(var/i=1,i<=choices.len,i++) - var/vote = ((C.ckey in voted) ? (voted[C.ckey].Find(i)) : 0) + var/vote = 0 + //linter yells at me if i use Find here + if(C.ckey in voted) + for(var/n=1,n<=voted[C.ckey].len,n++) + if(voted[C.ckey][n] == i) + vote = n if(vote) . += "
  • [choices[i]] ([vote])
  • " else From 94b7a48bbcec4bace70b962f8302f3ed938e3251 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 18:29:49 -0800 Subject: [PATCH 016/141] aaa --- code/controllers/subsystem/vote.dm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index ed589ca3c8..b8068215cf 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -365,13 +365,9 @@ SUBSYSTEM_DEF(vote) if(choice_descs.len >= i) . += "
  • [choice_descs[i]]
  • " if(INSTANT_RUNOFF_VOTING) + var/list/myvote = voted[C.ckey] for(var/i=1,i<=choices.len,i++) - var/vote = 0 - //linter yells at me if i use Find here - if(C.ckey in voted) - for(var/n=1,n<=voted[C.ckey].len,n++) - if(voted[C.ckey][n] == i) - vote = n + var/vote = (myvote ? (myvote.Find(i)) : 0) if(vote) . += "
  • [choices[i]] ([vote])
  • " else From fab65a3dbc41accdd4782dfb67ac92544563ce11 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 17 Dec 2019 20:12:23 -0800 Subject: [PATCH 017/141] actually condorcet not IRV --- code/__DEFINES/citadel_defines.dm | 2 +- code/controllers/subsystem/ticker.dm | 2 +- code/controllers/subsystem/vote.dm | 41 +++++++++++----------------- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 7cad6b5be7..55526eabc1 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -123,4 +123,4 @@ // Voting stuff (move this somewhere else eventually probs) #define PLURALITY_VOTING 0 #define APPROVAL_VOTING 1 -#define INSTANT_RUNOFF_VOTING 2 +#define RANKED_CHOICE_VOTING 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index cbd7dfdd52..cad5798a4c 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -481,7 +481,7 @@ SUBSYSTEM_DEF(ticker) SSticker.modevoted = TRUE var/dynamic = CONFIG_GET(flag/dynamic_voting) if(dynamic) - SSvote.initiate_vote("dynamic","server",TRUE,INSTANT_RUNOFF_VOTING) + SSvote.initiate_vote("dynamic","server",TRUE,RANKED_CHOICE_VOTING) else SSvote.initiate_vote("roundtype","server",TRUE,PLURALITY_VOTING) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index b8068215cf..42bd00d4af 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -86,30 +86,21 @@ SUBSYSTEM_DEF(vote) . += option return . -/datum/controller/subsystem/vote/proc/get_result_runoff() - var/already_lost_runoff = list() - for(var/n in 1 to choices.len) // if it takes more than this something REALLY wrong happened - for(var/ckey in voted) - choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying - var/least_vote = 100000 - var/least_voted - for(var/i in 1 to choices.len) - var/option = choices[i] - if(choices[option] > voted.len/2) - message_admins("[option] has a majority, returning...") - return list(option) - else if(choices[option] < least_vote && !(option in already_lost_runoff)) - least_vote = choices[option] - least_voted = i - message_admins("[choices[least_voted]] lost the runoff, running again...") - already_lost_runoff += choices[least_voted] - for(var/ckey in voted) - voted[ckey] -= least_voted - for(var/option in choices) - choices[option] = 0 +/datum/controller/subsystem/vote/proc/calculate_condorcet_votes() + for(var/ckey in voted) + var/list/this_vote = voted[ckey] + for(var/a in 1 to choices.len) + for(var/b in a+1 to choices.len) + var/vote_sgn = SIGN(this_vote.Find(a)-this_vote.Find(b)) + if(vote_sgn==-1) + choices[choices[a]]++ + else if(vote_sgn==1) + choices[choices[b]]++ /datum/controller/subsystem/vote/proc/announce_result() - var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_result_runoff() : get_result() + if(vote_system == RANKED_CHOICE_VOTING) + calculate_condorcet_votes() + var/list/winners = get_result() var/text var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -233,7 +224,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote - if(INSTANT_RUNOFF_VOTING) + if(RANKED_CHOICE_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -346,7 +337,7 @@ SUBSYSTEM_DEF(vote) . += "

    Vote one.

    " if(APPROVAL_VOTING) . += "

    Vote any number of choices.

    " - if(INSTANT_RUNOFF_VOTING) + if(RANKED_CHOICE_VOTING) . += "

    Vote by order of preference. Revoting will demote to the bottom.

    " . += "Time Left: [time_remaining] s