Adds random character when antagonist preference (#46952)

About The Pull Request

Well known statics rejoice! You can now choose to have random name/body/age/gender whenever you roll roundstart antagonist.

Since player mobs are generated before antag datums are handed out, I added a list that collects minds chosen as antags during pre_setup() to keep track of this.

"Other" was also missing from the random gender, added it.

Wizard, clown op, nukeop, latejoin and midround antags are excempt.
Why It's Good For The Game

Some static namers get metagamed to the extreme when antagonists, this should help alleviate that while allowing them to keep static naming for the RP. Keep in mind all conversion, midround and latejoin antag rolls are excempt, this is not a guarantee someone is a non-antag.
Changelog

cl Skoglol
add: Random name/body/age/gender when roundstart antagonist preference added.
add: Random gender will now have a chance of picking "Other".
/cl
This commit is contained in:
skoglol
2019-10-13 06:00:17 +02:00
committed by oranges
parent 6628f692aa
commit b68abe7e6d
15 changed files with 93 additions and 29 deletions

View File

@@ -85,10 +85,14 @@
//randomised elements
#define RANDOM_NAME "random_name"
#define RANDOM_NAME_ANTAG "random_name_antag"
#define RANDOM_BODY "random_body"
#define RANDOM_BODY_ANTAG "random_body_antag"
#define RANDOM_SPECIES "random_species"
#define RANDOM_GENDER "random_gender"
#define RANDOM_GENDER_ANTAG "random_gender_antag"
#define RANDOM_AGE "random_age"
#define RANDOM_AGE_ANTAG "random_age_antag"
#define RANDOM_UNDERWEAR "random_underwear"
#define RANDOM_UNDERWEAR_COLOR "random_underwear_color"
#define RANDOM_UNDERSHIRT "random_undershirt"
@@ -100,4 +104,4 @@
#define RANDOM_FACIAL_HAIR_COLOR "random_facial_hair_color"
#define RANDOM_FACIAL_HAIRSTYLE "random_facial_hairstyle"
#define RANDOM_SKIN_TONE "random_skin_tone"
#define RANDOM_EYE_COLOR "random_eye_color"
#define RANDOM_EYE_COLOR "random_eye_color"

View File

@@ -18,6 +18,7 @@ GLOBAL_LIST_EMPTY(drones_list)
GLOBAL_LIST_EMPTY(dead_mob_list) //all dead mobs, including clientless. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game at round-start or as a latejoin.
GLOBAL_LIST_EMPTY(new_player_list) //all /mob/dead/new_player, in theory all should have clients and those that don't are in the process of spawning and get deleted when done.
GLOBAL_LIST_EMPTY(pre_setup_antags) //minds that have been picked as antag by the gamemode. removed as antag datums are set.
GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs
GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes
GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subtypes, notably does not contain brains or simple animals

View File

@@ -45,7 +45,12 @@
bro.restricted_roles = restricted_jobs
log_game("[key_name(bro)] has been selected as a Brother")
pre_brother_teams += team
return ..()
. = ..()
if(.) //To ensure the game mode is going ahead
for(var/teams in pre_brother_teams)
for(var/antag in teams)
GLOB.pre_setup_antags += antag
return
/datum/game_mode/traitor/bros/post_setup()
for(var/datum/team/brother_team/team in pre_brother_teams)
@@ -53,6 +58,7 @@
team.forge_brother_objectives()
for(var/datum/mind/M in team.members)
M.add_antag_datum(/datum/antagonist/brother, team)
GLOB.pre_setup_antags -= M
team.update_name()
brother_teams += pre_brother_teams
return ..()

View File

@@ -51,10 +51,11 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
changelings += changeling
changeling.special_role = ROLE_CHANGELING
changeling.restricted_roles = restricted_jobs
return 1
GLOB.pre_setup_antags += changeling
return TRUE
else
setup_error = "Not enough changeling candidates"
return 0
return FALSE
/datum/game_mode/changeling/post_setup()
//Decide if it's ok for the lings to have a team objective
@@ -75,6 +76,7 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
var/datum/antagonist/changeling/new_antag = new()
new_antag.team_mode = TRUE
changeling.add_antag_datum(new_antag)
GLOB.pre_setup_antags -= changeling
..()
/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners

View File

@@ -51,13 +51,18 @@
changeling.special_role = ROLE_CHANGELING
changelings += changeling
changeling.restricted_roles = restricted_jobs
return ..()
. = ..()
if(.) //To ensure the game mode is going ahead
for(var/antag in changelings)
GLOB.pre_setup_antags += antag
return
else
return 0
return FALSE
/datum/game_mode/traitor/changeling/post_setup()
for(var/datum/mind/changeling in changelings)
changeling.add_antag_datum(/datum/antagonist/changeling)
GLOB.pre_setup_antags -= changeling
return ..()
/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners

View File

@@ -174,9 +174,10 @@ Credit where due:
servant.assigned_role = ROLE_SERVANT_OF_RATVAR
servant.special_role = ROLE_SERVANT_OF_RATVAR
starter_servants--
GLOB.pre_setup_antags += servant
ark_time = 30 + round((roundstart_player_count / 5)) //In minutes, how long the Ark will wait before activation
ark_time = min(ark_time, 35) //35 minute maximum for the activation timer
return 1
return TRUE
/datum/game_mode/clockwork_cult/post_setup()
var/list/spread_out_spawns = GLOB.servant_spawns.Copy()
@@ -191,20 +192,21 @@ Credit where due:
greet_servant(L)
equip_servant(L)
add_servant_of_ratvar(L, TRUE)
GLOB.pre_setup_antags -= S
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar //that's a mouthful
G.final_countdown(ark_time)
..()
return 1
return TRUE
/datum/game_mode/clockwork_cult/proc/greet_servant(mob/M) //Description of their role
if(!M)
return 0
return FALSE
to_chat(M, "<span class='bold large_brass'>You are a servant of Ratvar, the Clockwork Justiciar!</span>")
to_chat(M, "<span class='brass'>You have approximately <b>[ark_time]</b> minutes until the Ark activates.</span>")
to_chat(M, "<span class='brass'>Unlock <b>Script</b> scripture by converting a new servant.</span>")
to_chat(M, "<span class='brass'><b>Application</b> scripture will be unlocked halfway until the Ark's activation.</span>")
M.playsound_local(get_turf(M), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE)
return 1
return TRUE
/datum/game_mode/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob, with one of each component
if(!M || !ishuman(M))

View File

@@ -83,6 +83,8 @@
log_game("[key_name(cultist)] has been selected as a cultist")
if(cultists_to_cult.len>=required_enemies)
for(var/antag in cultists_to_cult)
GLOB.pre_setup_antags += antag
return TRUE
else
setup_error = "Not enough cultist candidates"
@@ -94,6 +96,7 @@
for(var/datum/mind/cult_mind in cultists_to_cult)
add_cultist(cult_mind, 0, equip=TRUE, cult_team = main_cult)
GLOB.pre_setup_antags -= cult_mind
main_cult.setup_objectives() //Wait until all cultists are assigned to make sure none will be chosen as sacrifice.

View File

@@ -47,15 +47,17 @@
if(devils.len < required_enemies)
setup_error = "Not enough devil candidates"
return 0
return 1
return FALSE
for(var/antag in devils)
GLOB.pre_setup_antags += antag
return TRUE
/datum/game_mode/devil/post_setup()
for(var/datum/mind/devil in devils)
post_setup_finalize(devil)
..()
return 1
return TRUE
/datum/game_mode/devil/generate_report()
return "Infernal creatures have been seen nearby offering great boons in exchange for souls. This is considered theft against Nanotrasen, as all employment contracts contain a lien on the \
@@ -63,6 +65,7 @@
/datum/game_mode/devil/proc/post_setup_finalize(datum/mind/devil)
add_devil(devil.current, ascendable = TRUE) //Devil gamemode devils are ascendable.
GLOB.pre_setup_antags -= devil
add_devil_objectives(devil,2)
/proc/is_devil(mob/living/M)

View File

@@ -110,6 +110,7 @@
/datum/dynamic_ruleset/proc/execute()
for(var/datum/mind/M in assigned)
M.add_antag_datum(antag_datum)
GLOB.pre_setup_antags -= M
return TRUE
/// Here you can perform any additional checks you want. (such as checking the map etc)

View File

@@ -28,6 +28,7 @@
assigned += M.mind
M.mind.special_role = ROLE_TRAITOR
M.mind.restricted_roles = restricted_roles
GLOB.pre_setup_antags += M.mind
return TRUE
/datum/dynamic_ruleset/roundstart/traitor/rule_process()
@@ -77,6 +78,7 @@
team.add_member(bro.mind)
bro.mind.special_role = "brother"
bro.mind.restricted_roles = restricted_roles
GLOB.pre_setup_antags += bro.mind
pre_brother_teams += team
return TRUE
@@ -86,6 +88,7 @@
team.forge_brother_objectives()
for(var/datum/mind/M in team.members)
M.add_antag_datum(/datum/antagonist/brother, team)
GLOB.pre_setup_antags -= M
team.update_name()
mode.brother_teams += pre_brother_teams
return TRUE
@@ -116,6 +119,7 @@
assigned += M.mind
M.mind.restricted_roles = restricted_roles
M.mind.special_role = ROLE_CHANGELING
GLOB.pre_setup_antags += M.mind
return TRUE
/datum/dynamic_ruleset/roundstart/changeling/execute()
@@ -135,6 +139,7 @@
var/datum/antagonist/changeling/new_antag = new antag_datum()
new_antag.team_mode = team_mode
changeling.add_antag_datum(new_antag)
GLOB.pre_setup_antags -= changeling
return TRUE
//////////////////////////////////////////////
@@ -173,7 +178,7 @@
assigned += M.mind
M.mind.assigned_role = ROLE_WIZARD
M.mind.special_role = ROLE_WIZARD
return TRUE
/datum/dynamic_ruleset/roundstart/wizard/execute()
@@ -218,6 +223,7 @@
assigned += M.mind
M.mind.special_role = ROLE_CULTIST
M.mind.restricted_roles = restricted_roles
GLOB.pre_setup_antags += M.mind
return TRUE
/datum/dynamic_ruleset/roundstart/bloodcult/execute()
@@ -227,6 +233,7 @@
new_cultist.cult_team = main_cult
new_cultist.give_equipment = TRUE
M.add_antag_datum(new_cultist)
GLOB.pre_setup_antags -= M
main_cult.setup_objectives()
return TRUE
@@ -361,6 +368,7 @@
assigned += M.mind
M.mind.restricted_roles = restricted_roles
M.mind.special_role = antag_flag
GLOB.pre_setup_antags += M.mind
return TRUE
/datum/dynamic_ruleset/roundstart/revs/execute()
@@ -371,6 +379,7 @@
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
M.add_antag_datum(new_head,revolution)
GLOB.pre_setup_antags -= M
revolution.update_objectives()
revolution.update_heads()
SSshuttle.registerHostileEnvironment(src)
@@ -480,6 +489,7 @@
assigned += servant.mind
servant.mind.assigned_role = ROLE_SERVANT_OF_RATVAR
servant.mind.special_role = ROLE_SERVANT_OF_RATVAR
GLOB.pre_setup_antags += servant.mind
ark_time = 30 + round((number_players / 5))
ark_time = min(ark_time, 35)
return TRUE
@@ -496,6 +506,7 @@
greet_servant(S)
equip_servant(S)
add_servant_of_ratvar(S, TRUE)
GLOB.pre_setup_antags -= S.mind
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar //that's a mouthful
G.final_countdown(ark_time)
return TRUE
@@ -601,6 +612,7 @@
assigned += devil.mind
devil.mind.special_role = ROLE_DEVIL
devil.mind.restricted_roles = restricted_roles
GLOB.pre_setup_antags += devil.mind
log_game("[key_name(devil)] has been selected as a devil")
return TRUE
@@ -608,6 +620,7 @@
/datum/dynamic_ruleset/roundstart/devil/execute()
for(var/datum/mind/devil in assigned)
add_devil(devil.current, ascendable = TRUE)
GLOB.pre_setup_antags -= devil
add_devil_objectives(devil,2)
return TRUE

View File

@@ -55,6 +55,8 @@
setup_error = "Not enough headrev candidates"
return FALSE
for(var/antag in headrev_candidates)
GLOB.pre_setup_antags += antag
return TRUE
/datum/game_mode/revolution/post_setup()
@@ -97,6 +99,7 @@
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
rev_mind.add_antag_datum(new_head,revolution)
GLOB.pre_setup_antags -= rev_mind
revolution.update_objectives()
revolution.update_heads()

View File

@@ -63,6 +63,9 @@
setup_error = "Not enough traitor candidates"
return FALSE
else
for(var/antag in pre_traitors)
GLOB.pre_setup_antags += antag
to_chat(world, "Added [antag] to pre-antag list")
return TRUE
@@ -70,6 +73,7 @@
for(var/datum/mind/traitor in pre_traitors)
var/datum/antagonist/traitor/new_antag = new antag_datum()
addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100))
GLOB.pre_setup_antags -= traitor
if(!exchange_blue)
exchange_blue = -1 //Block latejoiners from getting exchange objectives
..()

