Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
41a8a70
Adds support for dynamic mathing
Xoxeyos May 5, 2020
50d3bd0
Adds Dynamic Main Files.
Xoxeyos May 5, 2020
0c81903
Adds Dynamic loading to yogstation.dme
Xoxeyos May 5, 2020
5dea2fc
Probably adds dynamic related changes.
Xoxeyos May 5, 2020
05c0882
Fixes code I didn't add, won't fix my retardation.
Xoxeyos May 5, 2020
e5aae0c
Adds "/datum/game_mode/proc/admin_panel()" because it's apparently im…
Xoxeyos May 5, 2020
de20857
Adds dynamic related code.
Xoxeyos May 5, 2020
9f58dd0
Adds more dynamic related code.
Xoxeyos May 5, 2020
2e2268c
Fixes error: possible unreachable code here on line 313
Xoxeyos May 5, 2020
7ba5e8d
Fixes copy and paste error.
Xoxeyos May 5, 2020
51d8a45
Adds a testing change to fix the lint
Xoxeyos May 5, 2020
2732704
Undos paranthesis
Xoxeyos May 5, 2020
9af97c6
LintFixTry#2
Xoxeyos May 5, 2020
b293c36
Merge branch 'master' into Dynamic#1
SomeguyManperson May 6, 2020
32356fd
Merge branch 'master' into Dynamic#1
fluffe9911 May 7, 2020
180e145
Merge branch 'master' into Dynamic#1
Xoxeyos May 7, 2020
41f5ec2
Merge branch 'master' into Dynamic#1
Xoxeyos May 7, 2020
df45623
Merge branch 'master' into Dynamic#1
Xoxeyos May 8, 2020
96c2e07
Merge branch 'master' into Dynamic#1
Xoxeyos May 8, 2020
05e7218
Merge branch 'master' into Dynamic#1
Xoxeyos May 8, 2020
3d84074
Merge branch 'master' into Dynamic#1
Xoxeyos May 8, 2020
bff727d
Merge branch 'master' into Dynamic#1
Xoxeyos May 8, 2020
9bb0cea
Merge branch 'master' into Dynamic#1
Xoxeyos May 8, 2020
9d20676
Merge branch 'master' into Dynamic#1
fluffe9911 May 9, 2020
bcf234e
Merge branch 'master' into Dynamic#1
Xoxeyos May 9, 2020
11ac85e
Merge branch 'master' into Dynamic#1
Xoxeyos May 9, 2020
71bd0f0
Merge branch 'master' into Dynamic#1
fluffe9911 May 10, 2020
bfa7bbe
Merge branch 'master' into Dynamic#1
Xoxeyos May 11, 2020
d08066f
Adds Shadowling
Xoxeyos May 14, 2020
64abf57
adds a slash
Xoxeyos May 14, 2020
3b23b3f
adds some logging
SomeguyManperson May 14, 2020
a06fcf6
Adds IMMERSION
Xoxeyos May 14, 2020
bd16eea
FIXES IMMERSION
Xoxeyos May 14, 2020
4ddeb49
Adds Mindshield Implants for Dynamic
Xoxeyos May 16, 2020
c70dd8e
Adds the mindshield implant into dynamic
Xoxeyos May 16, 2020
574275c
Adds the mindshield stuff yadayadayda
Xoxeyos May 16, 2020
f77c9f3
adds another slash
Xoxeyos May 16, 2020
bf9b2ac
removes said slash
Xoxeyos May 16, 2020
ef02015
test addes imp_ before mindshield on line 427
Xoxeyos May 16, 2020
e9bbb09
redo
Xoxeyos May 16, 2020
187504f
test
Xoxeyos May 16, 2020
9de54ee
Going to try and do this again #1
Xoxeyos May 16, 2020
fec6a55
syndie_kit/mindshield/
Xoxeyos May 16, 2020
94088cd
gets rid of an error
Xoxeyos May 16, 2020
8d083b4
renames to imp_mindshield
Xoxeyos May 16, 2020
3d2d0cb
Maybe I'm just super retarded.
Xoxeyos May 16, 2020
2da7fa7
v
Xoxeyos May 16, 2020
ee82252
#include "code\game\objects\items\implants\implant_mindshieldtot.dm"
Xoxeyos May 16, 2020
29fd811
oops
Xoxeyos May 16, 2020
7dc5515
recompile
Xoxeyos May 16, 2020
6e4729b
Part of getting rid of weights, relies on dice rolls
Xoxeyos May 18, 2020
55de676
Adds dice roll, adds the ability for clock cult to roll
Xoxeyos May 18, 2020
630a7c2
Readjusts weight and costs, no more weight
Xoxeyos May 18, 2020
4dbf28e
ahem fuck you travis or whatever the hell your name is - recompile
Xoxeyos May 18, 2020
9d46761
Oh god oh fuck clock cult cost 0 for a while, oh god oh fuck meteors …
Xoxeyos May 19, 2020
743e50a
recompile
Xoxeyos May 19, 2020
2ab746f
Rev Fix
Xoxeyos May 19, 2020
7a5e451
Allows more midrounds to play
Xoxeyos May 19, 2020
6a97e02
Clockwork additions and whatnot
Xoxeyos May 19, 2020
fdf099d
Adds Vampire, and some changes to the requirements, and whatnot.
Xoxeyos May 23, 2020
fd98fda
Fixed Jobs to Roles
Xoxeyos May 23, 2020
419600a
Adds Vampire to Late Join
Xoxeyos May 23, 2020
242ceca
Adds vampire cooldown to roundstart
Xoxeyos May 24, 2020
c07129c
Adds Traitor_Ruleset to Vampire
Xoxeyos May 24, 2020
090ca87
Adds Vamps to midround
Xoxeyos May 24, 2020
6a8810f
recompile
Xoxeyos May 24, 2020
42e87b3
Shadowling Modification
Xoxeyos May 24, 2020
16582ea
Revs are now under the flag TRAITOR_RULESET, shadowling change, attem…
Xoxeyos May 25, 2020
e549d7a
Makes mindshield limited stock, now costs 1 tc, very small chance to …
Xoxeyos May 26, 2020
babebe4
Adds cargo crate discounts
Xoxeyos May 26, 2020
fb3dec1
Adds the party crate to discount
Xoxeyos May 26, 2020
ebccce6
Adds Zombies to the midround
Xoxeyos May 26, 2020
27b1445
Recompile
Xoxeyos May 26, 2020
7b0b176
FUCK YOU RECOMPILE ALREADY
Xoxeyos May 26, 2020
990a106
recompile
Xoxeyos May 26, 2020
4c4712a
Jungle Fever can now roll.
Xoxeyos May 27, 2020
d87f939
Only need one vampire candidate now.
Xoxeyos May 28, 2020
be9d8e9
Fix
Xoxeyos May 31, 2020
50d0627
Ah shit it seems you're utterly fucked.
Xoxeyos May 31, 2020
f452ece
Update dynamic_rulesets_roundstart.dm
Xoxeyos Jun 3, 2020
bcbc917
No Highpop req for shadowling
Xoxeyos Jun 3, 2020
b2dcd36
Adds Darkspawn
Xoxeyos Jun 4, 2020
ba1db11
Adds some logging.
Xoxeyos Jun 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions code/__DEFINES/maths.dm
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,12 @@
region_y2["[i]"] = TRUE

