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 01/19] 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" From 24c09edd03d48c4f7cd59e38e4aa81c6b4e9774f Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 12 Dec 2020 11:12:37 -0700 Subject: [PATCH 02/19] stuff --- code/modules/admin/admin_verbs.dm | 5 +- code/modules/client/preferences.dm | 2 + .../modules/mob/dead/new_player/new_player.dm | 1 + code/modules/mob/dead/observer/respawn.dm | 120 ++++++++++++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 52b4fa05b1..e2c12353f7 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -78,8 +78,11 @@ GLOBAL_PROTECT(admin_verbs_admin) /client/proc/mark_datum_mapview, /client/proc/hide_verbs, /*hides all our adminverbs*/ /client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/ - /datum/admins/proc/open_borgopanel + /datum/admins/proc/open_borgopanel, + /client/proc/admin_cmd_respawn_return_to_lobby, + /client/proc/admin_cmd_remove_ghost_respawn_timer ) + GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel)) GLOBAL_PROTECT(admin_verbs_ban) GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/manual_play_web_sound, /client/proc/set_round_end_sound)) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index dddb78a729..e73808cad7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -27,6 +27,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) 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 + /// time of death we consider for respawns + var/respawn_time_of_death = -INFINITY // Intra-round persistence end diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index a06fee2cf7..6d619c4fd1 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -316,6 +316,7 @@ stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised") transfer_ckey(observer, FALSE) observer.client = client + observer.client.prefs?.respawn_time_of_death = world.time observer.set_ghost_appearance() if(observer.client && observer.client.prefs) observer.real_name = observer.client.prefs.real_name diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index d162e19531..fb1873adff 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -5,11 +5,72 @@ * If a lobby player is selected, their restrictions are removed. */ /client/proc/admin_cmd_respawn_return_to_lobby() + set name = "Respawn Player (Unrestricted)" + set desc = "Gives a player an unrestricted respawn, resetting all respawn restrictions for them." + set category = "Admin" + + var/list/mob/valid = list() + for(var/mob/dead/observer/I in GLOB.dead_mob_list) + if(!I.client) + continue + valid["[I.ckey] - Observing: [I]"] = I.ckey + for(var/mob/dead/new_player/I in GLOB.dead_mob_list) + if(!I.client || !I.prefs.respawn_restrictions_active) + continue + valid["[I.ckey] - IN LOBBY"] = I.ckey + var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid] + var/client/player = GLOB.directory[ckey] + if(!player) + to_chat(src, "Client not found.") + return + var/mob/M = player.mob + if(istype(M, /mob/dead/observer)) + var/mob/dead/observer/O = M + var/confirm = alert(src, "Send [O]([ckey]) back to the lobby without respawn restrictions?", "Send to Lobby", "Yes", "No") + if(confirm != "Yes") + return + message_admins("[key_name_admin(src)] gave [key_name_admin(O)] a full respawn and sent them back to the lobby.") + log_admin("[key_name(src)] gave [key_name(O)] a full respawn and sent them back to the lobby.") + to_chat(O, "You have been given a full respawn.") + O.do_respawn(FALSE) + else if(istype(M, /mob/dead/new_player)) + var/mob/dead/new_player/NP = M + var/confirm = alert(src, "Remove [NP]'s respawn restrictions?", "Remove Restrictions", "Yes", "No") + if(confirm != "Yes") + return + message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.") + log_admins("[key_name(src)] removed [ckey]'s respawn restrictions") + NP.client.prefs.respawn_restrictions_active = FALSE + to_chat(NP, "Your respawn restrictions have been removed.") + else + CRASH("Invalid mobtype") /** * Allows a ghost to bypass respawn delay without lifting respawn restrictions */ /client/proc/admin_cmd_remove_ghost_respawn_timer() + set name = "Remove Respawn Timer for Player" + set desc = "Removes a player's respawn timer without removing their respawning restrictions." + set category = "Admin" + + var/list/mob/dead/observer/valid = list() + for(var/mob/dead/observer/i in GLOB.dead_mob_list) + if(!I.client) + continue + valid["[I.ckey] - [I.name]"] = I + var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid] + + if(!O.client) + to_chat(src, "[O] has no client.") + return + var/timeleft = O.time_left_to_respawn() + if(!timeleft) + to_chat(src, "[O] can already respawn.") + return + message_admins("[key_name_admin(src)] removed [key_name_admin(O)]'s respawn timer.") + log_admin("[key_name(src)] removed [key_name(O)]'s respawn timer.") + O.client.prefs.respawn_time_of_death = -INFINITY + to_chat(O, "Your respawn timer has been removed.") // ADMIN VERBS END @@ -17,6 +78,19 @@ * 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) + var/can_same_person = CONFIG_GET(flag/allow_same_character_respawn) + if(can_same_person) + return TRUE + var/nameless = client.prefs.nameless + var/randomname = client.prefs.be_random_name + var/randombody = client.prefs.be_random_body + if(randombody && (nameless || randomname)) + return TRUE // somewhat unrecognizable + if(client.prefs.slots_joined_as && (client.prefs.default_slot in client.prefs.slots_joined_as)) + return FALSE + if((!nameless && !randomname) && (client.prefs.characters_joined_as && (client.prefs.real_name in client.prefs.characters_joined_as))) + return FALSE + return TRUE /** * Attempts to respawn. @@ -25,6 +99,52 @@ set name = "Respawn" set category = "OOC" + var/timeleft = time_left_to_respawn() + if(timeleft) + to_chat(src, "It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.") + return + do_respawn(TRUE) + +/** + * Gets time left until we can respawn. Returns 0 if we can respawn now. + */ +/mob/dead/observer/verb/time_left_to_respawn() + ASSERT(client) + return max(0, (CONFIG_GET(number/respawn_delay) MINUTES + client.prefs.respawn_time_of_death) - world.time) + +/** + * Handles respawning + */ +/mob/dead/observer/proc/do_respawn(penalize) + if(!client) + return + if(isnull(penalize)) + penalize = client.prefs.respawn_restrictions_active + client.prefs.respawn_restrictions_active = penalize + + to_chat(src, "You have been respawned to the lobby. \ + Remember to take heed of rules regarding round knowledge - notably, that ALL past lives are forgotten. \ + Any character you join as has NO knowledge of round events unless specified otherwise by an admin.") + + log_game("[key_name(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.") + transfer_to_lobby() + +/** + * Actual proc that removes us and puts us back on lobby + */ +/mob/dead/observer/proc/transfer_to_lobby() + if(!client) // if no one's in us we can just be deleted + qdel(src) + return + client.screen.Cut() + client.view_size.resetToDefault() + client.generate_clickcatcher() + client.apply_clickcatcher() + client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref)) + client.view_size.resetToDefault() + + var/mob/dead/new_player/M = new /mob/dead/new_player + M.ckey = ckey /mob/verb/abandon_mob() set name = "Respawn" From 07d8e72125113d964b34b4fe3b3e33f4dd550fa1 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 12 Dec 2020 11:19:45 -0700 Subject: [PATCH 03/19] fix --- code/controllers/subsystem/ticker.dm | 2 +- code/datums/world_topic.dm | 2 +- code/modules/admin/admin.dm | 4 +- .../modules/mob/dead/new_player/new_player.dm | 4 +- code/modules/mob/dead/observer/respawn.dm | 43 +++---------------- code/modules/mob/living/death.dm | 4 ++ 6 files changed, 17 insertions(+), 42 deletions(-) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 730ee3d6ab..e58d05f0d8 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -373,7 +373,7 @@ SUBSYSTEM_DEF(ticker) 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)) + 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 diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 261e423640..7a1f0f6980 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -164,7 +164,7 @@ . = list() .["version"] = GLOB.game_version .["mode"] = "hidden" //CIT CHANGE - hides the gamemode in topic() calls to prevent meta'ing the gamemode - .["respawn"] = config ? !CONFIG_GET(flag/norespawn) : FALSE + .["respawn"] = config ? CONFIG_GET(flag/respawns_enabled) : FALSE .["enter"] = GLOB.enter_allowed .["vote"] = CONFIG_GET(flag/allow_vote_mode) .["ai"] = CONFIG_GET(flag/allow_ai) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index d4b2d03428..d4afc3dbb4 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -679,8 +679,8 @@ set category = "Server" set desc="Respawn basically" set name="Toggle Respawn" - var/new_nores = !CONFIG_GET(flag/norespawn) - CONFIG_SET(flag/norespawn, new_nores) + var/new_nores = CONFIG_GET(flag/respawns_enabled) + CONFIG_SET(flag/respawns_enabled, !new_nores) if (!new_nores) to_chat(world, "You may now respawn.", confidential = TRUE) else diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 6d619c4fd1..09975ed7b9 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -449,8 +449,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)) + LAZYOR(character.client.prefs.slots_joined_as, prefs.slot) + LAZYOR(character.client.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 index fb1873adff..0ccdc460cf 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -15,7 +15,7 @@ continue valid["[I.ckey] - Observing: [I]"] = I.ckey for(var/mob/dead/new_player/I in GLOB.dead_mob_list) - if(!I.client || !I.prefs.respawn_restrictions_active) + if(!I.client || !I.client.prefs.respawn_restrictions_active) continue valid["[I.ckey] - IN LOBBY"] = I.ckey var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid] @@ -39,7 +39,7 @@ if(confirm != "Yes") return message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.") - log_admins("[key_name(src)] removed [ckey]'s respawn restrictions") + log_admin("[key_name(src)] removed [ckey]'s respawn restrictions") NP.client.prefs.respawn_restrictions_active = FALSE to_chat(NP, "Your respawn restrictions have been removed.") else @@ -54,7 +54,7 @@ set category = "Admin" var/list/mob/dead/observer/valid = list() - for(var/mob/dead/observer/i in GLOB.dead_mob_list) + for(var/mob/dead/observer/I in GLOB.dead_mob_list) if(!I.client) continue valid["[I.ckey] - [I.name]"] = I @@ -99,6 +99,10 @@ set name = "Respawn" set category = "OOC" + if(!CONFIG_GET(flag/respawns_enabled)) + to_chat(src, "Respawns are disabled in configuration.") + return + var/timeleft = time_left_to_respawn() if(timeleft) to_chat(src, "It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.") @@ -145,36 +149,3 @@ var/mob/dead/new_player/M = new /mob/dead/new_player M.ckey = ckey - -/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/living/death.dm b/code/modules/mob/living/death.dm index c605f91528..f0caa63a1a 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -66,6 +66,10 @@ GLOB.alive_mob_list -= src if(!gibbed) GLOB.dead_mob_list += src + if(mind.key) + var/datum/preferences/P = GLOB.preferences_datums[ckey(mind.key)] + if(P) + P.respawn_time_of_death = world.time set_drugginess(0) set_disgust(0) SetSleeping(0, 0) From a4688557d7424bf3b852c6186bcf9a4f166c9b64 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 13 Dec 2020 02:29:31 -0700 Subject: [PATCH 04/19] Cryo --- code/controllers/subsystem/ticker.dm | 2 +- code/game/machinery/cryopod.dm | 197 +++++++----------- .../modules/mob/dead/new_player/new_player.dm | 2 +- 3 files changed, 83 insertions(+), 118 deletions(-) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index e58d05f0d8..198c380f41 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -372,7 +372,7 @@ SUBSYSTEM_DEF(ticker) 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.slots_joined_as, player.client.prefs.default_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.") diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 5bc0ed20b0..4019a00531 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -22,17 +22,16 @@ //Used for logging people entering cryosleep and important items they are carrying. var/list/frozen_crew = list() - var/list/frozen_items = list() - - // Used for containing rare items traitors need to steal, so it's not - // game-over if they get iced - var/list/objective_items = list() - // A cache of theft datums so you don't have to re-create them for - // each item check - var/list/theft_cache = list() + var/list/obj/stored_packages = list() var/allow_items = TRUE +/obj/machinery/computer/cryopod/deconstruct() + . = ..() + for(var/i in stored_packages) + var/obj/O = i + O.forceMove(drop_location()) + /obj/machinery/computer/cryopod/attack_ai() attack_hand() @@ -70,8 +69,8 @@ if(!frozen_items.len) dat += "There has been no storage usage at this terminal.
" else - for(var/obj/item/I in frozen_items) - dat += "[I.name]
" + for(var/obj/O in stored_packages) + dat += "[O.name]
" dat += "
" var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control") @@ -87,25 +86,27 @@ add_fingerprint(user) if(href_list["item"]) - if(!allowed(user)) + if(!allowed(user) && !(obj_flags & EMAGGED)) to_chat(user, "Access Denied.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) updateUsrDialog() return - if(!allow_items) return - if(frozen_items.len == 0) + if(!allow_items) + return + + if(stored_packages.len == 0) to_chat(user, "There is nothing to recover from storage.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) updateUsrDialog() return - var/obj/item/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items + var/obj/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in stored_packages playsound(src, "terminal_type", 25, 0) if(!I) return - if(!(I in frozen_items)) + if(!(I in stored_packages)) to_chat(user, "\The [I] is no longer in storage.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) updateUsrDialog() @@ -117,20 +118,21 @@ I.forceMove(drop_location()) if(user && Adjacent(user) && user.can_hold_items()) user.put_in_hands(I) - frozen_items -= I + stored_packages -= I updateUsrDialog() else if(href_list["allitems"]) playsound(src, "terminal_type", 25, 0) - if(!allowed(user)) + if(!allowed(user) && !(obj_flags & EMAGGED)) to_chat(user, "Access Denied.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) updateUsrDialog() return + if(!allow_items) return - if(frozen_items.len == 0) + if(stored_packages.len == 0) to_chat(user, "There is nothing to recover from storage.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) return @@ -138,10 +140,10 @@ visible_message("The console beeps happily as it disgorges the desired objects.") playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - for(var/obj/item/I in frozen_items) - I.forceMove(drop_location()) - frozen_items -= I - updateUsrDialog() + for(var/obj/O in stored_packages) + O.forceMove(get_turf(src)) + stored_packages.Cut() + updateUsrDialog() else if (href_list["menu"]) src.menu = text2num(href_list["menu"]) @@ -159,6 +161,9 @@ /obj/machinery/computer/cryopod/contents_explosion() return +/obj/machinery/computer/cryopod/contents_explosion() + return //don't blow everyone's shit up. + //Cryopods themselves. /obj/machinery/cryopod name = "cryogenic freezer" @@ -177,44 +182,9 @@ var/despawn_world_time = null // Used to keep track of the safe period. var/obj/machinery/computer/cryopod/control_computer + var/item_storage_type = /obj/item/storage/box/blue //with how storage components work this can be anything the player can open or anything with a storage component. var/last_no_computer_message = 0 - // These items are preserved when the process() despawn proc occurs. - var/static/list/preserve_items = typecacheof(list( - /obj/item/hand_tele, - /obj/item/card/id/captains_spare, - /obj/item/aicard, - /obj/item/mmi, - /obj/item/paicard, - /obj/item/gun, - /obj/item/pinpointer, - /obj/item/clothing/shoes/magboots, - /obj/item/areaeditor/blueprints, - /obj/item/clothing/head/helmet/space, - /obj/item/clothing/suit/space, - /obj/item/clothing/suit/armor, - /obj/item/defibrillator/compact, - /obj/item/reagent_containers/hypospray/CMO, - /obj/item/clothing/accessory/medal/gold/captain, - /obj/item/clothing/gloves/krav_maga, - /obj/item/nullrod, - /obj/item/tank/jetpack, - /obj/item/documents, - /obj/item/nuke_core_container - )) - // These items will NOT be preserved - var/static/list/do_not_preserve_items = typecacheof(list( - /obj/item/mmi/posibrain, - /obj/item/gun/energy/laser/mounted, - /obj/item/gun/energy/e_gun/advtaser/mounted, - /obj/item/gun/ballistic/revolver/grenadelauncher/cyborg, - /obj/item/gun/energy/disabler/cyborg, - /obj/item/gun/energy/e_gun/advtaser/cyborg, - /obj/item/gun/energy/printer, - /obj/item/gun/energy/kinetic_accelerator/cyborg, - /obj/item/gun/energy/laser/cyborg - )) - /obj/machinery/cryopod/Initialize(mapload) . = ..() update_icon() @@ -286,73 +256,72 @@ despawn_occupant() -#define CRYO_DESTROY 0 -#define CRYO_PRESERVE 1 -#define CRYO_OBJECTIVE 2 -#define CRYO_IGNORE 3 -#define CRYO_DESTROY_LATER 4 - -/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I) - for(var/datum/objective_item/steal/T in control_computer.theft_cache) - if(istype(I, T.targetitem) && T.check_special_completion(I)) - return CRYO_OBJECTIVE - if(preserve_items[I] && !do_not_preserve_items[I]) - return CRYO_PRESERVE - return CRYO_DESTROY - // This function can not be undone; do not call this unless you are sure /obj/machinery/cryopod/proc/despawn_occupant() if(!control_computer) find_control_computer() var/mob/living/mob_occupant = occupant - var/list/obj/item/cryo_items = list() + + var/list/obj/item/storing = list() + var/list/obj/item/destroying = list() + var/list/obj/item/destroy_later = list() investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS) - //Handle Borg stuff first + var/atom/target_store = (control_computer?.allow_items && control_computer) || src //the double control computer check makes it return the control computer. + var/drop_to_ground = !istype(target_store, /obj/machinery/computer/cryopod) + if(iscyborg(mob_occupant)) var/mob/living/silicon/robot/R = mob_occupant if(R.mmi?.brain) - cryo_items[R.mmi] = CRYO_DESTROY_LATER - cryo_items[R.mmi.brain] = CRYO_DESTROY_LATER - for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc - for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags - cryo_items[O] = should_preserve_item(O) - O.forceMove(src) - R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over. - - //Drop all items into the pod. - for(var/obj/item/I in mob_occupant) - if(cryo_items[I] == CRYO_IGNORE || cryo_items[I] ==CRYO_DESTROY_LATER) - continue - cryo_items[I] = should_preserve_item(I) - mob_occupant.transferItemToLoc(I, src, TRUE) - if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items. - if(cryo_items[I] != CRYO_DESTROY) // Don't remove the contents of things that need preservation + destroy_later += R.mmi + destroy_later += R.mmi.brain + for(var/i in R.module) + if(!isitem(i)) + destroying += i continue - for(var/obj/item/O in I.contents) - cryo_items[O] = should_preserve_item(O) - O.forceMove(src) + var/obj/item/I = i + // let's be honest we only care about the trash bag don't beat around the bush + if(SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE)) + storing += I.contents + for(var/atom/movable/AM in I.contents) + AM.forceMove(src) + R.module.remove_module(I, TRUE) + else + var/list/gear = list() + if(iscarbon(mob_occupant)) // sorry simp-le-mobs deserve no mercy + var/mob/living/carbon/C = mob_occupant + gear = C.get_all_gear() + for(var/i in gear) + var/obj/item/I = i + I.forceMove(src) + if(!istype(I)) + destroying += I + continue + if(I.item_flags & (DROPDEL | ABSTRACT)) + destroying += I + continue + if(HAS_TRAIT(I, TRAIT_NODROP)) + destroying += I + continue + storing += I - for(var/A in cryo_items) - var/obj/item/I = A - if(QDELETED(I)) //edge cases and DROPDEL. - continue - var/preserve = cryo_items[I] - if(preserve == CRYO_DESTROY_LATER) - continue - if(preserve != CRYO_IGNORE) - if(preserve == CRYO_DESTROY) - qdel(I) - else if(control_computer?.allow_items) - control_computer.frozen_items += I - if(preserve == CRYO_OBJECTIVE) - control_computer.objective_items += I - I.moveToNullspace() - else - I.forceMove(loc) - cryo_items -= I + // get rid of mobs + for(var/mob/living/L in mob_occupant.GetAllContents()) + L.forceMove(drop_location()) + + if(storing.len) + var/obj/O = new item_storage_type + O.name = "cryogenic retrieval package: [mob_occupant.real_name]" + for(var/i in stored) + var/obj/item/I = i + I.forceMove(O) + O.forceMove(drop_to_ground? target_store.drop_location() : target_store) + if((target_store == control_computer) && !drop_to_ground) + control_computer.stored_packages += O + + QDEL_LIST(destroying) //Update any existing objectives involving this mob. for(var/i in GLOB.objectives) @@ -417,16 +386,12 @@ mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE) QDEL_NULL(occupant) - for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left) - var/atom/A = I - if(!QDELETED(A)) - qdel(A) + QDEL_LIST(destroy_later) open_machine() name = initial(name) #undef CRYO_DESTROY #undef CRYO_PRESERVE -#undef CRYO_OBJECTIVE #undef CRYO_IGNORE #undef CRYO_DESTROY_LATER diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 09975ed7b9..7acf6ad32c 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -449,7 +449,7 @@ GLOB.joined_player_list += character.ckey GLOB.latejoiners += character - LAZYOR(character.client.prefs.slots_joined_as, prefs.slot) + LAZYOR(character.client.prefs.slots_joined_as, character.client.prefs.default_slot) LAZYOR(character.client.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. From 61c08ba42207c13b86089189ee1c730da49bdcdb Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 13 Dec 2020 02:29:53 -0700 Subject: [PATCH 05/19] fine --- config/respawns.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/respawns.txt b/config/respawns.txt index 97b196135a..79eb53469c 100644 --- a/config/respawns.txt +++ b/config/respawns.txt @@ -5,7 +5,7 @@ RESPAWNS_ENABLED RESPAWN_DELAY 15.0 ## Allow respawning as anything but an assistant. -# ALLOW_NON_ASSISTANT_RESPAWN +ALLOW_NON_ASSISTANT_RESPAWN ## Allow respawning as security and command. Only works if ALLOW_NON_ASSISTANT_RESPAWN is on. # ALLOW_COMBAT_ROLE_RESPAWN From 99709a1a35d0613eef82271d5d0709f5b2e52261 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 13 Dec 2020 04:30:00 -0700 Subject: [PATCH 06/19] fix --- code/game/machinery/cryopod.dm | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 4019a00531..2ba902e4c2 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -66,7 +66,7 @@ if(3) dat += "<< Back

" dat += "

Recently stored objects




" - if(!frozen_items.len) + if(!stored_packages.len) dat += "There has been no storage usage at this terminal.
" else for(var/obj/O in stored_packages) @@ -314,7 +314,7 @@ if(storing.len) var/obj/O = new item_storage_type O.name = "cryogenic retrieval package: [mob_occupant.real_name]" - for(var/i in stored) + for(var/i in storing) var/obj/item/I = i I.forceMove(O) O.forceMove(drop_to_ground? target_store.drop_location() : target_store) @@ -390,11 +390,6 @@ open_machine() name = initial(name) -#undef CRYO_DESTROY -#undef CRYO_PRESERVE -#undef CRYO_IGNORE -#undef CRYO_DESTROY_LATER - /obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user) if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled) return From e79ce41f24041a3ae426413e67532cab6994b3a3 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 13 Dec 2020 16:41:01 -0700 Subject: [PATCH 07/19] Update code/modules/mob/living/death.dm Co-authored-by: DeltaFire <46569814+DeltaFire15@users.noreply.github.com> --- code/modules/mob/living/death.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index f0caa63a1a..24e91f6051 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -66,7 +66,7 @@ GLOB.alive_mob_list -= src if(!gibbed) GLOB.dead_mob_list += src - if(mind.key) + if(mind?.key) var/datum/preferences/P = GLOB.preferences_datums[ckey(mind.key)] if(P) P.respawn_time_of_death = world.time From 4451a96997b0fdb5641a89eb7037bbe8c85a0ef5 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 13 Dec 2020 20:12:14 -0700 Subject: [PATCH 08/19] fixes --- code/game/machinery/cryopod.dm | 2 +- code/modules/mob/dead/observer/observer.dm | 5 +++++ code/modules/mob/dead/observer/respawn.dm | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 2ba902e4c2..c9c555e331 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -308,7 +308,7 @@ storing += I // get rid of mobs - for(var/mob/living/L in mob_occupant.GetAllContents()) + for(var/mob/living/L in mob_occupant.GetAllContents() - mob_occupant) L.forceMove(drop_location()) if(storing.len) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 0c57c13e3f..b16903f062 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -277,6 +277,11 @@ Works together with spawning an observer, noted above. if (client && client.prefs && client.prefs.auto_ooc) if (!(client.prefs.chat_toggles & CHAT_OOC)) client.prefs.chat_toggles ^= CHAT_OOC + if(ckey && penalize) + var/datum/preferences/P = GLOB.preferences_datums[ckey] + if(P) + P.respawn_restrictions_active = TRUE + P.respawn_time_of_death = world.time transfer_ckey(ghost, FALSE) ghost.client.init_verbs() if(penalize) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index 0ccdc460cf..5a5a4572bd 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -87,8 +87,12 @@ if(randombody && (nameless || randomname)) return TRUE // somewhat unrecognizable if(client.prefs.slots_joined_as && (client.prefs.default_slot in client.prefs.slots_joined_as)) + if(notify) + to_chat(src, "You cannot respawn on the same slot. Joined slots: [english_list(client.prefs.slots_joined_as)].") return FALSE if((!nameless && !randomname) && (client.prefs.characters_joined_as && (client.prefs.real_name in client.prefs.characters_joined_as))) + if(notify) + to_chat(src, "You cannot respawn on the same character. Joined slots: [english_list(client.prefs.characters_joined_as)].") return FALSE return TRUE From 413bd23d0ab1b57318caa03610fcc296c179236e Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 13 Dec 2020 23:07:12 -0700 Subject: [PATCH 09/19] dnr prevention --- code/modules/client/preferences.dm | 2 ++ code/modules/mob/dead/observer/observer.dm | 6 ++++-- code/modules/mob/dead/observer/respawn.dm | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 0cf03e3a84..a634810dbf 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -29,6 +29,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/respawn_restrictions_active = FALSE /// time of death we consider for respawns var/respawn_time_of_death = -INFINITY + /// did they DNR? used to prevent respawns. + var/dnr_triggered = FALSE // Intra-round persistence end diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index b16903f062..800f704ab6 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -428,12 +428,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(usr, "You're already stuck out of your body!") return FALSE - var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. ","Are you sure you want to stay dead?","Yes","No") + var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. THIS WILL ALSO STOP YOU FROM RESPAWNING!!!","Are you sure you want to stay dead and never respawn?","Yes","No") + if(response != "Yes") return can_reenter_corpse = FALSE - to_chat(src, "You can no longer be brought back into your body.") + client.prefs?.dnr_triggered = TRUE + to_chat(src, "You can no longer be brought back into your body or respawn.") return TRUE /mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source, flashwindow = TRUE) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index 5a5a4572bd..a53fc514b8 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -33,6 +33,7 @@ log_admin("[key_name(src)] gave [key_name(O)] a full respawn and sent them back to the lobby.") to_chat(O, "You have been given a full respawn.") O.do_respawn(FALSE) + O.client.prefs.dnr_triggered = FALSE else if(istype(M, /mob/dead/new_player)) var/mob/dead/new_player/NP = M var/confirm = alert(src, "Remove [NP]'s respawn restrictions?", "Remove Restrictions", "Yes", "No") @@ -41,6 +42,7 @@ message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.") log_admin("[key_name(src)] removed [ckey]'s respawn restrictions") NP.client.prefs.respawn_restrictions_active = FALSE + NP.client.prefs.dnr_triggered = FALSE to_chat(NP, "Your respawn restrictions have been removed.") else CRASH("Invalid mobtype") @@ -107,6 +109,10 @@ to_chat(src, "Respawns are disabled in configuration.") return + if(client.prefs.dnr_triggered) + to_chat(src, "You cannot respawn as you have enabled DNR.") + return + var/timeleft = time_left_to_respawn() if(timeleft) to_chat(src, "It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.") From 2844d2e4de4228b08ecd22c9da411a1e863bdb72 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Mon, 14 Dec 2020 06:01:32 -0700 Subject: [PATCH 10/19] fix --- code/modules/mob/dead/observer/respawn.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index a53fc514b8..e2a85d11d8 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -80,6 +80,8 @@ * 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) + if(!client.prefs.respawn_restrictions_active) + return TRUE var/can_same_person = CONFIG_GET(flag/allow_same_character_respawn) if(can_same_person) return TRUE From e87cc2780333c3c5c7fb275db53192ac2ed6ada4 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Tue, 15 Dec 2020 07:21:06 -0700 Subject: [PATCH 11/19] modifications --- code/controllers/configuration/entries/respawns.dm | 5 +++++ code/game/machinery/cryopod.dm | 2 +- code/modules/admin/topic.dm | 7 +++++-- code/modules/client/preferences.dm | 2 ++ code/modules/mob/dead/observer/observer.dm | 3 ++- code/modules/mob/dead/observer/respawn.dm | 13 ++++++++++--- config/respawns.txt | 3 +++ 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/code/controllers/configuration/entries/respawns.dm b/code/controllers/configuration/entries/respawns.dm index b19c8bf9d8..d92f4ec394 100644 --- a/code/controllers/configuration/entries/respawns.dm +++ b/code/controllers/configuration/entries/respawns.dm @@ -7,6 +7,11 @@ config_entry_value = 15.0 integer = FALSE +/// Minutes before allowing respawn, if user cryo'd. +/datum/config_entry/number/respawn_delay_cryo + config_entry_value = 5.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 diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index c9c555e331..31ae77848f 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -383,7 +383,7 @@ // Ghost and delete the mob. if(!mob_occupant.get_ghost(1)) - mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE) + mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE, cryo = TRUE) QDEL_NULL(occupant) QDEL_LIST(destroy_later) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index fd8204a296..e0434a6fea 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1805,12 +1805,15 @@ if(alert(usr, "Send [key_name(M)] back to Lobby?", "Message", "Yes", "No") != "Yes") return - log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby.") - message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby.") + log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby, removing their respawn restrictions if they existed.") + message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby, removing their respawn restrictions if they existed.") var/mob/dead/new_player/NP = new() NP.ckey = M.ckey qdel(M) + if(GLOB.preferences_datums[NP.ckey]) + var/datum/preferences/P = GLOB.preferences_datums[NP.ckey] + P.respawn_restrictions_active = FALSE else if(href_list["tdome1"]) if(!check_rights(R_FUN)) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index a634810dbf..e97f6dc3f4 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -31,6 +31,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/respawn_time_of_death = -INFINITY /// did they DNR? used to prevent respawns. var/dnr_triggered = FALSE + /// did they cryo on their last ghost? + var/respawn_did_cryo = FALSE // Intra-round persistence end diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 800f704ab6..9493d11792 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -264,7 +264,7 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body Works together with spawning an observer, noted above. */ -/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE) +/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE, cryo = FALSE) var/sig_flags = SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize) penalize = !(sig_flags & COMPONENT_DO_NOT_PENALIZE_GHOSTING) && (suiciding || penalize) // suicide squad. voluntary_ghosted = voluntary @@ -282,6 +282,7 @@ Works together with spawning an observer, noted above. if(P) P.respawn_restrictions_active = TRUE P.respawn_time_of_death = world.time + P.respawn_did_cryo = cryo transfer_ckey(ghost, FALSE) ghost.client.init_verbs() if(penalize) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index e2a85d11d8..53c6eef4c9 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -18,7 +18,10 @@ if(!I.client || !I.client.prefs.respawn_restrictions_active) continue valid["[I.ckey] - IN LOBBY"] = I.ckey - var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid] + if(!valid.len) + to_chat(src, "No player found that is either a ghost or is in lobby with restrictions active.") + return + var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid var/client/player = GLOB.directory[ckey] if(!player) to_chat(src, "Client not found.") @@ -60,7 +63,11 @@ if(!I.client) continue valid["[I.ckey] - [I.name]"] = I - var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid] + + if(!valid.len) + to_chat(src, "No logged in ghosts found.") + return + var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid if(!O.client) to_chat(src, "[O] has no client.") @@ -126,7 +133,7 @@ */ /mob/dead/observer/verb/time_left_to_respawn() ASSERT(client) - return max(0, (CONFIG_GET(number/respawn_delay) MINUTES + client.prefs.respawn_time_of_death) - world.time) + return max(0, ((client.prefs.respawn_did_cryo? CONFIG_GET(number/respawn_delay_cryo) : CONFIG_GET(number/respawn_delay)) MINUTES + client.prefs.respawn_time_of_death) - world.time) /** * Handles respawning diff --git a/config/respawns.txt b/config/respawns.txt index 79eb53469c..46a4bb0e07 100644 --- a/config/respawns.txt +++ b/config/respawns.txt @@ -4,6 +4,9 @@ RESPAWNS_ENABLED ## Minutes delay before allowing respawns, either from death or observing. Not an integer. RESPAWN_DELAY 15.0 +## Minutes delay before allowing respawns, if the user cryo'd. Not an integer. +RESPAWN_DELAY_CRYO 5.0 + ## Allow respawning as anything but an assistant. ALLOW_NON_ASSISTANT_RESPAWN From 0a593013e0d84bf829baa6b451436c0b4d489374 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Tue, 15 Dec 2020 07:23:46 -0700 Subject: [PATCH 12/19] wew --- code/modules/mob/dead/observer/respawn.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index 53c6eef4c9..a31fdd4bf4 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -21,7 +21,7 @@ if(!valid.len) to_chat(src, "No player found that is either a ghost or is in lobby with restrictions active.") return - var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid + var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid] var/client/player = GLOB.directory[ckey] if(!player) to_chat(src, "Client not found.") @@ -67,7 +67,7 @@ if(!valid.len) to_chat(src, "No logged in ghosts found.") return - var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid + var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid] if(!O.client) to_chat(src, "[O] has no client.") From a7aa7f24662f004a41115b0c39d0b8545feff940 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Tue, 15 Dec 2020 07:43:35 -0700 Subject: [PATCH 13/19] delete pdas --- code/game/machinery/cryopod.dm | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 31ae77848f..5cee613ffd 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -272,6 +272,9 @@ var/atom/target_store = (control_computer?.allow_items && control_computer) || src //the double control computer check makes it return the control computer. var/drop_to_ground = !istype(target_store, /obj/machinery/computer/cryopod) + var/mind_identity = mob_occupant.mind?.name + var/occupant_identity = mob_occupant.real_name + if(iscyborg(mob_occupant)) var/mob/living/silicon/robot/R = mob_occupant if(R.mmi?.brain) @@ -305,7 +308,21 @@ if(HAS_TRAIT(I, TRAIT_NODROP)) destroying += I continue - storing += I + // WEE WOO SNOWFLAKE TIME + if(istype(I, /obj/item/pda)) + var/obj/item/pda/P = I + if((P.owner == mind_identity) || (P.owner == occupant_identity)) + destroying += P + else + storing += P + else if(istype(I, /obj/item/card/id)) + var/obj/item/card/id/idcard = I + if((idcard.registered_name == mind_identity) || (idcard.registered_name == occupant_identity)) + destroying += idcard + else + storing += idcard + else + storing += I // get rid of mobs for(var/mob/living/L in mob_occupant.GetAllContents() - mob_occupant) From ebd6e0cbec9c914c23968defd40d4aea7cb47651 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Thu, 17 Dec 2020 04:14:04 -0700 Subject: [PATCH 14/19] no backapck in backpack --- code/game/machinery/cryopod.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 5cee613ffd..ea41d77e2a 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -164,6 +164,10 @@ /obj/machinery/computer/cryopod/contents_explosion() return //don't blow everyone's shit up. +/// The box +/obj/item/storage/box/blue/cryostorage_items + w_class = WEIGHT_CLASS_HUGE + //Cryopods themselves. /obj/machinery/cryopod name = "cryogenic freezer" @@ -182,7 +186,7 @@ var/despawn_world_time = null // Used to keep track of the safe period. var/obj/machinery/computer/cryopod/control_computer - var/item_storage_type = /obj/item/storage/box/blue //with how storage components work this can be anything the player can open or anything with a storage component. + var/item_storage_type = /obj/item/storage/box/blue/cryostorage_items //with how storage components work this can be anything the player can open or anything with a storage component. var/last_no_computer_message = 0 /obj/machinery/cryopod/Initialize(mapload) From ce10278c5a84cc5ed915720dc7f14990c13dcea1 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 20 Dec 2020 19:25:49 -0700 Subject: [PATCH 15/19] changes --- .../configuration/entries/respawns.dm | 18 ++++++++++++++++++ code/modules/mob/dead/new_player/new_player.dm | 4 +++- code/modules/mob/dead/observer/respawn.dm | 11 +++++++++++ config/respawns.txt | 9 +++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/code/controllers/configuration/entries/respawns.dm b/code/controllers/configuration/entries/respawns.dm index d92f4ec394..69e48ed820 100644 --- a/code/controllers/configuration/entries/respawns.dm +++ b/code/controllers/configuration/entries/respawns.dm @@ -27,3 +27,21 @@ /// Observing penalizes for respawns, not just joining. /datum/config_entry/flag/respawn_penalty_includes_observe config_entry_value = FALSE + +/// Minutes from roundstart before someone can respawn +/datum/config_entry/flag/respawn_minimum_delay_roundstart + config_entry_value = 30.0 + integer = FALSE + +/// Gamemode config tags that are banned from respawning +/datum/config_entry/keyed_list/respawn_chaos_gamemodes + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_FLAG + +/datum/config_entry/keyed_list/respawn_chaos_gamemodes/ValidateListEntry(key_name, key_value) + . = ..() + return . && (key_name in config.modes) + +/datum/config_entry/keyed_list/respawn_chaos_gamemodes/preprocess_key(key) + . = ..() + return lowertext(key) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 7acf6ad32c..72ec3d06f6 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -294,7 +294,9 @@ ready = PLAYER_NOT_READY return FALSE - var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") + var/mintime = max(CONFIG_GET(number/respawn_delay), (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time, 0) + + var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to respawn for [round(mintime / 600, 0.1)] minutes!!","Player Setup","Yes","No") if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes") ready = PLAYER_NOT_READY diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index a31fdd4bf4..d882e8d474 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -122,6 +122,16 @@ to_chat(src, "You cannot respawn as you have enabled DNR.") return + var/roundstart_timeleft = world.time - (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) + if(roundstart_timeleft > 0) + to_chat(src, "It's been too short of a time since the round started! Please wait [CEILING(roundstart_timeleft / 600, 0.1)] more minutes.") + return + + var/list/modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes) + if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag])) + to_chat(src, "The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.") + return + var/timeleft = time_left_to_respawn() if(timeleft) to_chat(src, "It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.") @@ -149,6 +159,7 @@ Remember to take heed of rules regarding round knowledge - notably, that ALL past lives are forgotten. \ Any character you join as has NO knowledge of round events unless specified otherwise by an admin.") + message_admins("[key_name_admin(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.") log_game("[key_name(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.") transfer_to_lobby() diff --git a/config/respawns.txt b/config/respawns.txt index 46a4bb0e07..337a691b07 100644 --- a/config/respawns.txt +++ b/config/respawns.txt @@ -18,3 +18,12 @@ ALLOW_NON_ASSISTANT_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 + +## Time in minutes from round start before respawn is enabled +RESPAWN_MINIMUM_DELAY_ROUNDSTART 30.0 + +## Gamemode (config tags!) banlist for respawn +RESPAWN_CHAOS_GAMEMODES WIZARD +RESPAWN_CHAOS_GAMEMODES NUCLEAR +RESPAWN_CHAOS_GAMEMODES CLONWOPS +RESPAWN_CHOAS_GAMEMODES REVOLUTION From eef2a323ed689c03d6510c77aae15c24ed721c0d Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Mon, 21 Dec 2020 00:11:19 -0700 Subject: [PATCH 16/19] ok --- code/modules/mob/dead/observer/respawn.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index d882e8d474..dc825af57e 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -128,7 +128,7 @@ return var/list/modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes) - if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag])) + if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)])) to_chat(src, "The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.") return From 97824f4030d5abb1763dad198b03c412cf7447fa Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Mon, 21 Dec 2020 00:14:48 -0700 Subject: [PATCH 17/19] ok --- code/modules/mob/dead/observer/respawn.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index dc825af57e..bca4d6ab0d 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -128,7 +128,7 @@ return var/list/modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes) - if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)])) + if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)]) to_chat(src, "The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.") return From 7da6979b543f1cf0923f8c77db81854236b08e01 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Mon, 21 Dec 2020 00:28:03 -0700 Subject: [PATCH 18/19] ok --- code/controllers/configuration/entries/respawns.dm | 2 +- code/modules/mob/dead/observer/respawn.dm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/controllers/configuration/entries/respawns.dm b/code/controllers/configuration/entries/respawns.dm index 69e48ed820..40c7d248a4 100644 --- a/code/controllers/configuration/entries/respawns.dm +++ b/code/controllers/configuration/entries/respawns.dm @@ -29,7 +29,7 @@ config_entry_value = FALSE /// Minutes from roundstart before someone can respawn -/datum/config_entry/flag/respawn_minimum_delay_roundstart +/datum/config_entry/number/respawn_minimum_delay_roundstart config_entry_value = 30.0 integer = FALSE diff --git a/code/modules/mob/dead/observer/respawn.dm b/code/modules/mob/dead/observer/respawn.dm index bca4d6ab0d..f966051ed3 100644 --- a/code/modules/mob/dead/observer/respawn.dm +++ b/code/modules/mob/dead/observer/respawn.dm @@ -122,12 +122,12 @@ to_chat(src, "You cannot respawn as you have enabled DNR.") return - var/roundstart_timeleft = world.time - (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) + var/roundstart_timeleft = (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time if(roundstart_timeleft > 0) to_chat(src, "It's been too short of a time since the round started! Please wait [CEILING(roundstart_timeleft / 600, 0.1)] more minutes.") return - var/list/modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes) + var/list/banned_modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes) if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)]) to_chat(src, "The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.") return From ca6df2999872be93af52305fe47eea8095532269 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Mon, 21 Dec 2020 13:42:33 -0700 Subject: [PATCH 19/19] Update death.dm --- code/modules/mob/living/death.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 24e91f6051..688b0cf63e 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -66,8 +66,8 @@ GLOB.alive_mob_list -= src if(!gibbed) GLOB.dead_mob_list += src - if(mind?.key) - var/datum/preferences/P = GLOB.preferences_datums[ckey(mind.key)] + if(ckey) + var/datum/preferences/P = GLOB.preferences_datums[ckey] if(P) P.respawn_time_of_death = world.time set_drugginess(0)