diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index afa9071aae..bccf1f28dd 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -221,10 +221,6 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) //Same as above except gets the area instead #define get_area(A) (isarea(A) ? A : get_step(A, 0)?.loc) -//Used to prevent cryo/suicidees from coming back into the round as ghost roles or mid round antags before a given duration has passed. -#define SUICIDE_REENTER_ROUND_TIMER 30 MINUTES -#define ROUNDSTART_QUITTER_TIME_LIMIT 30 MINUTES //a game time threshold under which will be applied a proportional added penalty. - //Ghost orbit types: #define GHOST_ORBIT_CIRCLE "circle" #define GHOST_ORBIT_TRIANGLE "triangle" diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index cfd57b4850..95935a7066 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -132,6 +132,14 @@ min_val = 0 max_val = 1 +/datum/config_entry/number/suicide_reenter_round_timer + config_entry_value = 30 + min_val = 0 + +/datum/config_entry/number/roundstart_suicide_time_limit + config_entry_value = 30 + min_val = 0 + /datum/config_entry/number/shuttle_refuel_delay config_entry_value = 12000 min_val = 0 diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 84cc27953a..b856ee4c94 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -411,8 +411,7 @@ // Ghost and delete the mob. if(!mob_occupant.get_ghost(1)) - mob_occupant.suiciding = TRUE //to penalize them from making a ghost role / midround antag comeback right away. - mob_occupant.ghostize(0) + mob_occupant.ghostize(FALSE, penalize = TRUE) QDEL_NULL(occupant) open_machine() diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index 2e643cc05d..90c692c60e 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -49,7 +49,7 @@ if(!(damagetype & (BRUTELOSS | FIRELOSS | TOXLOSS | OXYLOSS) )) adjustOxyLoss(max(200 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - death(FALSE) + death(FALSE, penalize = TRUE) return diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 835dcab9e2..eb5c968bd2 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -18,7 +18,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) invisibility = INVISIBILITY_OBSERVER hud_type = /datum/hud/ghost var/can_reenter_corpse - var/reenter_round_timeout = 0 // used to prevent people from coming back through ghost roles/midround antags as they suicide/cryo for a duration set by SUICIDE_REENTER_ROUND_TIMER. + var/reenter_round_timeout = 0 // used to prevent people from coming back through ghost roles/midround antags as they suicide/cryo for a duration set by CONFIG_GET(number/suicide_reenter_round_timer) and CONFIG_GET(number/roundstart_suicide_time_limit) var/datum/hud/living/carbon/hud = null // hud var/bootime = 0 var/started_as_observer //This variable is set to 1 when you enter the game as an observer. @@ -260,18 +260,20 @@ 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) - if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special) & COMPONENT_BLOCK_GHOSTING)) +/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE) + if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse) & COMPONENT_BLOCK_GHOSTING)) return //mob has no key, is an aghost or some component hijacked. stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc. SStgui.on_transfer(src, ghost) // Transfer NanoUIs. ghost.can_reenter_corpse = can_reenter_corpse - if(suiciding) - var/penalty = SUICIDE_REENTER_ROUND_TIMER - if(world.time < ROUNDSTART_QUITTER_TIME_LIMIT) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed. - penalty += ROUNDSTART_QUITTER_TIME_LIMIT - world.time - ghost.reenter_round_timeout = world.realtime + penalty + if(penalize) //penalizing them from making a ghost role / midround antag comeback right away. + var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) + var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) + if(world.time < roundstart_quit_limit) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed. + penalty += roundstart_quit_limit - world.time + if(penalty) + ghost.reenter_round_timeout = world.realtime + penalty transfer_ckey(ghost, FALSE) return ghost @@ -287,29 +289,25 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, (stat == DEAD) ? TRUE : FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING) return - var/penalty = SUICIDE_REENTER_ROUND_TIMER - if(world.time < ROUNDSTART_QUITTER_TIME_LIMIT) - penalty += ROUNDSTART_QUITTER_TIME_LIMIT - world.time -// CITADEL EDIT - if(istype(loc, /obj/machinery/cryopod)) - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round for the next [round(penalty/600, 600)] minutes! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") - if(response != "Ghost")//darn copypaste - return - var/obj/machinery/cryopod/C = loc - C.despawn_occupant() - return -// END EDIT + var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) + var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) + if(world.time < roundstart_quit_limit) + penalty += roundstart_quit_limit - world.time if(stat != DEAD) succumb() if(stat == DEAD) ghostize(1) else - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round for the next [round(penalty/600, 600)] minutes! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles for the next [round(penalty/600)] minutes" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") if(response != "Ghost") return //didn't want to ghost after-all - ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 - suicide_log(TRUE) + if(istype(loc, /obj/machinery/cryopod)) + var/obj/machinery/cryopod/C = loc + C.despawn_occupant() + else + ghostize(0, penalize = TRUE) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + suicide_log(TRUE) /mob/camera/verb/ghost() set category = "OOC" @@ -319,14 +317,15 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING) return - var/penalty = SUICIDE_REENTER_ROUND_TIMER - if(world.time < ROUNDSTART_QUITTER_TIME_LIMIT) - penalty += ROUNDSTART_QUITTER_TIME_LIMIT - world.time + var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) + var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) + if(world.time < roundstart_quit_limit) + penalty += roundstart_quit_limit - world.time - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round for the next [round(penalty/600, 600)] minutes! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles for the next [round(penalty/600)] minutes" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") if(response != "Ghost") return - ghostize(0) + ghostize(0, penalize = TRUE) /mob/dead/observer/Move(NewLoc, direct) if(updatedir) diff --git a/config/game_options.txt b/config/game_options.txt index 2e346ce0ac..ca07d4e744 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -471,6 +471,18 @@ MIDROUND_ANTAG_TIME_CHECK 60 ## A ratio of living to total crew members, the lower this is, the more people will have to die in order for midround antag to be skipped MIDROUND_ANTAG_LIFE_CHECK 0.7 +## A time, in real-time deciseconds, applied upon suicide, cryosleep or ghosting whilst alive +## during which the player shouldn't be able to come back through +## midround playable roles or mob spawners. +## Set to 0 to completely disable it. +SUICIDE_REENTER_ROUND_TIMER 18000 + +## A time, in real-time deciseconds, below which the player receives +## a timed penalty, for purposes similar to the aforementioned one (can also stack) +## and equal to this config difference with world.time. +## Both configs are indipendent from each other, disabling one won't affect the other. +ROUNDSTART_SUICIDE_TIME_LIMIT 18000 + ##Limit Spell Choices## ## Uncomment to disallow wizards from using certain spells that may be too chaotic/fun for your playerbase