diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 5581d71080..b38eb98b14 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -16,6 +16,7 @@
#define DISABLE_ARRIVALRATTLE (1<<13)
#define COMBOHUD_LIGHTING (1<<14)
#define SOUND_BARK (1<<15)
+#define NO_ANTAG (1<<16)
#define DEADMIN_ALWAYS (1<<0)
#define DEADMIN_ANTAGONIST (1<<1)
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 3204a39b89..e08a8de417 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -44,15 +44,12 @@
#define ROLE_GHOSTCAFE "ghostcafe"
#define ROLE_MINOR_ANTAG "minorantag"
#define ROLE_RESPAWN "respawnsystem"
-/// Not an actual antag. Lets players force all antags off.
-#define ROLE_NO_ANTAGONISM "NO_ANTAGS"
//Define for disabling individual antagonists for dynamic
-#define HAS_ANTAG_PREF(C,ROLE) (!(ROLE_NO_ANTAGONISM in C.prefs.be_special) && (ROLE in C.prefs.be_special))
+#define HAS_ANTAG_PREF(C,ROLE) (!(NO_ANTAG & C.prefs.toggles) && (ROLE in C.prefs.be_special))
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
//(in game days played) to play that role
GLOBAL_LIST_INIT(special_roles, list(
- ROLE_NO_ANTAGONISM,
ROLE_TRAITOR = /datum/game_mode/traitor,
ROLE_BROTHER = /datum/game_mode/traitor/bros,
ROLE_OPERATIVE = /datum/game_mode/nuclear,
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm
index 30004a3b69..b742f6f36c 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm
@@ -210,10 +210,6 @@
candidates.Remove(candidate_player)
continue
- if(ROLE_NO_ANTAGONISM in candidate_player.client.prefs.be_special)
- candidates.Remove(candidate_player)
- continue
-
if(antag_flag_override)
if(!(HAS_ANTAG_PREF(candidate_player.client, antag_flag_override)))
candidates.Remove(candidate_player)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
index a719ec6198..4dbe7a4387 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
@@ -14,8 +14,6 @@
candidates.Remove(P)
else if((exclusive_roles.len > 0) && !(P.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job?
candidates.Remove(P)
- else if(ROLE_NO_ANTAGONISM in P.client.prefs.be_special)
- candidates.Remove(P)
else if(antag_flag_override)
if(!(HAS_ANTAG_PREF(P.client, antag_flag_override)))
candidates.Remove(P)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
index 601848c22c..b6de6c300a 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
@@ -46,9 +46,6 @@
if(!mode.check_age(M.client, minimum_required_age))
trimmed_list.Remove(M)
continue
- if(ROLE_NO_ANTAGONISM in M.client.prefs.be_special)
- trimmed_list.Remove(M)
- continue
if(antag_flag_override)
if(!(HAS_ANTAG_PREF(M.client, antag_flag_override)))
trimmed_list.Remove(M)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index df1b0a701a..12dfc92cc4 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -348,8 +348,9 @@
var/list/curr_tickets = list() //how many tickets someone has for *this* antag roll, so with the free tickets
var/list/datum/mind/insufficient = list() //who got cucked out of an antag roll due to not having *any* tickets
for(var/datum/mind/M in candidates)
+ var/weight = clamp(candidates[M], 0, 1)
var/mind_ckey = ckey(M.key)
- var/can_spend = min(prev_tickets[mind_ckey], additional_tickets) //they can only spend up to config/max_tickets_per_roll
+ var/can_spend = min(prev_tickets[mind_ckey], additional_tickets * weight) //they can only spend up to config/max_tickets_per_roll
var/amount = can_spend + free_tickets //but they get config/default_antag_tickets for free
if(amount <= 0) //if they don't have any
insufficient += M //too bad!
@@ -425,10 +426,11 @@
for(var/mob/dead/new_player/player in players)
if(player.client && player.ready == PLAYER_READY_TO_PLAY)
- if((role in player.client.prefs.be_special) && !(ROLE_NO_ANTAGONISM in player.client.prefs.be_special))
+ if(HAS_ANTAG_PREF(player.client, role))
if(!jobban_isbanned(player, ROLE_SYNDICATE) && !QDELETED(player) && !jobban_isbanned(player, role) && !QDELETED(player)) //Nodrak/Carn: Antag Job-bans
if(age_check(player.client)) //Must be older than the minimum age
candidates += player.mind // Get a list of all the people who want to be the antagonist for this round
+ candidates[player.mind] = player.client.prefs.be_special[role]
if(restricted_jobs)
for(var/datum/mind/player in candidates)
@@ -449,35 +451,11 @@
if(player.assigned_role == job)
drafted -= player
- drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie
-
- while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates
- if(drafted.len > 0)
- applicant = pick(drafted)
- if(applicant)
- candidates += applicant
- drafted.Remove(applicant)
-
- else // Not enough scrubs, ABORT ABORT ABORT
- break
-
- if(restricted_jobs)
- for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist
- for(var/job in restricted_jobs)
- if(player.assigned_role == job)
- drafted -= player
-
- drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie
-
- while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates
- if(drafted.len > 0)
- applicant = pick(drafted)
- if(applicant)
- candidates += applicant
- drafted.Remove(applicant)
-
- else // Not enough scrubs, ABORT ABORT ABORT
- break
+ while(candidates.len < recommended_enemies && length(drafted)) // Pick randomlly just the number of people we need and add them to our list of candidates
+ applicant = pick_n_take(drafted)
+ if(applicant)
+ candidates += applicant
+ candidates[applicant] = 0
return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies
// recommended_enemies if the number of people with that role set to yes is less than recomended_enemies,
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 1df5d125f7..622f789870 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1005,11 +1005,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "You are banned from antagonist roles."
src.be_special = list()
+ dat += "DISABLE ALL ANTAGONISM [(toggles & NO_ANTAG) ? "YES" : "NO"]
"
for (var/i in GLOB.special_roles)
- if(i == ROLE_NO_ANTAGONISM)
- dat += "DISABLE ALL ANTAGONISM [(i in be_special) ? "YES" : "NO"]
"
- continue
if(jobban_isbanned(user, i))
dat += "Be [capitalize(i)]: BANNED
"
else
@@ -1022,7 +1020,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(days_remaining)
dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS]
"
else
- dat += "Be [capitalize(i)]: [(i in be_special) ? "Enabled" : "Disabled"]
"
+ var/enabled_text = ""
+ if(i in be_special)
+ if(be_special[i] >= 1)
+ enabled_text = "Enabled"
+ else
+ enabled_text = "Low"
+ else
+ enabled_text = "Disabled"
+ dat += "Be [capitalize(i)]: [enabled_text]
"
dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
"
dat += "
"
@@ -2936,12 +2942,19 @@ GLOBAL_LIST_EMPTY(preferences_datums)
deadmin ^= DEADMIN_POSITION_SILICON
//
+ if("disable_antag")
+ toggles ^= NO_ANTAG
+
if("be_special")
var/be_special_type = href_list["be_special_type"]
if(be_special_type in be_special)
- be_special -= be_special_type
+ if(be_special[be_special_type] >= 1)
+ be_special -= be_special_type
+ else
+ be_special[be_special_type] = 1
else
be_special += be_special_type
+ be_special[be_special_type] = 0
if("name")
be_random_name = !be_random_name
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 249dbba45f..92deb1a978 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
-#define SAVEFILE_VERSION_MAX 55
+#define SAVEFILE_VERSION_MAX 56
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -42,14 +42,17 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//if your savefile is 3 months out of date, then 'tough shit'.
/datum/preferences/proc/update_preferences(current_version, savefile/S)
- if(current_version < 55) //Bitflag toggles don't set their defaults when they're added, always defaulting to off instead.
- toggles |= SOUND_BARK
- if(current_version < 46) //If you remove this, remove force_reset_keybindings() too.
- force_reset_keybindings_direct(TRUE)
- addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice.
if(current_version < 30)
outline_enabled = TRUE
outline_color = COLOR_THEME_MIDNIGHT
+ if(current_version < 46) //If you remove this, remove force_reset_keybindings() too.
+ force_reset_keybindings_direct(TRUE)
+ addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice.
+ if(current_version < 55) //Bitflag toggles don't set their defaults when they're added, always defaulting to off instead.
+ toggles |= SOUND_BARK
+ if(current_version < 56)
+ for(var/be_special_type in be_special)
+ be_special[be_special_type] = 1
/datum/preferences/proc/update_character(current_version, savefile/S)
if(current_version < 19)