diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 952a53a0b6b9a..0d59c04afc61f 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -432,6 +432,13 @@ GLOBAL_LIST_INIT(available_random_trauma_list, list( #define DOING_INTERACTION_WITH_TARGET(user, target) (LAZYACCESS(user.do_afters, target)) #define DOING_INTERACTION_WITH_TARGET_LIMIT(user, target, max_interaction_count) ((LAZYACCESS(user.do_afters, target) || 0) >= max_interaction_count) +// recent examine defines +/// How long it takes for an examined atom to be removed from recent_examines. Should be the max of the below time windows +#define RECENT_EXAMINE_MAX_WINDOW (2 SECONDS) +/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine() +#define EXAMINE_MORE_WINDOW (1 SECONDS) + + #define SILENCE_RANGED_MESSAGE (1<<0) // Mob Playability Set By Admin Or Ghosting diff --git a/code/datums/mind.dm b/code/datums/mind.dm index d05a0a0b82427..436625a26f16e 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -169,6 +169,8 @@ RegisterSignal(new_character, COMSIG_MOB_DEATH, PROC_REF(set_death_time)) if(active || force_key_move) new_character.key = key //now transfer the key to link the client to our new body + if(new_character.client) + LAZYCLEARLIST(new_character.client.recent_examines) SEND_SIGNAL(src, COMSIG_MIND_TRANSFER_TO, old_current, new_character) // Update SSD indicators diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 20dfbd188c3ea..bb360a1823e21 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -113,6 +113,9 @@ var/datum/view_data/view_size + ///A lazy list of atoms we've examined in the last RECENT_EXAMINE_MAX_WINDOW (default 2) seconds, so that we will call [/atom/proc/examine_more] instead of [/atom/proc/examine] on them when examining + var/list/recent_examines + // List of all asset filenames sent to this client by the asset cache, along with their assoicated md5s var/list/sent_assets = list() /// List of all completed blocking send jobs awaiting acknowledgement by send_asset diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 50dc44d8e44f8..5fb00c8bfbd4c 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -13,9 +13,9 @@ var/unique_death /// The unique sound effect of dying while wearing this /obj/item/clothing/mask/attack_self(mob/user) - if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE)) - TOGGLE_BITFIELD(clothing_flags, VOICEBOX_DISABLED) - var/status = !CHECK_BITFIELD(clothing_flags, VOICEBOX_DISABLED) + if((clothing_flags & VOICEBOX_TOGGLABLE)) + clothing_flags ^= (VOICEBOX_DISABLED) + var/status = !(clothing_flags & VOICEBOX_DISABLED) to_chat(user, "You turn the voice box in [src] [status ? "on" : "off"].") /obj/item/clothing/mask/equipped(mob/M, slot) diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index af9f9c2486aa0..6d6df31836677 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -14,7 +14,6 @@ visor_flags_cover = MASKCOVERSMOUTH resistance_flags = NONE - /datum/armor/mask_breath bio = 50 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ffcb0154282b7..da21b1b7eff07 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1696,8 +1696,8 @@ /// Proc to append behavior to the condition of being floored. Called when the condition starts. /mob/living/proc/on_floored_start() if(body_position == STANDING_UP) //force them on the ground - set_lying_angle(pick(90, 270)) set_body_position(LYING_DOWN) + set_lying_angle(pick(90, 270)) on_fall() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e6e8fd5ce3c38..528335a21c3c3 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -530,22 +530,40 @@ * [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716) * for why this isn't atom/verb/examine() */ -/mob/verb/examinate(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why +/mob/verb/examinate(atom/examinify as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why set name = "Examine" set category = "IC" - if(isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src))) + if(isturf(examinify) && !(sight & SEE_TURFS) && !(examinify in view(client ? client.view : world.view, src))) // shift-click catcher may issue examinate() calls for out-of-sight turfs return - if(is_blind(src) && !blind_examine_check(A)) + if(is_blind(src) && !blind_examine_check(examinify)) return - face_atom(A) - var/list/result = A.examine(src) + face_atom(examinify) + var/list/result + if(client) + LAZYINITLIST(client.recent_examines) + var/ref_to_atom = ref(examinify) + var/examine_time = client.recent_examines[ref_to_atom] + if(examine_time && (world.time - examine_time < EXAMINE_MORE_WINDOW)) + result = examinify.examine_more(src) + if(!length(result)) + result += "You examine [examinify] closer, but find nothing of interest..." + else + result = examinify.examine(src) + client.recent_examines[ref_to_atom] = world.time // set to when we last normal examine'd them + addtimer(CALLBACK(src, .proc/clear_from_recent_examines, ref_to_atom), RECENT_EXAMINE_MAX_WINDOW) + else + result = examinify.examine(src) // if a tree is examined but no client is there to see it, did the tree ever really exist? - to_chat(src, EXAMINE_BLOCK(jointext(result, "\n"))) - SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) + if(result.len) + for(var/i in 1 to (length(result) - 1)) + result[i] += "\n" + + to_chat(src, EXAMINE_BLOCK("[result.Join()]")) + SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, examinify) /mob/proc/blind_examine_check(atom/examined_thing) return TRUE @@ -595,6 +613,12 @@ return TRUE +/mob/proc/clear_from_recent_examines(ref_to_clear) + SIGNAL_HANDLER + if(!client) + return + LAZYREMOVE(client.recent_examines, ref_to_clear) + /** * Called by using Activate Held Object with an empty hand/limb *