View File

@@ -48,6 +48,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/uses_glasses_colour = 0
//character preferences
var/slot_randomized //keeps track of round-to-round randomization of the character slot, prevents overwriting
var/real_name //our character's name
var/gender = MALE //gender of character (well duh)
var/age = 30 //age of character
@@ -137,6 +138,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
/datum/preferences/proc/ShowChoices(mob/user)
if(!user || !user.client)
return
if(slot_randomized)
load_character(default_slot) // Reloads the character slot. Prevents random features from overwriting the slot if saved.
slot_randomized = FALSE
update_preview_icon()
var/list/dat = list("<center>")
@@ -182,8 +186,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(is_banned_from(user.ckey, "Appearance"))
dat += "<b>You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.</b><br>"
dat += "<a href='?_src_=prefs;preference=name;task=random'>Random Name</A> "
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_NAME]'>Always Random Name: [(randomise[RANDOM_NAME]) ? "Yes" : "No"]</a><BR>"
dat += "<b>Name:</b> "
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_NAME]'>Always Random Name: [(randomise[RANDOM_NAME]) ? "Yes" : "No"]</a>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_NAME_ANTAG]'>When Antagonist: [(randomise[RANDOM_NAME_ANTAG]) ? "Yes" : "No"]</a>"
dat += "<br><b>Name:</b> "
dat += "<a href='?_src_=prefs;preference=name;task=input'>[real_name]</a><BR>"
if(!(AGENDER in pref_species.species_traits))
@@ -195,10 +200,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
dispGender = "Other"
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender'>[dispGender]</a>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_GENDER]'>Always Random Gender: [(randomise[RANDOM_GENDER]) ? "Yes" : "No"]</A>"
if(randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG]) //doesn't work unless random body
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_GENDER]'>Always Random Gender: [(randomise[RANDOM_GENDER]) ? "Yes" : "No"]</A>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_GENDER_ANTAG]'>When Antagonist: [(randomise[RANDOM_GENDER_ANTAG]) ? "Yes" : "No"]</A>"
dat += "<br><b>Age:</b> <a href='?_src_=prefs;preference=age;task=input'>[age]</a>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_AGE]'>Always Random Age: [(randomise[RANDOM_AGE]) ? "Yes" : "No"]</A>"
if(randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG]) //doesn't work unless random body
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_AGE]'>Always Random Age: [(randomise[RANDOM_AGE]) ? "Yes" : "No"]</A>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_AGE_ANTAG]'>When Antagonist: [(randomise[RANDOM_AGE_ANTAG]) ? "Yes" : "No"]</A>"
dat += "<br><br><b>Special Names:</b><BR>"
var/old_group
@@ -220,7 +229,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<h2>Body</h2>"
dat += "<a href='?_src_=prefs;preference=all;task=random'>Random Body</A> "
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_BODY]'>Always Random Body: [(randomise[RANDOM_BODY]) ? "Yes" : "No"]</A><br>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_BODY]'>Always Random Body: [(randomise[RANDOM_BODY]) ? "Yes" : "No"]</A>"
dat += "<a href='?_src_=prefs;preference=toggle_random;random_type=[RANDOM_BODY_ANTAG]'>When Antagonist: [(randomise[RANDOM_BODY_ANTAG]) ? "Yes" : "No"]</A><br>"
dat += "<table width='100%'><tr><td width='24%' valign='top'>"
@@ -1561,15 +1571,17 @@ GLOBAL_LIST_EMPTY(preferences_datums)
ShowChoices(user)
return 1
/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE, character_setup = FALSE)
/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE, character_setup = FALSE, antagonist = FALSE)
if(randomise[RANDOM_SPECIES] && !character_setup)
random_species()
if(randomise[RANDOM_BODY] && !character_setup)
random_character(gender)
if((randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG] && antagonist) && !character_setup)
slot_randomized = TRUE
random_character(gender, antagonist)
if(randomise[RANDOM_NAME] && !character_setup)
if((randomise[RANDOM_NAME] || randomise[RANDOM_NAME_ANTAG] && antagonist) && !character_setup)
slot_randomized = TRUE
real_name = pref_species.random_name(gender)
if(roundstart_checks)

