mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-14 09:35:30 +01:00
[MIRROR] Mafia games can now be voted on to start early, forced to start early by admins [MDB IGNORE] (#20120)
* Mafia games can now be voted on to start early, forced to start early by admins (#74256) ## About The Pull Request **DISCLAIMER:** Mafia, being a 12-player game, is very very difficult to debug. I've tested everything here to the extent that I can as one person, but this might need some really careful inspection. This PR adds a new option to the mafia minigame menu, which lets signed-up players vote to start the game early. If there are more than three players signed up, and at least half of them are voting to start, the round will start. Admins also have the option to force a mafia round to start in the admin options panel. When a round is forcibly started, a random non-standard role setup is created. Unlike the normal setup parameters, which assume you have twelve players and attempts to fill out certain role types as a result, this one uses pools based on role alignment. If you start with eight players, you just might end up with four wardens, two thoughtfeeders, and double clowns. Every 3rd player is chosen as a random mafia member. The 5th and 6th roles are neutral disruptive and a random neutral role respectively. Everyone else is a random townie. I believe this formula is sufficient to create a playable experience with 5+ players. It can't start at any less than three, as the game would auto-resolve instantly. The setup won't be pretty, but it's better than no mafia game at all. ## Why It's Good For The Game Now you can play mafia without the strict 12-player requirement! Gives some opportunity for players to get acquainted with roles, the gameplay, and the mafia panel in a lower-seriousness environment than a standard 12-man game. If the ratio of early start voters required to start needs adjusting, that can be done. ## Changelog 🆑 Rhials add: You can now vote to start a Mafia game early. If over half of the current signups vote (And you have three or more players) you will immediately start a game with a slightly adjusted set of roles. admin: You can now force a mafia game to start in the admin options panel. /🆑 * Mafia games can now be voted on to start early, forced to start early by admins --------- Co-authored-by: Rhials <Datguy33456@gmail.com>
This commit is contained in:
@@ -79,3 +79,5 @@ GLOBAL_LIST_EMPTY(mafia_signup)
|
||||
GLOBAL_LIST_EMPTY(mafia_bad_signup)
|
||||
/// the current global mafia game running.
|
||||
GLOBAL_VAR(mafia_game)
|
||||
/// list of ghosts in mafia_signup who have voted to start early
|
||||
GLOBAL_LIST_EMPTY(mafia_early_votes)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
#define MINIMUM_MAFIA_PLAYERS 3
|
||||
|
||||
/**
|
||||
* The mafia controller handles the mafia minigame in progress.
|
||||
@@ -714,6 +714,9 @@
|
||||
try_autostart()//don't worry, this fails if there's a game in progress
|
||||
if("cancel_setup")
|
||||
custom_setup = list()
|
||||
if("start_now")
|
||||
forced_setup()
|
||||
|
||||
switch(action) //both living and dead
|
||||
if("mf_lookup")
|
||||
var/role_lookup = params["atype"]
|
||||
@@ -732,6 +735,7 @@
|
||||
return
|
||||
if(GLOB.mafia_signup[C.ckey])
|
||||
GLOB.mafia_signup -= C.ckey
|
||||
GLOB.mafia_early_votes -= C.ckey //Remove their early start vote as well
|
||||
to_chat(usr, span_notice("You unregister from Mafia."))
|
||||
return TRUE
|
||||
else
|
||||
@@ -749,6 +753,23 @@
|
||||
to_chat(usr, span_notice("You will now get messages from the game."))
|
||||
spectators += C.ckey
|
||||
return TRUE
|
||||
if("vote_to_start")
|
||||
if(phase != MAFIA_PHASE_SETUP)
|
||||
to_chat(usr, span_notice("You cannot vote to start while a game is underway!"))
|
||||
return
|
||||
if(!GLOB.mafia_signup[C.ckey])
|
||||
to_chat(usr, span_notice("You must be signed up for this game to vote!"))
|
||||
return
|
||||
if(GLOB.mafia_early_votes[C.ckey])
|
||||
GLOB.mafia_early_votes -= C.ckey
|
||||
to_chat(usr, span_notice("You are no longer voting to start the game early."))
|
||||
else
|
||||
GLOB.mafia_early_votes[C.ckey] = C
|
||||
to_chat(usr, span_notice("You vote to start the game early ([length(GLOB.mafia_early_votes)] out of [FLOOR(round(length(GLOB.mafia_signup) / 2), MINIMUM_MAFIA_PLAYERS)])."))
|
||||
if(check_start_votes()) //See if we have enough votes to start
|
||||
forced_setup()
|
||||
return TRUE
|
||||
|
||||
if(user_role && user_role.game_status == MAFIA_DEAD)
|
||||
return
|
||||
//User actions (just living)
|
||||
@@ -819,11 +840,11 @@
|
||||
. += L[key]
|
||||
|
||||
/**
|
||||
* Returns a semirandom setup with 12 roles. balance not guaranteed!
|
||||
* Returns a standard setup, with certain important/unique roles guaranteed. More balanced of an experience than generate_forced_setup()
|
||||
*
|
||||
* please check the variables at the top of the proc to see how much of each role types it picks
|
||||
*/
|
||||
/datum/mafia_controller/proc/generate_random_setup()
|
||||
/datum/mafia_controller/proc/generate_standard_setup()
|
||||
var/invests_left = 2
|
||||
var/protects_left = 2
|
||||
var/killings_left = 1
|
||||
@@ -864,6 +885,33 @@
|
||||
debug = random_setup
|
||||
return random_setup
|
||||
|
||||
/**
|
||||
* Returns a more volatile-ly generated role list, balance absolutely not expected. Does not assure any role types, only role alignments.
|
||||
*
|
||||
* Generates a setup based on a ratio of random pools of good/neutral/badguy roles.
|
||||
* Specific roles are not chosen (You could get an entire town of lawyers and double nightmares), outcomes may be unbalanced as a result.
|
||||
* This is used when a game start is forced and we don't have the players to make a properly balanced game.
|
||||
* Game will auto-resolve if less than 3 roles are generated (Town Victory), which should only be able to happen if an admin forces it.
|
||||
*
|
||||
* roles_to_generate - The number of roles we will return.
|
||||
*/
|
||||
/datum/mafia_controller/proc/generate_forced_setup(roles_to_generate)
|
||||
var/list/role_setup = list()
|
||||
var/list/unique_roles_added = list()
|
||||
for(var/i in 1 to roles_to_generate)
|
||||
if(i == 6)
|
||||
add_setup_role(role_setup, unique_roles_added, pick(NEUTRAL_KILL || NEUTRAL_DISRUPT))
|
||||
continue
|
||||
if(i == 5)
|
||||
add_setup_role(role_setup, unique_roles_added, pick(NEUTRAL_DISRUPT))
|
||||
continue
|
||||
if(ISMULTIPLE(i, MINIMUM_MAFIA_PLAYERS))
|
||||
add_setup_role(role_setup, unique_roles_added, pick(MAFIA_REGULAR, MAFIA_SPECIAL))
|
||||
continue
|
||||
add_setup_role(role_setup, unique_roles_added, pick(TOWN_INVEST, TOWN_PROTECT, TOWN_KILLING, TOWN_SUPPORT))
|
||||
|
||||
return role_setup
|
||||
|
||||
/**
|
||||
* Helper proc that adds a random role of a type to a setup. if it doesn't exist in the setup, it adds the path to the list and otherwise bumps the path in the list up one. unique roles can only get added once.
|
||||
*/
|
||||
@@ -904,6 +952,63 @@
|
||||
else
|
||||
req_players = assoc_value_sum(setup)
|
||||
|
||||
var/list/filtered_keys = filter_players(req_players)
|
||||
|
||||
if(!setup.len) //don't actually have one yet, so generate a max player random setup. it's good to do this here instead of above so it doesn't generate one every time a game could possibly start.
|
||||
setup = generate_standard_setup()
|
||||
prepare_game(setup,filtered_keys)
|
||||
start_game()
|
||||
|
||||
/**
|
||||
* Generates a forced role list and runs the game with the current number of signed-up players.
|
||||
*
|
||||
* Generates a randomized setup, and begins the game with everyone currently signed up.
|
||||
*/
|
||||
|
||||
/datum/mafia_controller/proc/forced_setup()
|
||||
check_signups() //Refresh the signup list, so our numbers are accurate and we only take active players into consideration.
|
||||
var/list/filtered_keys = filter_players(length(GLOB.mafia_signup))
|
||||
var/req_players = length(filtered_keys)
|
||||
|
||||
if(!req_players) //If we have nobody signed up, we give up on starting
|
||||
log_admin("Attempted to force a mafia game to start with nobody signed up!")
|
||||
return
|
||||
|
||||
var/list/setup = generate_forced_setup(req_players)
|
||||
|
||||
prepare_game(setup, filtered_keys)
|
||||
start_game()
|
||||
|
||||
/**
|
||||
* Checks if we have enough early start votes to begin the game early.
|
||||
*
|
||||
* Checks if we have the bare minimum of three signups, then checks if the number of early voters is at least half of the total
|
||||
* number of active signups.
|
||||
*/
|
||||
|
||||
/datum/mafia_controller/proc/check_start_votes()
|
||||
check_signups() //Same as before. What a useful proc.
|
||||
|
||||
if(length(GLOB.mafia_early_votes) < MINIMUM_MAFIA_PLAYERS)
|
||||
return FALSE //Bare minimum is 3, otherwise the game instantly ends. Also prevents people from randomly starting games for no reason.
|
||||
|
||||
if(length(GLOB.mafia_early_votes) < round(length(GLOB.mafia_signup) / 2))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Handles the filtering of disconected signups when picking who gets to be in the round.
|
||||
*
|
||||
* Filters out the player list, from a given max_players count. If more players are found
|
||||
* in the signup list than max_players, those players will be notified that they will not be put into the game.
|
||||
*
|
||||
* This should only be run as we are in the process of starting a game.
|
||||
*
|
||||
* max_players - The maximum number of keys to put in our return list before we start telling people they're not getting in.
|
||||
* filtered_keys - A list of player ckeys, to be included in the game.
|
||||
*/
|
||||
/datum/mafia_controller/proc/filter_players(max_players)
|
||||
//final list for all the players who will be in this game
|
||||
var/list/filtered_keys = list()
|
||||
//cuts invalid players from signups (disconnected/not a ghost)
|
||||
@@ -916,13 +1021,13 @@
|
||||
continue
|
||||
GLOB.mafia_signup -= key //not valid to play when we checked so remove them from signups
|
||||
|
||||
//if there were not enough players, don't start. we already trimmed the list to now hold only valid signups
|
||||
if(length(possible_keys) < req_players)
|
||||
return
|
||||
//If we're not over capacity and don't need to notify anyone of their exclusion, return early.
|
||||
if(length(possible_keys) < max_players)
|
||||
return filtered_keys
|
||||
|
||||
//if there were too many players, still start but only make filtered keys as big as it needs to be (cut excess)
|
||||
//also removes people who do get into final player list from the signup so they have to sign up again when game ends
|
||||
for(var/i in 1 to req_players)
|
||||
for(var/i in 1 to max_players)
|
||||
var/chosen_key = pick_n_take(possible_keys)
|
||||
filtered_keys += chosen_key
|
||||
GLOB.mafia_signup -= chosen_key
|
||||
@@ -932,10 +1037,7 @@
|
||||
to_chat(unpicked_client, span_danger("Sorry, the starting mafia game has too many players and you were not picked."))
|
||||
to_chat(unpicked_client, span_warning("You're still signed up, getting messages from the current round, and have another chance to join when the one starting now finishes."))
|
||||
|
||||
if(!setup.len) //don't actually have one yet, so generate a max player random setup. it's good to do this here instead of above so it doesn't generate one every time a game could possibly start.
|
||||
setup = generate_random_setup()
|
||||
prepare_game(setup,filtered_keys)
|
||||
start_game()
|
||||
return filtered_keys
|
||||
|
||||
/**
|
||||
* Called when someone signs up, and sees if there are enough people in the signup list to begin.
|
||||
@@ -990,3 +1092,5 @@
|
||||
QDEL_NULL(GLOB.mafia_game)
|
||||
var/datum/mafia_controller/MF = new()
|
||||
return MF
|
||||
|
||||
#undef MINIMUM_MAFIA_PLAYERS
|
||||
|
||||
Reference in New Issue
Block a user