diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 4fe0c1fd7db..2fdda2ee188 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -164,3 +164,5 @@ /// Status effect given when someone uses the Give Item command to offer an item to another player. #define STATUS_EFFECT_OFFERING_ITEM /datum/status_effect/offering_item + +#define STATUS_EFFECT_STARING /datum/status_effect/staring //Used in ../human/examine() proc diff --git a/code/datums/spells/mimic.dm b/code/datums/spells/mimic.dm index 2a6ba9263c1..cd6fb7e5c29 100644 --- a/code/datums/spells/mimic.dm +++ b/code/datums/spells/mimic.dm @@ -196,18 +196,29 @@ /datum/mimic_form + /// What the visible species of the form is (Only for human forms)? + var/examine_species = "Unknown" + /// What the visible gender of the form is (Only for human forms)? + var/examine_gender + /// What is the examine text paired with this form? + var/examine_text + /// What is the examine time paired with this form? + var/examine_time /// How does the form look like? var/appearance - /// What is the examine text paired with this form - var/examine_text - /// What the name of the form is + /// What the name of the form is? var/name /datum/mimic_form/New(atom/movable/form, mob/user) - appearance = form.appearance + examine_gender = form.get_visible_gender() examine_text = form.examine(user) + examine_time = form.get_examine_time() + appearance = form.appearance name = form.name + if(isliving(form)) + var/mob/living/form_living = form + examine_species = form_living.get_visible_species() /obj/effect/proc_holder/spell/mimic/morph diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 247b06abb0e..dffbc4157c6 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -43,6 +43,36 @@ get_kill() . = ..() +/datum/status_effect/staring + id = "staring" + alert_type = null + status_type = STATUS_EFFECT_UNIQUE + var/mob/living/target + var/target_gender + var/target_species + +/datum/status_effect/staring/on_creation(mob/living/new_owner, new_duration, new_target, new_target_gender, new_target_species) + if(!new_duration) + qdel(src) + return + duration = new_duration + . = ..() + target = new_target + target_gender = new_target_gender + target_species = new_target_species + +/datum/status_effect/staring/proc/catch_look(mob/living/opponent) + if(target == opponent) + to_chat(owner, span_notice("[opponent.name] catch your look!")) + to_chat(opponent, span_notice("[owner.name] catch your look!")) + var/list/loved_ones = list(MALE, FEMALE) + if(!ishuman(owner) || !(target_gender in loved_ones) || !(owner.gender in loved_ones)) + return + var/mob/living/carbon/human/human_owner = owner + if(target_gender != human_owner.gender && target_species == human_owner.dna.species.name && prob(5)) + owner.emote("blush") + to_chat(owner, span_danger("You feel something burning in your chest...")) + /datum/status_effect/high_five id = "high_five" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 06b48a8511a..a78ae6fc560 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1295,3 +1295,11 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons) return TRUE . = !density + +/atom/proc/get_examine_time() // Used only in /mob/living/carbon/human and /mob/living/simple_animal/hostile/morph + return 0 SECONDS + + +/atom/proc/get_visible_gender() // Used only in /mob/living/carbon/human and /mob/living/simple_animal/hostile/morph + return gender + diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index 51e98f457a1..ef9d680af3a 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -393,6 +393,19 @@ to_chat(src, chat_box_red(messages.Join("
"))) + +/mob/living/simple_animal/hostile/morph/get_examine_time() + return morphed ? mimic_spell.selected_form.examine_time : ..() + + +/mob/living/simple_animal/hostile/morph/get_visible_gender() + return morphed ? mimic_spell.selected_form.examine_gender : ..() + + +/mob/living/simple_animal/hostile/morph/get_visible_species() + return morphed ? mimic_spell.selected_form.examine_species : ..() + + #undef MORPHED_SPEED #undef ITEM_EAT_COST #undef MORPHS_ANNOUNCE_THRESHOLD diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 3f561ea3cec..1d8a1b58801 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -33,12 +33,8 @@ msg += "[bicon(icon(icon, dir=SOUTH))] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated msg += "[name]" - var/displayed_species = dna.species.name + var/displayed_species = get_visible_species() var/examine_color = dna.species.flesh_color - for(var/obj/item/clothing/C in src) //Disguise checks - if(C == src.head || C == src.wear_suit || C == src.wear_mask || C == src.w_uniform || C == src.belt || C == src.back) - if(C.species_disguise) - displayed_species = C.species_disguise if(skipjumpsuit && skipface || (NO_EXAMINE in dna.species.species_traits)) //either obscured or on the nospecies list msg += "!\n" //omit the species when examining else if(displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural @@ -428,6 +424,11 @@ . = list(msg) SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) + +/mob/living/carbon/human/get_examine_time() + return 1 SECONDS + + //Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records. /proc/hasHUD(mob/M, hudtype) if(istype(M, /mob/living/carbon/human)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 8a99c7a2941..cf7473f68f1 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1094,13 +1094,21 @@ return 0 return 1 -/mob/living/carbon/human/proc/get_visible_gender() +/mob/living/carbon/human/get_visible_gender() var/list/obscured = check_obscured_slots() var/skipface = (wear_mask && (wear_mask.flags_inv & HIDENAME)) || (head && (head.flags_inv & HIDENAME)) if((slot_w_uniform in obscured) && skipface) return PLURAL return gender +/mob/living/carbon/human/get_visible_species() + var/displayed_species = dna.species.name + for(var/obj/item/clothing/C in src) //Disguise checks + if(C == head || C == wear_suit || C == wear_mask || C == w_uniform || C == belt || C == back) + if(C.species_disguise) + displayed_species = C.species_disguise + return displayed_species + /mob/living/carbon/human/proc/increase_germ_level(n) if(gloves) gloves.germ_level += n diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e572c94c6f2..210c0a4738e 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1379,3 +1379,44 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven if(target_move) remove_ventcrawl() add_ventcrawl(loc, target_move) + + +/mob/living/proc/get_visible_species() // Used only in /mob/living/carbon/human and /mob/living/simple_animal/hostile/morph + return "Unknown" + + +/mob/living/run_examinate(atom/target) + var/datum/status_effect/staring/user_staring_effect = has_status_effect(STATUS_EFFECT_STARING) + if(user_staring_effect || hindered_inspection(target)) + return + + var/examine_time = target.get_examine_time() + face_atom(target) + if(examine_time && target != src) + var/visible_gender = target.get_visible_gender() + var/visible_species = "Unknown" + + if(isliving(target)) + var/mob/living/target_living = target + visible_species = target_living.get_visible_species() + + if(ishuman(target)) // Yep. Only humans affected by catched looks. + var/datum/status_effect/staring/target_staring_effect = target_living.has_status_effect(STATUS_EFFECT_STARING) + if(target_staring_effect) + target_staring_effect.catch_look(src) + + user_staring_effect = apply_status_effect(STATUS_EFFECT_STARING, examine_time, target, visible_gender, visible_species) + if(do_mob(src, target, examine_time, FALSE, list(CALLBACK(src, PROC_REF(hindered_inspection), target)), TRUE)) + ..() + else + ..() + + +/mob/living/proc/hindered_inspection(atom/target) + if(QDELETED(src) || QDELETED(target)) + return TRUE + if(!has_vision(information_only = TRUE)) + to_chat(src, span_notice("Здесь что-то есть, но вы не видите — что именно.")) + return TRUE + return FALSE + diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e65e901721a..acbc42a4e38 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -306,11 +306,6 @@ DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(run_examinate), A)) /mob/proc/run_examinate(atom/A) - if(!has_vision(information_only = TRUE) && !isobserver(src)) - to_chat(src, chat_box_regular("Здесь что-то есть, но вы не видите — что именно.")) - return TRUE - - face_atom(A) var/list/result = A.examine(src) to_chat(src, chat_box_examine(result.Join("\n")))