return list(region_x1 & region_x2, region_y1 & region_y2)

#define EXP_DISTRIBUTION(desired_mean) ( -(1/(1/desired_mean)) * log(rand(1, 1000) * 0.001) )

#define LORENTZ_DISTRIBUTION(x, s) ( s*tan(TODEGREES(PI*(rand()-0.5))) + x )
#define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 )

#define RULE_OF_THREE(a, b, x) ((a*x)/b)

// )
7 changes: 7 additions & 0 deletions code/__HELPERS/roundend.dm
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,13 @@
//ignore this comment, it fixes the broken sytax parsing caused by the " above
else
parts += "[GLOB.TAB]<i>Nobody died this shift!</i>"
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
parts += "[FOURSPACES]Threat left: [mode.threat]" //yes
parts += "[FOURSPACES]Executed rules:"
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost] threat"
return parts.Join("<br>")

/client/proc/roundend_report_file()
Expand Down
752 changes: 752 additions & 0 deletions code/game/gamemodes/dynamic/dynamic.dm

Large diffs are not rendered by default.

180 changes: 180 additions & 0 deletions code/game/gamemodes/dynamic/dynamic_rulesets.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/datum/dynamic_ruleset
/// For admin logging and round end screen.
var/name = ""
/// For admin logging and round end screen, do not change this unless making a new rule type.
var/ruletype = ""
/// If set to TRUE, the rule won't be discarded after being executed, and dynamic will call rule_process() every time it ticks.
var/persistent = FALSE
/// If set to TRUE, dynamic mode will be able to draft this ruleset again later on. (doesn't apply for roundstart rules)
var/repeatable = FALSE
/// If set higher than 0 decreases weight by itself causing the ruleset to appear less often the more it is repeated.
var/repeatable_weight_decrease = 2
/// List of players that are being drafted for this rule
var/list/mob/candidates = list()
/// List of players that were selected for this rule
var/list/datum/mind/assigned = list()
/// Preferences flag such as ROLE_WIZARD that need to be turned on for players to be antag
var/antag_flag = null
/// The antagonist datum that is assigned to the mobs mind on ruleset execution.
var/datum/antagonist/antag_datum = null
/// The required minimum account age for this ruleset.
var/minimum_required_age = 7
/// If set, and config flag protect_roles_from_antagonist is false, then the rule will not pick players from these roles.
var/list/protected_roles = list()
/// If set, rule will deny candidates from those roles always.
var/list/restricted_roles = list()
/// If set, rule will only accept candidates from those roles, IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/list/exclusive_roles = list()
/// If set, there needs to be a certain amount of players doing those roles (among the players who won't be drafted) for the rule to be drafted IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/list/enemy_roles = list()
/// If enemy_roles was set, this is the amount of enemy job workers needed per threat_level range (0-10,10-20,etc) IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/required_enemies = list(1,1,0,0,0,0,0,0,0,0)
/// The rule needs this many candidates (post-trimming) to be executed (example: Cult needs 4 players at round start)
var/required_candidates = 0
/// 1 -> 9, probability for this rule to be picked against other rules
var/weight = 5
/// Threat cost for this rule, this is decreased from the mode's threat when the rule is executed.
var/cost = 0
/// A flag that determines how the ruleset is handled
/// HIGHLANDER_RULESET are rulesets can end the round.
/// TRAITOR_RULESET and MINOR_RULESET can't end the round and have no difference right now.
var/flags = 0
/// Pop range per requirement. If zero defaults to mode's pop_per_requirement.
var/pop_per_requirement = 0
/// Requirements are the threat level requirements per pop range.
/// With the default values, The rule will never get drafted below 10 threat level (aka: "peaceful extended"), and it requires a higher threat level at lower pops.
var/list/requirements = list(40,30,20,10,10,10,10,10,10,10)
/// An alternative, static requirement used instead when pop is over mode's high_pop_limit.
var/high_population_requirement = 10
/// Reference to the mode, use this instead of SSticker.mode.
var/datum/game_mode/dynamic/mode = null
/// If a role is to be considered another for the purpose of banning.
var/antag_flag_override = null
/// If a ruleset type which is in this list has been executed, then the ruleset will not be executed.
var/list/blocking_rules = list()
/// The minimum amount of players required for the rule to be considered.
var/minimum_players = 0
/// The maximum amount of players required for the rule to be considered.
/// Anything below zero or exactly zero is ignored.
var/maximum_players = 0


