diff --git a/code/__DEFINES/emotes_defines.dm b/code/__DEFINES/emotes_defines.dm index f814bfed0a7..42a7ff344d9 100644 --- a/code/__DEFINES/emotes_defines.dm +++ b/code/__DEFINES/emotes_defines.dm @@ -80,3 +80,8 @@ /// List of emotes useable by ghosties #define USABLE_DEAD_EMOTES list("*flip", "*spin") + +/// Sentinel for emote stats. +/// If this is set for max stat, then its value will be ignored. +#define DEFAULT_MAX_STAT_ALLOWED_EMOTE "defaultstat" + diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 7b91dc8c511..eb749342fa2 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -164,50 +164,52 @@ #define MFOAM_IRON 2 //Carbon Overlays Indexes///////// -#define MUTANTRACE_LAYER 43 -#define WING_UNDERLIMBS_LAYER 42 -#define TAIL_UNDERLIMBS_LAYER 41 //Tail split-rendering. -#define LIMBS_LAYER 40 -#define INTORGAN_LAYER 39 -#define MARKINGS_LAYER 38 -#define UNDERWEAR_LAYER 37 -#define MUTATIONS_LAYER 36 -#define H_DAMAGE_LAYER 35 -#define UNIFORM_LAYER 34 -#define SHOES_LAYER 33 -#define OVER_SHOES_LAYER 32 -#define ID_LAYER 31 -#define GLOVES_LAYER 30 -#define EARS_LAYER 29 -#define SUIT_LAYER 28 -#define BELT_LAYER 27 //Possible make this an overlay of somethign required to wear a belt? -#define NECK_LAYER 26 -#define SUIT_STORE_LAYER 25 -#define BACK_LAYER 24 -#define HEAD_ACCESSORY_LAYER 23 -#define FHAIR_LAYER 22 -#define GLASSES_LAYER 21 -#define HAIR_LAYER 20 //TODO: make part of head layer? -#define HEAD_ACC_OVER_LAYER 19 //Select-layer rendering. -#define FHAIR_OVER_LAYER 18 //Select-layer rendering. -#define GLASSES_OVER_LAYER 17 //Select-layer rendering. -#define WING_LAYER 16 -#define TAIL_LAYER 15 //bs12 specific. this hack is probably gonna come back to haunt me -#define FACEMASK_LAYER 14 -#define OVER_MASK_LAYER 13 //Select-layer rendering. -#define HEAD_LAYER 12 -#define OVER_HEAD_LAYER 11 -#define COLLAR_LAYER 10 -#define HANDCUFF_LAYER 9 -#define LEGCUFF_LAYER 8 -#define L_HAND_LAYER 7 -#define R_HAND_LAYER 6 -#define TARGETED_LAYER 5 //BS12: Layer for the target overlay from weapon targeting system -#define HALO_LAYER 4 //blood cult ascended halo, because there's currently no better solution for adding/removing -#define FIRE_LAYER 3 //If you're on fire -#define MISC_LAYER 2 -#define FROZEN_LAYER 1 -#define TOTAL_LAYERS 44 +#define MUTANTRACE_LAYER 45 +#define WING_UNDERLIMBS_LAYER 44 +#define TAIL_UNDERLIMBS_LAYER 43 //Tail split-rendering. +#define LIMBS_LAYER 42 +#define INTORGAN_LAYER 41 +#define MARKINGS_LAYER 40 +#define UNDERWEAR_LAYER 39 +#define MUTATIONS_LAYER 38 +#define H_DAMAGE_LAYER 37 +#define UNIFORM_LAYER 36 +#define SHOES_LAYER 35 +#define OVER_SHOES_LAYER 34 +#define ID_LAYER 33 +#define GLOVES_LAYER 32 +#define EARS_LAYER 31 +#define SUIT_LAYER 30 +#define BELT_LAYER 29 //Possible make this an overlay of somethign required to wear a belt? +#define NECK_LAYER 28 +#define SUIT_STORE_LAYER 27 +#define BACK_LAYER 26 +#define HEAD_ACCESSORY_LAYER 25 +#define FHAIR_LAYER 24 +#define GLASSES_LAYER 23 +#define HAIR_LAYER 22 //TODO: make part of head layer? +#define HEAD_ACC_OVER_LAYER 21 //Select-layer rendering. +#define FHAIR_OVER_LAYER 20 //Select-layer rendering. +#define GLASSES_OVER_LAYER 19 //Select-layer rendering. +#define WING_LAYER 18 +#define TAIL_LAYER 17 //bs12 specific. this hack is probably gonna come back to haunt me +#define FACEMASK_LAYER 16 +#define OVER_MASK_LAYER 15 //Select-layer rendering. +#define HEAD_LAYER 14 +#define OVER_HEAD_LAYER 13 +#define COLLAR_LAYER 12 +#define HANDCUFF_LAYER 11 +#define LEGCUFF_LAYER 10 +#define L_HAND_LAYER 9 +#define R_HAND_LAYER 8 +#define TARGETED_LAYER 7 //BS12: Layer for the target overlay from weapon targeting system +#define HALO_LAYER 6 //blood cult ascended halo, because there's currently no better solution for adding/removing +#define FIRE_LAYER 5 //If you're on fire +#define MISC_LAYER 4 +#define SLEEP_LAYER 3 +#define FROZEN_LAYER 2 +#define SSD_LAYER 1 +#define TOTAL_LAYERS 46 ///Access Region Codes/// #define REGION_ALL 0 diff --git a/code/datums/emote/emote.dm b/code/datums/emote/emote.dm index b87eb723a7c..43f769e3138 100644 --- a/code/datums/emote/emote.dm +++ b/code/datums/emote/emote.dm @@ -1,10 +1,6 @@ // Defines are in code\__DEFINES\emotes.dm -/// Sentinel for emote stats. -/// If this is set for max stat, then its value will be ignored. -#define DEFAULT_MAX_STAT_ALLOWED "defaultstat" - /** * # Emote * @@ -81,12 +77,12 @@ var/stat_allowed = CONSCIOUS /// How unconscious/dead can you be while still being able to use this emote intentionally? /// If this is set to DEFAULT_STAT_ALLOWED, it'll behave as if it isn't set. - var/max_stat_allowed = DEFAULT_MAX_STAT_ALLOWED + var/max_stat_allowed = DEFAULT_MAX_STAT_ALLOWED_EMOTE /// How conscious do you need to be to have this emote forced out of you? var/unintentional_stat_allowed = CONSCIOUS /// Same as above, how unconscious/dead do you need to be to have this emote forced out of you? /// If this is set to DEFAULT_STAT_ALLOWED, it'll behave as if it isn't set. - var/max_unintentional_stat_allowed = DEFAULT_MAX_STAT_ALLOWED + var/max_unintentional_stat_allowed = DEFAULT_MAX_STAT_ALLOWED_EMOTE /// Sound to play when emote is called. Might be a list with different sounds. If you want to adjust this dynamically, see get_sound(). var/sound /// Whether or not to vary the sound of the emote. @@ -492,8 +488,8 @@ return FALSE if(status_check && !is_type_in_typecache(user, mob_type_ignore_stat_typecache)) - var/intentional_stat_check = (intentional && (user.stat <= stat_allowed && (max_stat_allowed == DEFAULT_MAX_STAT_ALLOWED || user.stat >= max_stat_allowed))) - var/unintentional_stat_check = (!intentional && (user.stat <= unintentional_stat_allowed && (max_unintentional_stat_allowed == DEFAULT_MAX_STAT_ALLOWED || user.stat >= max_unintentional_stat_allowed))) + var/intentional_stat_check = (intentional && (user.stat <= stat_allowed && (max_stat_allowed == DEFAULT_MAX_STAT_ALLOWED_EMOTE || user.stat >= max_stat_allowed))) + var/unintentional_stat_check = (!intentional && (user.stat <= unintentional_stat_allowed && (max_unintentional_stat_allowed == DEFAULT_MAX_STAT_ALLOWED_EMOTE || user.stat >= max_unintentional_stat_allowed))) if(!intentional_stat_check && !unintentional_stat_check) var/stat = stat_to_text(user.stat) if(!intentional) @@ -629,6 +625,3 @@ visible_message(text) - -#undef DEFAULT_MAX_STAT_ALLOWED - diff --git a/code/datums/emote/emote_verbs.dm b/code/datums/emote/emote_verbs.dm index 421ed81b600..dce2eff87c1 100644 --- a/code/datums/emote/emote_verbs.dm +++ b/code/datums/emote/emote_verbs.dm @@ -69,12 +69,10 @@ set category = "Эмоции" emote("sniff", intentional = TRUE) -/* -/mob/living/carbon/human/verb/emote_snore() // locked to unconscious stat +/mob/living/carbon/human/verb/emote_snore() set name = "▷ Храпеть " set category = "Эмоции" emote("snore", intentional = TRUE) -*/ /mob/living/carbon/human/verb/emote_whistle() set name = "▷ Свистеть " diff --git a/code/datums/keybindings/emote.dm b/code/datums/keybindings/emote.dm index d807d416ef3..f399dec92d3 100644 --- a/code/datums/keybindings/emote.dm +++ b/code/datums/keybindings/emote.dm @@ -179,6 +179,10 @@ linked_emote = /datum/emote/living/swear name = "Ругаться" +/datum/keybinding/emote/snore + linked_emote = /datum/emote/living/snore + name = "Храпеть" + /** * Carbon */ diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 57c007e93b1..1692c84c0b2 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -3106,7 +3106,7 @@ /mob/proc/sync_mind() mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) - mind.active = 1 //indicates that the mind is currently synced with a client + mind.active = TRUE //indicates that the mind is currently synced with a client //slime /mob/living/simple_animal/slime/mind_initialize() diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index f17be7eddaa..2c3ab5c2239 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -117,7 +117,7 @@ if(!drownee) return - if(drownee && ((drownee.body_position == LYING_DOWN && !drownee.player_logged) || deep_water)) //Mob lying down and not SSD or water is deep (determined by controller) + if(drownee && ((drownee.body_position == LYING_DOWN && isnull(drownee.player_logged)) || deep_water)) //Mob lying down and not SSD or water is deep (determined by controller) if(drownee.internal) return //Has internals, no drowning if((NO_BREATHE in drownee.dna.species.species_traits) || (BREATHLESS in drownee.mutations)) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f43a96f0d51..4b644fd55bf 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -168,8 +168,6 @@ Works together with spawning an observer, noted above. /mob/proc/ghostize(flags = GHOST_CAN_REENTER) if(key) - if(player_logged) //if they have disconnected we want to remove their SSD overlay - cut_overlay(image('icons/effects/effects.dmi', icon_state = "zzz_glow")) if(GLOB.non_respawnable_keys[ckey]) flags &= ~GHOST_CAN_REENTER var/mob/dead/observer/ghost = new(src, flags) //Transfer safety to observer spawning proc. diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 230705312f4..6e10d9fb340 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -53,8 +53,6 @@ if(player_ghosted > 0 && stat == CONSCIOUS && job && !HAS_TRAIT(src, TRAIT_RESTRAINED)) handle_ghosted() - if(player_logged > 0 && stat != DEAD && job) - handle_ssd() if(stat != DEAD) return TRUE @@ -67,18 +65,24 @@ if(player_ghosted % 150 == 0) force_cryo_human(src) -/mob/living/carbon/human/proc/handle_ssd() - player_logged++ - if(istype(loc, /obj/machinery/cryopod)) - return - if(CONFIG_GET(number/auto_cryo_ssd_mins) && (player_logged >= (CONFIG_GET(number/auto_cryo_ssd_mins) * 30)) && player_logged % 30 == 0) - var/turf/T = get_turf(src) - if(!is_station_level(T.z)) - return - var/area/A = get_area(src) - cryo_ssd(src) - if(A.fast_despawn) - force_cryo_human(src) + +/mob/living/carbon/human/handle_SSD(seconds_per_tick) + . = ..() + if(!. || !job || istype(loc, /obj/machinery/cryopod) || !CONFIG_GET(number/auto_cryo_ssd_mins)) + return . + + if(player_logged < (CONFIG_GET(number/auto_cryo_ssd_mins) MINUTES)) + return . + + var/turf/our_turf = get_turf(src) + if(!our_turf || !is_station_level(our_turf.z)) + return . + + cryo_ssd(src) + var/area/our_area = get_area(src) + if(our_area.fast_despawn) + force_cryo_human(src) + /mob/living/carbon/human/calculate_affecting_pressure(pressure) var/pressure_difference = abs( pressure - ONE_ATMOSPHERE ) diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index f859134c278..5b0053ee944 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -1,6 +1,4 @@ /mob/living/carbon/human/Login() - if(player_logged) - cut_overlay(image('icons/effects/effects.dmi', icon_state = "zzz_glow")) ..() regenerate_icons() - return + diff --git a/code/modules/mob/living/carbon/human/logout.dm b/code/modules/mob/living/carbon/human/logout.dm index e0e4230e8bf..f795672be14 100644 --- a/code/modules/mob/living/carbon/human/logout.dm +++ b/code/modules/mob/living/carbon/human/logout.dm @@ -1,4 +1,4 @@ /mob/living/carbon/human/Logout() ..() - if(mind && mind.active && stat != DEAD) - add_overlay(image('icons/effects/effects.dmi', icon_state = "zzz_glow")) + // nothing for now + diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 86b8909caf7..23093ce1f4d 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -518,6 +518,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) add_overlay(get_emissive_block()) update_halo_layer() update_fire() + update_ssd_overlay() + update_unconscious_overlay() SEND_SIGNAL(src, COMSIG_HUMAN_REGENERATE_ICONS) @@ -1319,3 +1321,21 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) . = "[.][!!husk][!!hulk][!!skeleton]" + +/mob/living/carbon/human/update_ssd_overlay() + if(!isnull(player_logged)) + overlays_standing[SSD_LAYER] = mutable_appearance('icons/effects/effects.dmi', "SSD", -SSD_LAYER, appearance_flags = KEEP_APART|RESET_TRANSFORM|RESET_COLOR) + apply_overlay(SSD_LAYER) + else + remove_overlay(SSD_LAYER) + + +/mob/living/carbon/human/update_unconscious_overlay() + if(stat == UNCONSCIOUS) + var/mutable_appearance/sleep_effect = mutable_appearance('icons/effects/effects.dmi', "sleep", -SLEEP_LAYER, appearance_flags = KEEP_APART|RESET_TRANSFORM|RESET_COLOR) + sleep_effect.pixel_z = 8 + overlays_standing[SLEEP_LAYER] = sleep_effect + apply_overlay(SLEEP_LAYER) + else + remove_overlay(SLEEP_LAYER) + diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 3c56865a814..36319f6ac8e 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -93,6 +93,8 @@ handle_gravity(seconds, times_fired) + handle_SSD(seconds) + if(stat != DEAD) return TRUE @@ -282,3 +284,14 @@ if(!breathing_tube) AdjustLoseBreath(3 SECONDS, bound_upper = 6 SECONDS) + +/// Handles mob SSD status. +/mob/living/proc/handle_SSD(seconds_per_tick) + if(isnull(player_logged)) + return FALSE + if(stat == DEAD) + set_SSD(FALSE) + return FALSE + player_logged += seconds_per_tick SECONDS // called every 2s. on life + return TRUE + diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e5c2187b11a..f1ae4d862af 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2177,14 +2177,17 @@ update_sight() update_blind_effects() update_blurry_effects() + update_unconscious_overlay() if(UNCONSCIOUS) update_sight() update_blind_effects() update_blurry_effects() + update_unconscious_overlay() if(DEAD) update_sight() update_blind_effects() update_blurry_effects() + update_unconscious_overlay() GLOB.alive_mob_list += src GLOB.dead_mob_list -= src @@ -2240,3 +2243,35 @@ return layer = (body_position == LYING_DOWN) ? LYING_MOB_LAYER : initial(layer) + +/** + * Updates mob's SSD status with all the necessaey checks. + * + * Arguments: + * * enable (boolean) - `TRUE` to set SSD status, `FALSE` to remove. + * + * Returns `TRUE` on success, `FALSE` otherwise. + */ +/mob/living/proc/set_SSD(enable) + if(!mind || !last_known_ckey) // mindless / non player mobs are skipped + return FALSE + + if(enable) + if(stat == DEAD) // dead mobs are skipped, unless we are removing SSD status + return FALSE + if(!mind.active || (ckey && ckey[1] == "@")) // aghosting will do this, we want to avoid SSDing admemes + return FALSE + if(!isnull(player_logged)) // already in SSD, return TRUE and we are done + return TRUE + // this causes instant sleep and tags a player as SSD. See [/proc/handle_SSD()] for furthering SSD + player_logged = 0 + Sleeping(4 SECONDS) + . = TRUE + else + if(isnull(player_logged)) // SSD status is removed already, return TRUE and we are done + return TRUE + player_logged = null + . = TRUE + + update_ssd_overlay() // special SSD overlay handling + diff --git a/code/modules/mob/living/living_emote.dm b/code/modules/mob/living/living_emote.dm index 13dc19505b6..138806d5ea6 100644 --- a/code/modules/mob/living/living_emote.dm +++ b/code/modules/mob/living/living_emote.dm @@ -408,11 +408,6 @@ emote_type = EMOTE_AUDIBLE|EMOTE_MOUTH volume = 70 age_based = TRUE - // lock it so these emotes can only be used while unconscious - stat_allowed = UNCONSCIOUS - max_stat_allowed = UNCONSCIOUS - unintentional_stat_allowed = UNCONSCIOUS - max_unintentional_stat_allowed = UNCONSCIOUS /datum/emote/living/snore/get_sound(mob/living/carbon/human/user) diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index eb6ad24587c..949d9ae02b0 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -12,7 +12,7 @@ update_z(T.z) //If they're SSD, remove it so they can wake back up. - player_logged = 0 + set_SSD(FALSE) //Vents if(is_ventcrawler(src)) to_chat(src, span_notice("You can ventcrawl! Use Alt+Click on vents to quickly travel about the station.")) diff --git a/code/modules/mob/living/logout.dm b/code/modules/mob/living/logout.dm index f845f6cfa75..05f81fdaffe 100644 --- a/code/modules/mob/living/logout.dm +++ b/code/modules/mob/living/logout.dm @@ -6,9 +6,9 @@ ..() if(mind) if(!key) //key and mind have become seperated. I believe this is for when a staff member aghosts. - mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body. - //This causes instant sleep and tags a player as SSD. See life.dm for furthering SSD. + mind.active = FALSE //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body. if(mind.active) - Sleeping(4 SECONDS) - player_logged = 1 last_logout = world.time + + set_SSD(TRUE) + diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 80a38dbaa35..11f72edb9fe 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -200,8 +200,8 @@ ///How many usable hands does this mob currently have. Should only be changed through set_usable_hands() var/usable_hands = 2 - //SSD var, changed it up some so people can have special things happen for different mobs when SSD. - var/player_logged = 0 + /// SSD var. When mob has SSD status it contains num value (in deciseconds), since last mob logout. Always null otherwise. + var/player_logged //Ghosted var, set only if a player has manually ghosted out of this mob. var/player_ghosted = 0 diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 6e050ff91a2..45c359ed429 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -31,7 +31,7 @@ /proc/isLivingSSD(mob/M) - return istype(M) && M.player_logged && M.stat != DEAD + return istype(M) && !isnull(M.player_logged) && M.stat != DEAD /proc/isAntag(A) if(isliving(A)) diff --git a/code/modules/mob/update_icons.dm b/code/modules/mob/update_icons.dm index b31aa80752b..ea3ce8af70e 100644 --- a/code/modules/mob/update_icons.dm +++ b/code/modules/mob/update_icons.dm @@ -83,3 +83,9 @@ /mob/proc/update_inv_ears() return +/mob/proc/update_ssd_overlay() + return + +/mob/proc/update_unconscious_overlay() + return + diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 4cf287bfe54..9c71b4e58b5 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