Skip to content

Commit

Permalink
tweak: Antag Paradise Tweak (#3898)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gottfrei authored Nov 18, 2023
1 parent c91dee3 commit 9deec44
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 156 deletions.
1 change: 1 addition & 0 deletions code/__DEFINES/role_preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#define ROLE_MALF_AI "Malfunctioning AI"

#define ROLE_NONE "nothing" // special define used as a marker
#define ROLE_HIJACKER "hijacker" // another marker

//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
Expand Down
16 changes: 3 additions & 13 deletions code/_globalvars/game_modes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,9 @@ GLOBAL_VAR_INIT(disable_robotics_consoles, FALSE)
/// Chance to roll double antag for traitors in ANTAG-PARADISE gamemode.
GLOBAL_VAR(antag_paradise_double_antag_chance)

/// Weights for all minor antags in ANTAG-PARADISE gamemode. Highter the weight higher the chance for antag to roll.
GLOBAL_LIST_INIT(antag_paradise_weights, list(
ROLE_TRAITOR = 0,
ROLE_THIEF = 0,
ROLE_VAMPIRE = 0,
ROLE_CHANGELING = 0,
))
/// Weights for all minor antags in ANTAG-PARADISE gamemode.
GLOBAL_LIST(antag_paradise_weights)

/// Weights for all special antags in ANTAG-PARADISE gamemode.
GLOBAL_LIST_INIT(antag_paradise_special_weights, list(
ROLE_TRAITOR = 0, // hijacker actually
ROLE_MALF_AI = 0,
ROLE_NINJA = 0,
ROLE_NONE = 0, // to skip all roles entirely
))
GLOBAL_LIST(antag_paradise_special_weights)

32 changes: 9 additions & 23 deletions code/controllers/configuration/entries/config.dm
Original file line number Diff line number Diff line change
Expand Up @@ -414,24 +414,20 @@


/datum/config_entry/number/antag_paradise_double_antag_chance


/datum/config_entry/number/antag_paradise_double_antag_chance/ValidateAndSet(str_val)
. = ..()
if(.)
GLOB.antag_paradise_double_antag_chance = config_entry_value
default = 10
max_val = 100
min_val = 0


/datum/config_entry/keyed_list/antag_paradise_weights
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM


/datum/config_entry/keyed_list/antag_paradise_weights/ValidateAndSet(str_val)
. = ..()
if(.)
for(var/role in config_entry_value)
GLOB.antag_paradise_weights[role] = config_entry_value[role]
default = list(
ROLE_TRAITOR = 0,
ROLE_THIEF = 0,
ROLE_VAMPIRE = 0,
ROLE_CHANGELING = 0,
)


/datum/config_entry/keyed_list/antag_paradise_special_weights
Expand All @@ -445,15 +441,6 @@
)


/datum/config_entry/keyed_list/antag_paradise_special_weights/ValidateAndSet(str_val)
. = ..()
if(.)
GLOB.antag_paradise_special_weights[ROLE_TRAITOR] = config_entry_value["hijacker"]
GLOB.antag_paradise_special_weights[ROLE_MALF_AI] = config_entry_value["malfai"]
GLOB.antag_paradise_special_weights[ROLE_NINJA] = config_entry_value["ninja"]
GLOB.antag_paradise_special_weights[ROLE_NONE] = config_entry_value["nothing"]


/datum/config_entry/keyed_list/antag_paradise_mode_subtypes
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
Expand All @@ -472,7 +459,6 @@
ANTAG_SINGLE = 6,
ANTAG_DOUBLE = 4,
ANTAG_TRIPPLE = 2,
ANTAG_RANDOM = 10,
)


Expand Down
136 changes: 65 additions & 71 deletions code/game/gamemodes/antag_paradise/antag_paradise.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
var/list/protected_jobs_AI = list("Civilian","Chief Engineer","Station Engineer","Trainee Engineer","Life Support Specialist","Mechanic","Chief Medical Officer","Medical Doctor","Intern","Coroner","Chemist","Geneticist","Virologist","Psychiatrist","Paramedic","Research Director","Scientist","Student Scientist","Roboticist","Head of Personnel","Chaplain","Bartender","Chef","Botanist","Quartermaster","Cargo Technician","Shaft Miner","Clown","Mime","Janitor","Librarian","Barber","Explorer") // Basically all jobs, except AI.
var/secondary_protected_species = list("Machine")
var/vampire_restricted_jobs = list("Chaplain")
var/thief_prefered_species = list("Vox")
var/thief_prefered_species_mod = 4
var/list/datum/mind/pre_traitors = list()
var/list/datum/mind/pre_thieves = list()
var/list/datum/mind/pre_changelings = list()
Expand All @@ -26,9 +24,10 @@
ROLE_CHANGELING = 15,
)
var/list/special_antag_required_players = list(
ROLE_TRAITOR = 30, // hijacker
ROLE_HIJACKER = 30,
ROLE_MALF_AI = 30,
ROLE_NINJA = 30,
ROLE_NONE = 0,
)
var/list/antag_amount = list(
ROLE_TRAITOR = 0,
Expand All @@ -37,17 +36,6 @@
ROLE_CHANGELING = 0,
)

