From 45a7c68da19d454798d3e933b251e005e680e68f Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 11 Dec 2020 15:05:00 -0700 Subject: [PATCH] wow --- code/__DEFINES/role_preferences.dm | 1 + .../configuration/entries/general.dm | 2 - .../configuration/entries/respawns.dm | 24 ++++++++ code/controllers/subsystem/ticker.dm | 5 ++ code/modules/admin/topic.dm | 6 ++ code/modules/client/preferences.dm | 16 ++++- code/modules/jobs/job_types/_job.dm | 12 ++++ code/modules/jobs/job_types/ai.dm | 1 + code/modules/jobs/job_types/assistant.dm | 1 + code/modules/jobs/job_types/captain.dm | 1 + code/modules/jobs/job_types/chief_engineer.dm | 1 + .../jobs/job_types/chief_medical_officer.dm | 1 + code/modules/jobs/job_types/cyborg.dm | 1 + code/modules/jobs/job_types/detective.dm | 1 + .../jobs/job_types/head_of_personnel.dm | 2 +- .../jobs/job_types/head_of_security.dm | 1 + code/modules/jobs/job_types/quartermaster.dm | 1 + .../jobs/job_types/research_director.dm | 1 + .../jobs/job_types/security_officer.dm | 1 + code/modules/jobs/job_types/warden.dm | 1 + .../modules/mob/dead/new_player/new_player.dm | 5 ++ code/modules/mob/dead/observer/respawn.dm | 60 +++++++++++++++++++ code/modules/mob/mob.dm | 33 ---------- config/config.txt | 4 +- config/respawns.txt | 17 ++++++ tgstation.dme | 2 + 26 files changed, 160 insertions(+), 41 deletions(-) create mode 100644 code/controllers/configuration/entries/respawns.dm create mode 100644 code/modules/mob/dead/observer/respawn.dm create mode 100644 config/respawns.txt diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index d7487eb54b..605b3f6485 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -40,6 +40,7 @@ //#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now #define ROLE_GHOSTCAFE "ghostcafe" #define ROLE_MINOR_ANTAG "minorantag" +#define ROLE_RESPAWN "respawnsystem" //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 diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 90ec3bc289..3c93952b65 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -172,8 +172,6 @@ /datum/config_entry/string/hostedby -/datum/config_entry/flag/norespawn - /datum/config_entry/flag/guest_jobban /datum/config_entry/flag/usewhitelist diff --git a/code/controllers/configuration/entries/respawns.dm b/code/controllers/configuration/entries/respawns.dm new file mode 100644 index 0000000000..b19c8bf9d8 --- /dev/null +++ b/code/controllers/configuration/entries/respawns.dm @@ -0,0 +1,24 @@ +/// Allows usage of respawn system +/datum/config_entry/flag/respawns_enabled + config_entry_value = FALSE + +/// Minutes before allowing respawns. +/datum/config_entry/number/respawn_delay + config_entry_value = 15.0 + integer = FALSE + +/// Allows respawning as non-assistant. Overrides all others of this type. +/datum/config_entry/flag/allow_non_assistant_respawn + config_entry_value = FALSE + +/// Allows respawning as a combat role, defined as security/head. +/datum/config_entry/flag/allow_combat_role_respawn + config_entry_value = FALSE + +/// Allows respawning as the same character as a previous life +/datum/config_entry/flag/allow_same_character_respawn + config_entry_value = FALSE + +/// Observing penalizes for respawns, not just joining. +/datum/config_entry/flag/respawn_penalty_includes_observe + config_entry_value = FALSE diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 95d8928368..730ee3d6ab 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -371,6 +371,11 @@ SUBSYSTEM_DEF(ticker) if(player.ready == PLAYER_READY_TO_PLAY && player.mind) GLOB.joined_player_list += player.ckey player.create_character(FALSE) + if(player.new_character && player.client && player.client.prefs) // we cannot afford a runtime, ever + LAZYOR(player.client.prefs.slots_joined_as, player.client.prefs.slot) + LAZYOR(player.client.prefs.characters_joined_as, player.new_character.real_name)) + else + stack_trace("WARNING: Either a player did not have a new_character, did not have a client, or did not have preferences. This is VERY bad.") else player.new_player_panel() CHECK_TICK diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index ad8dd168eb..fd8204a296 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -936,6 +936,12 @@ else dat += "Mind Transfer Potion" + //Respawns + if(jobban_isbanned(M, ROLE_RESPAWN)) + dat += "Respawns" + else + dat += "Respawns" + dat += "" usr << browse(dat, "window=jobban2;size=800x450") return diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 16d6ca351d..dddb78a729 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -12,11 +12,23 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used var/max_save_slots = 24 - //non-preference stuff - var/muted = 0 + // Intra-round persistence begin + /// Flags for admin mutes + var/muted = NONE + /// Last IP the person was seen on var/last_ip + /// Last CID the person was seen on var/last_id + /// Do we log their clicks to disk? var/log_clicks = FALSE + /// Characters they have joined the round under - Lazylist of names + var/list/characters_joined_as + /// Slots they have joined the round under - Lazylist of numbers + var/list/slots_joined_as + /// Are we currently subject to respawn restrictions? Usually set by us using the "respawn" verb, but can be lifted by admins. + var/respawn_restrictions_active = FALSE + + // Intra-round persistence end var/icon/custom_holoform_icon var/list/cached_holoform_icons diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index b0ac5248c1..bb55ad45ca 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -73,6 +73,12 @@ /// Starting skill modifiers. var/list/starting_modifiers + // These can be flags but I don't care because they're never changed + /// Can you always join as this job even while respawning (should probably only be on for assistant) + var/always_can_respawn_as = FALSE + /// Is this job considered a combat role for respawning? (usually sec/command) + var/considered_combat_role = FALSE + /** * Checks if we should be created on a certain map */ @@ -118,6 +124,12 @@ //Used for a special check of whether to allow a client to latejoin as this job. /datum/job/proc/special_check_latejoin(client/C) + var/joined = LAZYLEN(C.prefs?.characters_joined_as) + if(C.prefs?.respawn_restrictions_active && (joined || CONFIG_GET(flag/respawn_penalty_includes_observe))) + if(!CONFIG_GET(flag/allow_non_assistant_respawn) && always_can_respawn_as) + return FALSE + if(!CONFIG_GET(flag/allow_combat_role_respawn) && considered_combat_role) + return FALSE return TRUE /datum/job/proc/GetAntagRep() diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index a7401791ab..d0eb690e94 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -16,6 +16,7 @@ display_order = JOB_DISPLAY_ORDER_AI var/do_special_check = TRUE threat = 5 + considered_combat_role = TRUE starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic) diff --git a/code/modules/jobs/job_types/assistant.dm b/code/modules/jobs/job_types/assistant.dm index b8fc963989..db5390f323 100644 --- a/code/modules/jobs/job_types/assistant.dm +++ b/code/modules/jobs/job_types/assistant.dm @@ -18,6 +18,7 @@ Assistant paycheck_department = ACCOUNT_CIV display_order = JOB_DISPLAY_ORDER_ASSISTANT dresscodecompliant = FALSE + always_can_respawn_as = TRUE threat = 0.2 /datum/job/assistant/get_access() diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 047a07062d..4806bf5546 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -14,6 +14,7 @@ exp_requirements = 180 exp_type = EXP_TYPE_COMMAND exp_type_department = EXP_TYPE_COMMAND + considered_combat_role = TRUE outfit = /datum/outfit/job/captain diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index 18be8c9835..902be0bdc8 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -15,6 +15,7 @@ exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_ENGINEERING + considered_combat_role = TRUE outfit = /datum/outfit/job/ce plasma_outfit = /datum/outfit/plasmaman/ce diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index 627a7a2ca1..bb5fc68809 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -15,6 +15,7 @@ exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_MEDICAL + considered_combat_role = TRUE outfit = /datum/outfit/job/cmo plasma_outfit = /datum/outfit/plasmaman/cmo diff --git a/code/modules/jobs/job_types/cyborg.dm b/code/modules/jobs/job_types/cyborg.dm index 4f74542b2a..761882894f 100644 --- a/code/modules/jobs/job_types/cyborg.dm +++ b/code/modules/jobs/job_types/cyborg.dm @@ -11,6 +11,7 @@ minimal_player_age = 21 exp_requirements = 120 exp_type = EXP_TYPE_CREW + considered_combat_role = TRUE starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic) diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index 65724765e1..c704326879 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -15,6 +15,7 @@ outfit = /datum/outfit/job/detective plasma_outfit = /datum/outfit/plasmaman/detective + considered_combat_role = TRUE access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index 41fb4b99da..f1b7d3e8c4 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -15,7 +15,7 @@ exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_SERVICE - + considered_combat_role = TRUE outfit = /datum/outfit/job/hop plasma_outfit = /datum/outfit/plasmaman/hop diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index cfd8d7f6c0..c772a8acae 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -14,6 +14,7 @@ minimal_player_age = 10 exp_requirements = 300 exp_type = EXP_TYPE_CREW + considered_combat_role = TRUE exp_type_department = EXP_TYPE_SECURITY outfit = /datum/outfit/job/hos diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm index 4c6b8e064f..301acff5c4 100644 --- a/code/modules/jobs/job_types/quartermaster.dm +++ b/code/modules/jobs/job_types/quartermaster.dm @@ -15,6 +15,7 @@ exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_SUPPLY + considered_combat_role = TRUE outfit = /datum/outfit/job/quartermaster diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index 33f7df8260..6c2cb94d13 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -15,6 +15,7 @@ exp_type_department = EXP_TYPE_SCIENCE exp_requirements = 180 exp_type = EXP_TYPE_CREW + considered_combat_role = TRUE outfit = /datum/outfit/job/rd plasma_outfit = /datum/outfit/plasmaman/rd diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index bc83eb752d..bdae7fe028 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -12,6 +12,7 @@ minimal_player_age = 7 exp_requirements = 300 exp_type = EXP_TYPE_CREW + considered_combat_role = TRUE outfit = /datum/outfit/job/security plasma_outfit = /datum/outfit/plasmaman/security diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index c909342d6f..dae3094ebe 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -12,6 +12,7 @@ minimal_player_age = 7 exp_requirements = 300 exp_type = EXP_TYPE_CREW + considered_combat_role = TRUE outfit = /datum/outfit/job/warden plasma_outfit = /datum/outfit/plasmaman/warden diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 91123c0c7f..a06fee2cf7 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -382,6 +382,9 @@ alert(src, "An administrator has disabled late join spawning.") return FALSE + if(!respawn_latejoin_check(notify = TRUE)) + return FALSE + var/arrivals_docked = TRUE if(SSshuttle.arrivals) close_spawn_windows() //In case we get held up @@ -445,6 +448,8 @@ GLOB.joined_player_list += character.ckey GLOB.latejoiners += character + LAZYOR(prefs.slots_joined_as, prefs.slot) + LAZYOR(prefs.characters_joined_as, character.real_name)) if(CONFIG_GET(flag/allow_latejoin_antagonists) && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais. if(SSshuttle.emergency) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm new file mode 100644 index 0000000000..d162e19531 --- /dev/null +++ b/code/modules/mob/dead/observer/respawn.dm @@ -0,0 +1,60 @@ +// ADMIN VERBS BEGIN +/** + * Fully returns a player to lobby, allowing them to bypass all respawn restrictions + * Works on ghosts or new players (lobby players) + * If a lobby player is selected, their restrictions are removed. + */ +/client/proc/admin_cmd_respawn_return_to_lobby() + +/** + * Allows a ghost to bypass respawn delay without lifting respawn restrictions + */ +/client/proc/admin_cmd_remove_ghost_respawn_timer() + +// ADMIN VERBS END + +/** + * Checks if we can latejoin on the currently selected slot, taking into account respawn status. + */ +/mob/dead/new_player/proc/respawn_latejoin_check(notify = FALSE) + +/** + * Attempts to respawn. + */ +/mob/dead/observer/verb/respawn() + set name = "Respawn" + set category = "OOC" + + +/mob/verb/abandon_mob() + set name = "Respawn" + set category = "OOC" + + if (CONFIG_GET(flag/norespawn)) + return + if ((stat != DEAD || !( SSticker ))) + to_chat(usr, "You must be dead to use this!") + return + + log_game("[key_name(usr)] used abandon mob.") + + to_chat(usr, "Please roleplay correctly!") + + if(!client) + log_game("[key_name(usr)] AM failed due to disconnect.") + return + client.screen.Cut() + client.screen += client.void + if(!client) + log_game("[key_name(usr)] AM failed due to disconnect.") + return + + var/mob/dead/new_player/M = new /mob/dead/new_player() + if(!client) + log_game("[key_name(usr)] AM failed due to disconnect.") + qdel(M) + return + + M.key = key +// M.Login() //wat + return diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3416a8b337..bac80d7ae7 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -457,39 +457,6 @@ else to_chat(src, "You don't have a mind datum for some reason, so you can't add a note to it.") -/mob/verb/abandon_mob() - set name = "Respawn" - set category = "OOC" - - if (CONFIG_GET(flag/norespawn)) - return - if ((stat != DEAD || !( SSticker ))) - to_chat(usr, "You must be dead to use this!") - return - - log_game("[key_name(usr)] used abandon mob.") - - to_chat(usr, "Please roleplay correctly!") - - if(!client) - log_game("[key_name(usr)] AM failed due to disconnect.") - return - client.screen.Cut() - client.screen += client.void - if(!client) - log_game("[key_name(usr)] AM failed due to disconnect.") - return - - var/mob/dead/new_player/M = new /mob/dead/new_player() - if(!client) - log_game("[key_name(usr)] AM failed due to disconnect.") - qdel(M) - return - - M.key = key -// M.Login() //wat - return - /mob/proc/transfer_ckey(mob/new_mob, send_signal = TRUE) if(!new_mob || (!ckey && new_mob.ckey)) CRASH("transfer_ckey() called [new_mob ? "on ckey-less mob with a player mob as target" : "without a valid mob target"]!") diff --git a/config/config.txt b/config/config.txt index 5be76972ab..72df74beb1 100644 --- a/config/config.txt +++ b/config/config.txt @@ -11,6 +11,7 @@ $include dynamic_config.txt $include plushies/defines.txt $include job_threats.txt $include policy.txt +$include respawns.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game # Example usage: @@ -206,9 +207,6 @@ VOTE_AUTOTRANSFER_MAXIMUM 4 ## players' votes default to "No vote" (otherwise, default to "No change") # DEFAULT_NO_VOTE -## disable abandon mob -NORESPAWN - ## disables calling del(src) on newmobs if they logout before spawnin in # DONT_DEL_NEWMOB diff --git a/config/respawns.txt b/config/respawns.txt new file mode 100644 index 0000000000..97b196135a --- /dev/null +++ b/config/respawns.txt @@ -0,0 +1,17 @@ +## Allow usage of the respawn system +RESPAWNS_ENABLED + +## Minutes delay before allowing respawns, either from death or observing. Not an integer. +RESPAWN_DELAY 15.0 + +## Allow respawning as anything but an assistant. +# ALLOW_NON_ASSISTANT_RESPAWN + +## Allow respawning as security and command. Only works if ALLOW_NON_ASSISTANT_RESPAWN is on. +# ALLOW_COMBAT_ROLE_RESPAWN + +## Allow respawning as the same character +# ALLOW_SAME_CHARACTER_RESPAWN + +## Observing is considered a respawn for the purposes of role lockouts. Defaults to disabled. When disabled, only RESPAWNING rather than returning from observe locks you out. +# RESPAWN_PENALTY_INCLUDES_OBSERVE diff --git a/tgstation.dme b/tgstation.dme index 1387748839..bdc384776c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -294,6 +294,7 @@ #include "code\controllers\configuration\entries\plushies.dm" #include "code\controllers\configuration\entries\policy.dm" #include "code\controllers\configuration\entries\resources.dm" +#include "code\controllers\configuration\entries\respawns.dm" #include "code\controllers\configuration\entries\stamina_combat.dm" #include "code\controllers\subsystem\acid.dm" #include "code\controllers\subsystem\adjacent_air.dm" @@ -2451,6 +2452,7 @@ #include "code\modules\mob\dead\observer\observer.dm" #include "code\modules\mob\dead\observer\observer_movement.dm" #include "code\modules\mob\dead\observer\orbit.dm" +#include "code\modules\mob\dead\observer\respawn.dm" #include "code\modules\mob\dead\observer\say.dm" #include "code\modules\mob\living\blood.dm" #include "code\modules\mob\living\bloodcrawl.dm"