/datum/dynamic_ruleset/New()
..()
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_roles += protected_roles
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
restricted_roles += "Assistant"

if (istype(SSticker.mode, /datum/game_mode/dynamic))
mode = SSticker.mode
else if (GLOB.master_mode != "dynamic") // This is here to make roundstart forced ruleset function.
qdel(src)


/datum/dynamic_ruleset/roundstart // One or more of those drafted at roundstart
ruletype = "Roundstart"
/// Delay for when execute will get called from the time of post_setup.
/// Make sure your ruleset works with execute being called during the game when using this.
var/delay = 0

// Can be drafted when a player joins the server
/datum/dynamic_ruleset/latejoin
ruletype = "Latejoin"

/// By default, a rule is acceptable if it satisfies the threat level/population requirements.
/// If your rule has extra checks, such as counting security officers, do that in ready() instead
/datum/dynamic_ruleset/proc/acceptable(population = 0, threat_level = 0)
pop_per_requirement = pop_per_requirement > 0 ? pop_per_requirement : (mode.pop_per_requirement > 0 ? mode.pop_per_requirement : 6) //sorry ike

if(minimum_players > population)
return FALSE
if(maximum_players > 0 && population > maximum_players)
return FALSE
if (population >= GLOB.dynamic_high_pop_limit)
return (threat_level >= high_population_requirement)
else
var/indice_pop = min(10,round(population/pop_per_requirement)+1) //fuck
return (threat_level >= requirements[indice_pop])