/// Weight ratio for antags. Higher the weight higher the chance to roll this antag. This values will be modified by config or by admins.
var/list/antag_weights = list(
ROLE_TRAITOR = 0,
ROLE_THIEF = 0,
ROLE_VAMPIRE = 0,
ROLE_CHANGELING = 0,
)

/// Default chance for traitor to get another antag role, available in prefs.
var/chance_double_antag = 10

/// Chosen antag type.
var/special_antag_type
/// Chosen special antag if any.
Expand Down Expand Up @@ -94,18 +82,20 @@
restricted_jobs += protected_jobs

switch(special_antag_type)
if(ROLE_TRAITOR) // hijacker
if(ROLE_HIJACKER)
special_antag = safepick(get_players_for_role(ROLE_TRAITOR))
if(special_antag)
special_antag.restricted_roles = restricted_jobs
special_antag.special_role = SPECIAL_ROLE_TRAITOR
else
special_antag_type = null

if(ROLE_MALF_AI)
special_antag = safepick(get_players_for_role(ROLE_MALF_AI))
if(special_antag)
special_antag.restricted_roles = (restricted_jobs|protected_jobs_AI)
special_antag.restricted_roles = (restricted_jobs|protected_jobs|protected_jobs_AI)
special_antag.restricted_roles -= "AI"
special_antag.special_role = SPECIAL_ROLE_TRAITOR
SSjobs.new_malf = special_antag.current
else
special_antag_type = null
Expand All @@ -119,7 +109,7 @@
var/datum/mind/vampire = pick_n_take(possible_vampires)
if(vampire.current.client.prefs.species in secondary_protected_species)
continue
if(vampire == special_antag)
if(vampire.special_role)
continue
pre_vampires += vampire
vampire.special_role = SPECIAL_ROLE_VAMPIRE
Expand All @@ -131,7 +121,7 @@
var/datum/mind/changeling = pick_n_take(possible_changelings)
if(changeling.current.client.prefs.species in secondary_protected_species)
continue
if(changeling.special_role || changeling == special_antag)
if(changeling.special_role)
continue
pre_changelings += changeling
changeling.special_role = SPECIAL_ROLE_CHANGELING
Expand All @@ -141,45 +131,37 @@
var/list/datum/mind/possible_traitors = get_players_for_role(ROLE_TRAITOR)
while(length(possible_traitors) && length(pre_traitors) <= antag_amount[ROLE_TRAITOR])
var/datum/mind/traitor = pick_n_take(possible_traitors)
if(traitor.special_role || traitor == special_antag)
if(traitor.special_role)
continue
pre_traitors += traitor
traitor.special_role = SPECIAL_ROLE_TRAITOR
traitor.restricted_roles = restricted_jobs

if(antag_amount[ROLE_THIEF])
var/list/datum/mind/possible_thieves = get_players_for_role(ROLE_THIEF)
if(length(possible_thieves))
var/list/thief_list = list()
for(var/datum/mind/thief in possible_thieves)
thief_list += thief
if(thief.current.client.prefs.species in thief_prefered_species)
for(var/i in 1 to thief_prefered_species_mod)
thief_list += thief

while(length(thief_list) && length(pre_thieves) <= antag_amount[ROLE_THIEF])
var/datum/mind/thief = pick_n_take(thief_list)
listclearduplicates(thief, thief_list)
if(thief.special_role || thief == special_antag)
continue
pre_thieves += thief
thief.special_role = SPECIAL_ROLE_THIEF
thief.restricted_roles = restricted_jobs
var/list/datum/mind/possible_thieves = get_players_for_role(ROLE_THIEF, list("Vox" = 4))
while(length(possible_thieves) && length(pre_thieves) <= antag_amount[ROLE_THIEF])
var/datum/mind/thief = pick_n_take(possible_thieves)
listclearduplicates(thief, possible_thieves)
if(thief.special_role)
continue
pre_thieves += thief
thief.special_role = SPECIAL_ROLE_THIEF
thief.restricted_roles = restricted_jobs

