diff --git a/code/__DEFINES/hud_locations.dm b/code/__DEFINES/hud_locations.dm index bcb5899fb4a..3373a77eb5c 100644 --- a/code/__DEFINES/hud_locations.dm +++ b/code/__DEFINES/hud_locations.dm @@ -144,12 +144,13 @@ #define UI_BOT_PULL "EAST-2:26,SOUTH:7" //Ghosts -#define UI_GHOST_ORBIT "SOUTH:6,CENTER-1.5" -#define UI_GHOST_REENTER_CORPSE "SOUTH:6,CENTER-.5" -#define UI_GHOST_TELEPORT "SOUTH:6,CENTER+.5" -#define UI_GHOST_RESPAWN_LIST "SOUTH:6,CENTER+1.5" -#define UI_GHOST_RESPAWN_MOB "SOUTH:6+1,CENTER+1.5" -#define UI_GHOST_RESPAWN_PAI "SOUTH:6+2,CENTER+1.5" +#define UI_GHOST_ORBIT "SOUTH:6,CENTER-2" +#define UI_GHOST_REENTER_CORPSE "SOUTH:6,CENTER-1" +#define UI_GHOST_TELEPORT "SOUTH:6,CENTER" +#define UI_GHOST_RESPAWN_LIST "SOUTH:6,CENTER+1" +#define UI_GHOST_RESPAWN_MOB "SOUTH:6+1,CENTER+1" +#define UI_GHOST_RESPAWN_PAI "SOUTH:6+2,CENTER+1" +#define UI_GHOST_RESPAWN_CHAR "SOUTH:6,CENTER+2" //HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12. #define HUD_STYLE_STANDARD 1 diff --git a/code/_onclick/hud/ghost_hud.dm b/code/_onclick/hud/ghost_hud.dm index 997eb1650a4..2af8734df6f 100644 --- a/code/_onclick/hud/ghost_hud.dm +++ b/code/_onclick/hud/ghost_hud.dm @@ -21,6 +21,14 @@ . = ..() flick(icon_state + "_anim", src) +/atom/movable/screen/ghost/respawn_char + name = "Respawn as new character" + icon_state = "respawn" + +/atom/movable/screen/ghost/respawn_char/Click() + var/mob/dead/observer/G = usr + G.respawn_character() + /atom/movable/screen/ghost/teleport name = "Teleport" icon_state = "teleport" @@ -82,6 +90,10 @@ ..() var/atom/movable/screen/using + using = new /atom/movable/screen/ghost/respawn_char() + using.screen_loc = UI_GHOST_RESPAWN_CHAR + static_inventory += using + using = new /atom/movable/screen/ghost/orbit() using.screen_loc = UI_GHOST_ORBIT static_inventory += using diff --git a/code/controllers/configuration/sections/general_configuration.dm b/code/controllers/configuration/sections/general_configuration.dm index 30e306860f2..00fad2808c3 100644 --- a/code/controllers/configuration/sections/general_configuration.dm +++ b/code/controllers/configuration/sections/general_configuration.dm @@ -19,7 +19,7 @@ /// Forbid players from rejoining if they use AntagHUD? var/restrict_antag_hud_rejoin = TRUE /// Enable respawns by default? - var/respawn_enabled = FALSE + var/respawn_enabled = TRUE /// Enable CID randomiser buster? var/enabled_cid_randomiser_buster = FALSE /// Forbid admins from posessing and flying the singulo round @@ -82,6 +82,8 @@ var/bomb_cap = 20 /// Time for a brain to keep its spark of life (deciseconds) var/revival_brain_life = 10 MINUTES + /// Time to wait before you can respawn as a new character. + var/respawn_delay = 10 MINUTES /// Enable random AI lawsets from the default=TRUE pool var/random_ai_lawset = TRUE /// Enable weather events initialized by SSweather. New weather events can still @@ -134,6 +136,7 @@ CONFIG_LOAD_NUM(monkey_cube_cap, data["monkey_cube_cap"]) CONFIG_LOAD_NUM(bomb_cap, data["bomb_cap"]) CONFIG_LOAD_NUM(revival_brain_life, data["revival_brain_life"]) + CONFIG_LOAD_NUM(respawn_delay, data["respawn_delay"]) // Strings CONFIG_LOAD_STR(server_name, data["server_name"]) diff --git a/code/modules/mob/dead/observer/observer_base.dm b/code/modules/mob/dead/observer/observer_base.dm index 341fd29a9e2..e3e40840f12 100644 --- a/code/modules/mob/dead/observer/observer_base.dm +++ b/code/modules/mob/dead/observer/observer_base.dm @@ -342,6 +342,67 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp GLOB.ghost_hud_panel.ui_interact(src) +/mob/dead/observer/verb/respawn_character() + set name = "Respawn as New Character" + set category = "Ghost" + + var/mob/dead/observer/O = usr + if(!isobserver(O)) + to_chat(O, "You are not dead!") + return + + if(!SSticker || SSticker.current_state < GAME_STATE_PLAYING) + to_chat(O, "You can't respawn before the game starts!") + return + + if(GAMEMODE_IS_WIZARD || GAMEMODE_IS_NUCLEAR || GAMEMODE_IS_RAGIN_MAGES) + to_chat(O, "You can't respawn for this gamemode.") + return + + var/death_time = world.time - O.timeofdeath + if(!HAS_TRAIT(O, TRAIT_RESPAWNABLE) && !check_rights(R_ADMIN, FALSE)) + to_chat(O, "You don't have respawnability!") + return + + var/death_time_minutes = round(death_time / 600) + var/plural_check = "minutes" + if(death_time_minutes == 0) + plural_check = "" + else if(death_time_minutes == 1) + plural_check = "[death_time_minutes] minute and" + else if(death_time_minutes > 1) + plural_check = "[death_time_minutes] minutes and" + var/death_time_seconds = round((death_time - death_time_minutes * 600) / 10, 1) + + if(death_time_minutes < GLOB.configuration.general.respawn_delay / 600 && !check_rights(R_ADMIN, FALSE)) + to_chat(O, "You have been dead for [plural_check] [death_time_seconds] second\s.") + to_chat(O, "You must wait [GLOB.configuration.general.respawn_delay / 600] minute\s before you can respawn.") + return + + if(!O.check_ahud_rejoin_eligibility()) + to_chat(O, "Upon using the antagHUD you forfeited the ability to join the round.") + return FALSE + if(tgui_alert(O, "Are you sure you want to respawn?\n(If you do this, you won't be able to be cloned!)", "Respawn?", list("Yes", "No")) != "Yes") + return + + log_and_message_admins("[key_name(O)][O.mind?.current? (O.mind.current.mind.special_role? " ([O.mind.current.mind.special_role])" : "") : ""] has chosen to respawn as a new character.") + + var/list/warning = list() + warning.Add("You have chosen to respawn as a new character!") + warning.Add("You will not remember anything from your previous life or time as a ghost.") + warning.Add("You MUST choose a different character slot to respawn as!") + to_chat(O, chat_box_notice(warning.Join("
"))) + + if(!O.client) + log_game("[key_name(O)] respawn failed due to disconnect.") + return + + var/mob/new_player/NP = new() + GLOB.non_respawnable_keys -= O.ckey + NP.ckey = O.ckey + qdel(O) + NP.chose_respawn = TRUE + /** * Toggles on all HUDs for the ghost player. * diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index cd51546b91d..894fc22329a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -1,6 +1,8 @@ /mob/new_player var/ready = FALSE var/spawning = FALSE //Referenced when you want to delete the new_player later on in the code. + /// Has this player chosen to respawn as a new character? + var/chose_respawn = FALSE universal_speak = TRUE invisibility = 101 @@ -329,7 +331,9 @@ var/mob/living/character = create_character() //creates the human and transfers vars and mind character = SSjobs.AssignRank(character, rank, TRUE) //equips the human - + if(chose_respawn) + SSblackbox.record_feedback("tally", "player_respawn", 1, "[thisjob]") + log_and_message_admins("[character.ckey] has respawned as [character.real_name], \a [character.dna?.species ? character.dna.species : "Undefined species"] [rank].") // AIs don't need a spawnpoint, they must spawn at an empty core if(character.mind.assigned_role == "AI") var/mob/living/silicon/ai/ai_character = character.AIize() // AIize the character, but don't move them yet diff --git a/config/example/config.toml b/config/example/config.toml index b2fe19e30eb..fde64003b45 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -302,7 +302,7 @@ allow_antag_hud = true # Forbid players from rejoining if they use antag hud restrict_antag_hud_rejoin = true # Do we want to allow player respawns? -respawn_enabled = false +respawn_enabled = true # Enable/disable the buster for the CID randomiser DLL enable_cid_randomiser_buster = false # Prevent admins from possessing the singularity @@ -365,6 +365,8 @@ reactionary_explosions = true bomb_cap = 20 # Amount of time (deciseconds) for a brain to keep its "spark of life". Set to -1 to disable. revival_brain_life = 6000 # 10 minutes +# Amount of time (deciseconds) the player must wait before respawning as a new character. +respawn_delay = 6000 # 10 minutes # Enable random silicon lawset (If said lawset has default = TRUE in the code). Disable for always crewsimov random_ai_lawset = true # Enable weather events initialized by SSweather. New weather events can still be added during the round if this is disabled. diff --git a/icons/mob/screen_ghost.dmi b/icons/mob/screen_ghost.dmi index fb4e79a83fd..6fffb2039c7 100644 Binary files a/icons/mob/screen_ghost.dmi and b/icons/mob/screen_ghost.dmi differ