/// This is called if persistent variable is true everytime SSTicker ticks.
/datum/dynamic_ruleset/proc/rule_process()
return

/// Called on game mode pre_setup for roundstart rulesets.
/// Do everything you need to do before job is assigned here.
/// IMPORTANT: ASSIGN special_role HERE
/datum/dynamic_ruleset/proc/pre_execute()
return TRUE

/// Called on post_setup on roundstart and when the rule executes on midround and latejoin.
/// Give your candidates or assignees equipment and antag datum here.
/datum/dynamic_ruleset/proc/execute()
for(var/datum/mind/M in assigned)
M.add_antag_datum(antag_datum)
return TRUE

/// Here you can perform any additional checks you want. (such as checking the map etc)
/// Remember that on roundstart no one knows what their job is at this point.
/// IMPORTANT: If ready() returns TRUE, that means pre_execute() or execute() should never fail!
/datum/dynamic_ruleset/proc/ready(forced = 0)
if (required_candidates > candidates.len)
return FALSE
return TRUE

/// Gets weight of the ruleset
/// Note that this decreases weight if repeatable is TRUE and repeatable_weight_decrease is higher than 0
/// Note: If you don't want repeatable rulesets to decrease their weight use the weight variable directly
/datum/dynamic_ruleset/proc/get_weight()
if(repeatable && weight > 1 && repeatable_weight_decrease > 0)
for(var/datum/dynamic_ruleset/DR in mode.executed_rules)
if(istype(DR, type))
weight = max(weight-repeatable_weight_decrease,1)
return weight

/// Here you can remove candidates that do not meet your requirements.
/// This means if their job is not correct or they have disconnected you can remove them from candidates here.
/// Usually this does not need to be changed unless you need some specific requirements from your candidates.
/datum/dynamic_ruleset/proc/trim_candidates()
return

/// Set mode result and news report here.
/// Only called if ruleset is flagged as HIGHLANDER_RULESET
/datum/dynamic_ruleset/proc/round_result()

/// Checks if round is finished, return true to end the round.
/// Only called if ruleset is flagged as HIGHLANDER_RULESET
/datum/dynamic_ruleset/proc/check_finished()
return FALSE

//////////////////////////////////////////////
// //
// ROUNDSTART RULESETS //
// //
//////////////////////////////////////////////

/// Checks if candidates are connected and if they are banned or don't want to be the antagonist.
/datum/dynamic_ruleset/roundstart/trim_candidates()
for(var/mob/dead/new_player/P in candidates)
if (!P.client || !P.mind) // Are they connected?
candidates.Remove(P)
continue
if(!mode.check_age(P.client, minimum_required_age))
candidates.Remove(P)
continue
if(P.mind.special_role) // We really don't want to give antag to an antag.
candidates.Remove(P)
continue
if(antag_flag_override)
if(!(antag_flag_override in P.client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag_override, ROLE_SYNDICATE)))
candidates.Remove(P)
continue
else
if(!(antag_flag in P.client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag, ROLE_SYNDICATE)))
candidates.Remove(P)
continue

/// Do your checks if the ruleset is ready to be executed here.
/// Should ignore certain checks if forced is TRUE
/datum/dynamic_ruleset/roundstart/ready(forced = FALSE)
return ..()
137 changes: 137 additions & 0 deletions code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//////////////////////////////////////////////
// //
// LATEJOIN RULESETS //
// //
//////////////////////////////////////////////