if(!(length(pre_vampires) + length(pre_changelings) + length(pre_traitors) + length(pre_thieves)) && !special_antag)
return

. = TRUE

var/chance_double_antag = isnull(GLOB.antag_paradise_double_antag_chance) ? CONFIG_GET(number/antag_paradise_double_antag_chance) : GLOB.antag_paradise_double_antag_chance
if(!chance_double_antag || !length(pre_traitors))
return

var/list/pre_traitors_copy = pre_traitors.Copy()
while(length(pre_traitors_copy))
for(var/T in pre_traitors)
if(!prob(chance_double_antag))
continue

var/datum/mind/traitor = pick_n_take(pre_traitors_copy)
var/datum/mind/traitor = T
var/list/available_roles = list(ROLE_VAMPIRE, ROLE_CHANGELING)
while(length(available_roles))
var/second_role = pick_n_take(available_roles)
Expand Down Expand Up @@ -209,61 +191,51 @@
var/scale = CONFIG_GET(number/traitor_scaling) ? CONFIG_GET(number/traitor_scaling) : 10
var/antags_amount = 1 + round(players / scale)

chance_double_antag = isnull(GLOB.antag_paradise_double_antag_chance) ? chance_double_antag : GLOB.antag_paradise_double_antag_chance

var/list/available_special_antags = list()
var/list/special_antags_list = GLOB.antag_paradise_special_weights ? GLOB.antag_paradise_special_weights.Copy() : config_to_roles(CONFIG_GET(keyed_list/antag_paradise_special_weights))
for(var/antag in special_antag_required_players)
if(players < special_antag_required_players[antag])
continue
available_special_antags += antag
special_antags_list -= antag

special_antag_type = pick_weight_classic(GLOB.antag_paradise_special_weights)
if(special_antag_type in available_special_antags)
antags_amount--
else
special_antag_type = null
if(length(special_antags_list))
special_antag_type = pick_weight_classic(special_antags_list)
if(special_antag_type && special_antag_type != ROLE_NONE)
antags_amount--

var/list/available_antags = list()
var/list/antags_list = GLOB.antag_paradise_weights ? GLOB.antag_paradise_weights.Copy() : config_to_roles(CONFIG_GET(keyed_list/antag_paradise_weights))
for(var/antag in antag_required_players)
if(players < antag_required_players[antag])
continue
available_antags += antag
antags_list -= antag

var/modifed_weights = FALSE
for(var/antag in antag_weights)
if(!(antag in available_antags))
continue
antag_weights[antag] = GLOB.antag_paradise_weights[antag]
if(GLOB.antag_paradise_weights[antag] > 0)
modifed_weights = TRUE
var/modified_weights = FALSE
for(var/antag in antags_list)
if(antags_list[antag])
modified_weights = TRUE

if(!modifed_weights)
if(!modified_weights)
var/mode_type = pick_weight_classic(CONFIG_GET(keyed_list/antag_paradise_mode_subtypes))
var/list/subtype_weights = CONFIG_GET(keyed_list/antag_paradise_subtype_weights)
if(mode_type == ANTAG_RANDOM)
for(var/antag in antag_weights)
if(!(antag in available_antags))
continue
var/random = rand(-subtype_weights[ANTAG_RANDOM], subtype_weights[ANTAG_RANDOM])
antag_weights[antag] = random < 0 ? 0 : random
for(var/antag in antags_list)
antags_list[antag] = rand(1, 100)
else
var/list/available_antags = antags_list.Copy()
var/list/subtype_weights = CONFIG_GET(keyed_list/antag_paradise_subtype_weights)
while(length(available_antags))
antag_weights[pick_n_take(available_antags)] = subtype_weights[ANTAG_SINGLE]
antags_list[pick_n_take(available_antags)] = subtype_weights[ANTAG_SINGLE]
if(!length(available_antags) || mode_type == ANTAG_SINGLE)
break
antag_weights[pick_n_take(available_antags)] = subtype_weights[ANTAG_DOUBLE]
antags_list[pick_n_take(available_antags)] = subtype_weights[ANTAG_DOUBLE]
if(!length(available_antags) || mode_type == ANTAG_DOUBLE)
break
antag_weights[pick_n_take(available_antags)] = subtype_weights[ANTAG_TRIPPLE]
antags_list[pick_n_take(available_antags)] = subtype_weights[ANTAG_TRIPPLE]
break