View File

@@ -481,7 +481,12 @@
if(frn)
client.prefs.random_character()
client.prefs.real_name = client.prefs.pref_species.random_name(gender,1)
client.prefs.copy_to(H)
var/is_antag
if(mind in GLOB.pre_setup_antags)
is_antag = TRUE
client.prefs.copy_to(H, antagonist = is_antag)
H.dna.update_dna_identity()
if(mind)
if(transfer_after)

View File

@@ -1,15 +1,15 @@
//The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/random_character(gender_override)
/datum/preferences/proc/random_character(gender_override, antag_override = FALSE)
if(randomise[RANDOM_SPECIES])
random_species()
else if(randomise[RANDOM_NAME])
real_name = pref_species.random_name(gender,1)
if(gender_override && !(randomise[RANDOM_GENDER]))
if(gender_override && !(randomise[RANDOM_GENDER] || randomise[RANDOM_GENDER_ANTAG] && antag_override))
gender = gender_override
else
gender = pick(MALE,FEMALE)
if(randomise[RANDOM_AGE])
gender = pick(MALE,FEMALE,PLURAL)
if(randomise[RANDOM_AGE] || randomise[RANDOM_AGE_ANTAG] && antag_override)
age = rand(AGE_MIN,AGE_MAX)
if(randomise[RANDOM_UNDERWEAR])
underwear = random_underwear(gender)
@@ -74,4 +74,4 @@
COMPILE_OVERLAYS(mannequin)
parent.show_character_previews(new /mutable_appearance(mannequin))
unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)