mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-06 04:43:10 +01:00
90b974071d
## About The Pull Request If the station rolls the "Cargo Gorilla" trait, a button will now be visible on the lobby. Clicking on this button before the round has started will add you to a list of participants, one of whom will be selected to become a gorilla when the round begins. If nobody signs up (because they're really boring I guess) the job will instead appear on the latejoin menu. Once someone has become the gorilla the button will disappear.  While implementing this I noticed that an inverted check means we were never populating the "GLOB.cargo_sloth" field which means the station trait wasn't even working. BEHIND THE SCENES This also adds a generic "job station trait" which can be expanded in the future. Future developers can extend this to add other "rare jobs" with relative ease. By default I have made it so all subtypes of this trait are mutually exclusive, only one can roll at a time. This also means that I have converted "cargo gorilla" into a job, which applies most of the code previously located in the mob's typepath or in the station trait. The fact that it is a job means that **admins** can enable any number of gorillas to be present on the latejoin menu (but not the roundstart one, as it is not possible to add Cargo Gorilla to your occupation preferences) if they so desire. The random beurocratic station trait, event, and traitor item (and the job console) are not able to add gorilla slots. Because I changed "Cargo Gorilla" to a job it now no longer exists on the map until a player gains the role, and there wasn't a non-hacky way to copy the name of this round's cargo sloth. Instead I just added a small cargo gorilla name list. ## Why It's Good For The Game Makes the presence of a fun trait more visible to players. Means that people who aren't observing get a chance to be a monkey. This is a framework several other people have wanted to exist for their own features. ## Changelog 🆑 Jacquerel and Fikou qol: If the station rolls the "Cargo Gorilla" station trait. you will be able to sign up for the role from the game lobby. qol: If nobody signs up to be the Cargo Gorilla then you can select it from the Late Join menu and arrive on the arrival shuttle. fix: The Cargo Gorilla will actually spawn. /🆑
223 lines
8.0 KiB
Plaintext
223 lines
8.0 KiB
Plaintext
#define JOB_CHOICE_YES "Yes"
|
|
#define JOB_CHOICE_REROLL "Reroll"
|
|
#define JOB_CHOICE_CANCEL "Cancel"
|
|
|
|
GLOBAL_DATUM_INIT(latejoin_menu, /datum/latejoin_menu, new)
|
|
|
|
/// Makes a list of jobs and pushes them to a DM list selector. Just in case someone did a special kind of fucky-wucky with TGUI.
|
|
/datum/latejoin_menu/proc/fallback_ui(mob/dead/new_player/user)
|
|
var/list/jobs = list()
|
|
for(var/datum/job/job as anything in SSjob.joinable_occupations)
|
|
jobs += job.title
|
|
|
|
var/input_contents = input(user, "Pick a job to join as:", "Latejoin Job Selection") as null|anything in jobs
|
|
|
|
if(!input_contents)
|
|
return
|
|
|
|
user.AttemptLateSpawn(input_contents)
|
|
|
|
/datum/latejoin_menu/ui_close(mob/dead/new_player/user)
|
|
. = ..()
|
|
if(istype(user))
|
|
user.jobs_menu_mounted = TRUE // Don't flood a user's chat if they open and close the UI.
|
|
|
|
/datum/latejoin_menu/ui_interact(mob/dead/new_player/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
// In case they reopen the GUI
|
|
// FIXME: this can cause a runtime since user can be a living mob
|
|
if(istype(user))
|
|
user.jobs_menu_mounted = FALSE
|
|
addtimer(CALLBACK(src, PROC_REF(scream_at_player), user), 5 SECONDS)
|
|
|
|
ui = new(user, src, "JobSelection", "Latejoin Menu")
|
|
ui.open()
|
|
|
|
/datum/latejoin_menu/proc/scream_at_player(mob/dead/new_player/player)
|
|
if(!player.jobs_menu_mounted)
|
|
to_chat(player, span_notice("If the late join menu isn't showing, hold CTRL while clicking the join button!"))
|
|
|
|
/datum/latejoin_menu/ui_data(mob/user)
|
|
var/mob/dead/new_player/owner = user
|
|
var/list/departments = list()
|
|
var/list/data = list(
|
|
"disable_jobs_for_non_observers" = SSlag_switch.measures[DISABLE_NON_OBSJOBS],
|
|
"round_duration" = DisplayTimeText(world.time - SSticker.round_start_time, round_seconds_to = 1),
|
|
"departments" = departments,
|
|
)
|
|
if(SSshuttle.emergency)
|
|
switch(SSshuttle.emergency.mode)
|
|
if(SHUTTLE_ESCAPE)
|
|
data["shuttle_status"] = "The station has been evacuated."
|
|
if(SHUTTLE_CALL, SHUTTLE_DOCKED, SHUTTLE_IGNITING, SHUTTLE_ESCAPE)
|
|
if(!SSshuttle.canRecall())
|
|
data["shuttle_status"] = "The station is currently undergoing evacuation procedures."
|
|
|
|
for(var/datum/job/prioritized_job in SSjob.prioritized_jobs)
|
|
if(prioritized_job.current_positions >= prioritized_job.total_positions)
|
|
SSjob.prioritized_jobs -= prioritized_job
|
|
|
|
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
|
|
var/list/department_jobs = list()
|
|
var/list/department_data = list(
|
|
"jobs" = department_jobs,
|
|
"open_slots" = 0,
|
|
)
|
|
departments[department.department_name] = department_data
|
|
|
|
for(var/datum/job/job_datum as anything in department.department_jobs)
|
|
//Jobs under multiple departments should only be displayed if this is their first department or the command department
|
|
if(LAZYLEN(job_datum.departments_list) > 1 && job_datum.departments_list[1] != department.type && !(job_datum.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND))
|
|
continue
|
|
|
|
var/job_availability = owner.IsJobUnavailable(job_datum.title, latejoin = TRUE)
|
|
|
|
var/list/job_data = list(
|
|
"prioritized" = (job_datum in SSjob.prioritized_jobs),
|
|
"used_slots" = job_datum.current_positions,
|
|
"open_slots" = job_datum.total_positions < 0 ? "∞" : job_datum.total_positions,
|
|
)
|
|
|
|
if(job_availability != JOB_AVAILABLE)
|
|
if (job_datum.job_flags & JOB_HIDE_WHEN_EMPTY)
|
|
continue
|
|
job_data["unavailable_reason"] = get_job_unavailable_error_message(job_availability, job_datum.title)
|
|
|
|
if(job_datum.total_positions < 0)
|
|
department_data["open_slots"] = "∞"
|
|
|
|
if(department_data["open_slots"] != "∞")
|
|
if(job_datum.total_positions - job_datum.current_positions > 0)
|
|
department_data["open_slots"] += job_datum.total_positions - job_datum.current_positions
|
|
|
|
department_jobs[job_datum.title] = job_data
|
|
|
|
return data
|
|
|
|
/datum/latejoin_menu/ui_static_data(mob/user)
|
|
var/list/departments = list()
|
|
var/mob/dead/new_player/owner = user
|
|
|
|
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
|
|
var/list/department_jobs = list()
|
|
var/list/department_data = list(
|
|
"jobs" = department_jobs,
|
|
"color" = department.ui_color,
|
|
)
|
|
departments[department.department_name] = department_data
|
|
|
|
for(var/datum/job/job_datum as anything in department.department_jobs)
|
|
//Jobs under multiple departments should only be displayed if this is their first department or the command department
|
|
if(LAZYLEN(job_datum.departments_list) > 1 && job_datum.departments_list[1] != department.type && !(job_datum.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND))
|
|
continue
|
|
if((job_datum.job_flags & JOB_HIDE_WHEN_EMPTY) && owner.IsJobUnavailable(job_datum.title, latejoin = TRUE) != JOB_AVAILABLE)
|
|
continue
|
|
|
|
var/list/job_data = list(
|
|
"command" = !!(job_datum.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND),
|
|
"description" = job_datum.description,
|
|
)
|
|
|
|
department_jobs[job_datum.title] = job_data
|
|
|
|
return list("departments_static" = departments)
|
|
|
|
/datum/latejoin_menu/ui_state(mob/user)
|
|
return GLOB.new_player_state
|
|
|
|
/datum/latejoin_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
|
|
if(!ui.user.client || ui.user.client.interviewee || !isnewplayer(ui.user))
|
|
return TRUE
|
|
|
|
var/mob/dead/new_player/owner = ui.user
|
|
|
|
switch(action)
|
|
if("ui_mounted_with_no_bluescreen")
|
|
owner.jobs_menu_mounted = TRUE
|
|
if("select_job")
|
|
if(params["job"] == "Random")
|
|
var/job = get_random_job(owner)
|
|
if(!job)
|
|
return TRUE
|
|
|
|
params["job"] = job
|
|
|
|
if(!SSticker?.IsRoundInProgress())
|
|
tgui_alert(owner, "The round is either not ready, or has already finished...", "Oh No!")
|
|
return TRUE
|
|
|
|
if(SSlag_switch.measures[DISABLE_NON_OBSJOBS])
|
|
tgui_alert(owner, "There is an administrative lock on entering the game for non-observers!", "Oh No!")
|
|
return TRUE
|
|
|
|
//Determines Relevent Population Cap
|
|
var/relevant_cap
|
|
var/hard_popcap = CONFIG_GET(number/hard_popcap)
|
|
var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
|
|
if(hard_popcap && extreme_popcap)
|
|
relevant_cap = min(hard_popcap, extreme_popcap)
|
|
else
|
|
relevant_cap = max(hard_popcap, extreme_popcap)
|
|
|
|
if(SSticker.queued_players.len && !(ckey(owner.key) in GLOB.admin_datums))
|
|
if((living_player_count() >= relevant_cap) || (owner != SSticker.queued_players[1]))
|
|
tgui_alert(owner, "The server is full!", "Oh No!")
|
|
return TRUE
|
|
|
|
// SAFETY: AttemptLateSpawn has it's own sanity checks. This is perfectly safe.
|
|
owner.AttemptLateSpawn(params["job"])
|
|
if("viewpoll")
|
|
var/datum/poll_question/poll = locate(params["viewpoll"]) in GLOB.polls
|
|
if(!poll)
|
|
return TRUE
|
|
|
|
owner.poll_player(poll)
|
|
return TRUE
|
|
|
|
if("votepollref")
|
|
var/datum/poll_question/poll = locate(params["votepollref"]) in GLOB.polls
|
|
if(!poll)
|
|
return TRUE
|
|
|
|
owner.vote_on_poll_handler(poll, params)
|
|
return TRUE
|
|
|
|
/// Gives the user a random job that they can join as, and prompts them if they'd actually like to keep it, rerolling if not. Cancellable by the user.
|
|
/// WARNING: BLOCKS THREAD!
|
|
/datum/latejoin_menu/proc/get_random_job(mob/dead/new_player/owner)
|
|
var/list/dept_data = list()
|
|
|
|
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
|
|
for(var/datum/job/job_datum as anything in department.department_jobs)
|
|
if(owner.IsJobUnavailable(job_datum.title, latejoin = TRUE) != JOB_AVAILABLE)
|
|
continue
|
|
dept_data += job_datum.title
|
|
|
|
if(dept_data.len <= 0) //Congratufuckinglations
|
|
tgui_alert(owner, "There are literally no random jobs available for you on this server, ahelp for assistance.", "Oh No!")
|
|
return
|
|
|
|
var/random_job
|
|
|
|
while(random_job != JOB_CHOICE_YES)
|
|
if(dept_data.len <= 0)
|
|
tgui_alert(owner, "It seems that there are no more random jobs available for you!", "Oh No!")
|
|
return
|
|
|
|
var/random = pick_n_take(dept_data)
|
|
var/list/random_job_options = list(JOB_CHOICE_YES, JOB_CHOICE_REROLL, JOB_CHOICE_CANCEL)
|
|
|
|
random_job = tgui_alert(owner, "[random]?", "Random Job", random_job_options)
|
|
|
|
if(random_job == JOB_CHOICE_CANCEL)
|
|
return
|
|
if(random_job == JOB_CHOICE_YES)
|
|
return random
|
|
|
|
#undef JOB_CHOICE_YES
|
|
#undef JOB_CHOICE_REROLL
|
|
#undef JOB_CHOICE_CANCEL
|