for(var/i in 1 to antags_amount)
antag_amount[pick_weight_classic(antag_weights)]++
antag_amount[pick_weight_classic(antags_list)]++


/datum/game_mode/antag_paradise/post_setup()
switch(special_antag_type)
if(ROLE_TRAITOR) // hijacker
if(ROLE_HIJACKER)
var/datum/antagonist/traitor/hijacker_datum = new
hijacker_datum.is_hijacker = TRUE
addtimer(CALLBACK(special_antag, TYPE_PROC_REF(/datum/mind, add_antag_datum), hijacker_datum), rand(1 SECONDS, 10 SECONDS))
Expand Down Expand Up @@ -299,3 +271,25 @@
for(var/datum/mind/changeling in traitor_changelings)
changeling.add_antag_datum(/datum/antagonist/changeling)


/proc/config_to_roles(list/check_list)
var/list/new_list = list()
for(var/index in check_list)
switch(index)
if("hijacker")
new_list += ROLE_HIJACKER
new_list[ROLE_HIJACKER] = check_list[index]
if("malfai")
new_list += ROLE_MALF_AI
new_list[ROLE_MALF_AI] = check_list[index]
if("ninja")
new_list += ROLE_NINJA
new_list[ROLE_NINJA] = check_list[index]
if("nothing")
new_list += ROLE_NONE
new_list[ROLE_NONE] = check_list[index]
else
new_list += index
new_list[index] = check_list[index]
return new_list

8 changes: 2 additions & 6 deletions code/game/gamemodes/game_mode.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@
var/list/protected_jobs = list()
/// Species that can't be antags.
var/list/protected_species = list()
/// Species duplicate for antags. Remember to clear the list you get with [get_players_for_role()] from duplicate minds. See thief game mode setup.
var/list/prefered_species = list()
/// If prefered_species list is not empty antagonist mind with that specie will be duplicated passed number of times in get_players_for_role().
var/prefered_species_mod = 0
/// How many players should press ready for mode to activate.
var/required_players = 0
/// How many antagonists are required for mode start.
Expand Down Expand Up @@ -293,7 +289,7 @@
* Returns a list of player minds who had the antagonist role set to yes, regardless of recomended_enemies.
* Jobbans and restricted jobs are checked. Species lock and prefered species are checked. List is already shuffled.
*/
/datum/game_mode/proc/get_players_for_role(role)
/datum/game_mode/proc/get_players_for_role(role, list/prefered_species)
var/list/players = list()
var/list/candidates = list()

Expand All @@ -320,7 +316,7 @@
player_draft_log += "[player.key] had [roletext] enabled, so we are drafting them."
candidates += player.mind
if(length(prefered_species) && (player.client.prefs.species in prefered_species))
for (var/i in 1 to prefered_species_mod) //prefered mod
for (var/i in 1 to prefered_species[player.client.prefs.species]) //prefered mod
candidates += player.mind
players -= player

Expand Down
2 changes: 1 addition & 1 deletion code/game/gamemodes/thief/changeling_thief.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs

var/list/datum/mind/possible_thieves = get_players_for_role(ROLE_THIEF)
var/list/datum/mind/possible_thieves = get_players_for_role(ROLE_THIEF, list("Vox" = 4))

if(length(possible_thieves))
var/datum/mind/thief = pick(possible_thieves)
Expand Down
4 changes: 1 addition & 3 deletions code/game/gamemodes/thief/thief.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
config_tag = "thief"
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Nanotrasen Navy Field Officer", "Special Operations Officer", "Supreme Commander", "Syndicate Officer")
prefered_species = list("Vox")
prefered_species_mod = 4
required_players = 0
required_enemies = 1
recommended_enemies = 3
Expand All @@ -26,7 +24,7 @@
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs

var/list/datum/mind/possible_thieves = get_players_for_role(ROLE_THIEF)
var/list/datum/mind/possible_thieves = get_players_for_role(ROLE_THIEF, list("Vox" = 4))

var/thieves_scale = 15
if(CONFIG_GET(number/traitor_scaling))
Expand Down
Loading

0 comments on commit 9deec44

Please sign in to comment.