/datum/dynamic_ruleset/latejoin/trim_candidates()
for(var/mob/P in candidates)
if (!P.client || !P.mind || !P.mind.assigned_role) // Are they connected?
candidates.Remove(P)
continue
if(!mode.check_age(P.client, minimum_required_age))
candidates.Remove(P)
continue
if(antag_flag_override)
if(!(antag_flag_override in P.client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag_override, ROLE_SYNDICATE)))
candidates.Remove(P)
continue
else
if(!(antag_flag in P.client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag, ROLE_SYNDICATE)))
candidates.Remove(P)
continue
if (P.mind.assigned_role in restricted_roles) // Does their job allow for it?
candidates.Remove(P)
continue
if ((exclusive_roles.len > 0) && !(P.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job?
candidates.Remove(P)
continue

/datum/dynamic_ruleset/latejoin/ready(forced = 0)
if (!forced)
var/job_check = 0
if (enemy_roles.len > 0)
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
if (M.stat == DEAD)
continue // Dead players cannot count as opponents
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles) && (!(M in candidates) || (M.mind.assigned_role in restricted_roles)))
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it

var/threat = round(mode.threat_level/10)
if (job_check < required_enemies[threat])
return FALSE
return ..()

/datum/dynamic_ruleset/latejoin/execute()
var/mob/M = pick(candidates)
assigned += M.mind
M.mind.special_role = antag_flag
M.mind.add_antag_datum(antag_datum)
return TRUE

//////////////////////////////////////////////
// //
// SYNDICATE TRAITORS //
// //
//////////////////////////////////////////////

/datum/dynamic_ruleset/latejoin/infiltrator
name = "Syndicate Infiltrator"
antag_datum = /datum/antagonist/traitor
antag_flag = ROLE_TRAITOR
protected_roles = list("Security Officer", "Warden", "Head of Personnel", "Detective", "Head of Security", "Captain")
restricted_roles = list("AI","Cyborg")
required_candidates = 1
weight = 1
cost = 5
requirements = list(40,30,20,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
flags = TRAITOR_RULESET

//////////////////////////////////////////////
// //
// REVOLUTIONARY PROVOCATEUR //
// //
//////////////////////////////////////////////

/datum/dynamic_ruleset/latejoin/provocateur
name = "Provocateur"
antag_datum = /datum/antagonist/rev/head
antag_flag = ROLE_REV_HEAD
antag_flag_override = ROLE_REV
restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director")
enemy_roles = list("AI", "Cyborg", "Security Officer","Detective","Head of Security", "Captain", "Warden")
required_enemies = list(2,2,1,1,1,1,1,0,0,0)
required_candidates = 1
weight = 1
cost = 20
requirements = list(80,75,60,60,55,50,40,30,20,20)
high_population_requirement = 50
flags = HIGHLANDER_RULESET
var/required_heads = 3

/datum/dynamic_ruleset/latejoin/provocateur/ready(forced=FALSE)
if (forced)
required_heads = 1
if(!..())
return FALSE
var/head_check = 0
for(var/mob/player in mode.current_players[CURRENT_LIVING_PLAYERS])
if (player.mind.assigned_role in GLOB.command_positions)
head_check++
return (head_check >= required_heads)

/datum/dynamic_ruleset/latejoin/provocateur/execute()
var/mob/M = pick(candidates)
assigned += M.mind
M.mind.special_role = antag_flag
var/datum/antagonist/rev/head/new_head = new()
new_head.give_flash = TRUE
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
new_head = M.mind.add_antag_datum(new_head)
new_head.rev_team.max_headrevs = 1 // Only one revhead if it is latejoin.
return TRUE


//////////////////////////////////////////////
// //
// VAMPIRE //
// //
//////////////////////////////////////////////

/datum/dynamic_ruleset/latejoin/vampire
name = "Vampiric Infiltrator"
antag_flag = ROLE_VAMPIRE
antag_datum = /datum/antagonist/vampire
protected_roles = list("Head of Security", "Captain", "Security Officer", "Chaplain", "Detective", "Warden", "Head of Personnel")
restricted_roles = list("AI", "Cyborg")
required_candidates = 3
weight = 1
cost = 15
requirements = list(80,70,60,50,50,45,30,30,20,25)
minimum_players = 30
repeatable = TRUE
flags = TRAITOR_RULESET

Loading