mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-09 16:05:07 +00:00
Adds eye contact (#52108)
* doesn't do it for me * signal and hijinx * creep stare * less lazy code
This commit is contained in:
@@ -312,6 +312,10 @@
|
||||
#define COMSIG_MOB_THROW "mob_throw"
|
||||
///from base of /mob/verb/examinate(): (atom/target)
|
||||
#define COMSIG_MOB_EXAMINATE "mob_examinate"
|
||||
///from /mob/living/handle_eye_contact(): (mob/living/other_mob)
|
||||
#define COMSIG_MOB_EYECONTACT "mob_eyecontact"
|
||||
/// return this if you want to block printing this message to this person, if you want to print your own (does not affect the other person's message)
|
||||
#define COMSIG_BLOCK_EYECONTACT (1<<0)
|
||||
///from base of /mob/update_sight(): ()
|
||||
#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight"
|
||||
////from /mob/living/say(): ()
|
||||
|
||||
@@ -366,5 +366,7 @@
|
||||
|
||||
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
/// How far away you can be to make eye contact with someone while examining
|
||||
#define EYE_CONTACT_RANGE 5
|
||||
|
||||
#define SILENCE_RANGED_MESSAGE (1<<0)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
owner.mind.add_antag_datum(/datum/antagonist/obsessed)
|
||||
antagonist = owner.mind.has_antag_datum(/datum/antagonist/obsessed)
|
||||
antagonist.trauma = src
|
||||
RegisterSignal(obsession, COMSIG_MOB_EYECONTACT, .proc/stare)
|
||||
..()
|
||||
//antag stuff//
|
||||
antagonist.forge_objectives(obsession.mind)
|
||||
@@ -65,6 +66,8 @@
|
||||
/datum/brain_trauma/special/obsessed/on_lose()
|
||||
..()
|
||||
owner.mind.remove_antag_datum(/datum/antagonist/obsessed)
|
||||
if(obsession)
|
||||
UnregisterSignal(obsession, COMSIG_MOB_EYECONTACT)
|
||||
|
||||
/datum/brain_trauma/special/obsessed/handle_speech(datum/source, list/speech_args)
|
||||
if(!viewing)
|
||||
@@ -100,6 +103,13 @@
|
||||
fail = TRUE
|
||||
return fail
|
||||
|
||||
// if the creep examines first, then the obsession examines them, have a 50% chance to possibly blow their cover. wearing a mask avoids this risk
|
||||
/datum/brain_trauma/special/obsessed/proc/stare(datum/source, mob/living/examining_mob, triggering_examiner)
|
||||
if(examining_mob != owner || !triggering_examiner || prob(50))
|
||||
return
|
||||
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, obsession, "<span class='warning'>You catch [examining_mob] staring at you...</span>", 3))
|
||||
return COMSIG_BLOCK_EYECONTACT
|
||||
|
||||
/datum/brain_trauma/special/obsessed/proc/find_obsession()
|
||||
var/chosen_victim
|
||||
|
||||
@@ -96,7 +96,6 @@
|
||||
/datum/quirk/brainproblems/on_process()
|
||||
if(HAS_TRAIT(quirk_holder, TRAIT_TUMOR_SUPPRESSED))
|
||||
return
|
||||
|
||||
quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
|
||||
|
||||
/datum/quirk/deafness
|
||||
@@ -484,6 +483,13 @@
|
||||
hardcore_value = 4
|
||||
var/dumb_thing = TRUE
|
||||
|
||||
/datum/quirk/social_anxiety/add()
|
||||
RegisterSignal(quirk_holder, COMSIG_MOB_EYECONTACT, .proc/eye_contact)
|
||||
RegisterSignal(quirk_holder, COMSIG_MOB_EXAMINATE, .proc/looks_at_floor)
|
||||
|
||||
/datum/quirk/social_anxiety/remove()
|
||||
UnregisterSignal(quirk_holder, list(COMSIG_MOB_EYECONTACT, COMSIG_MOB_EXAMINATE))
|
||||
|
||||
/datum/quirk/social_anxiety/on_process()
|
||||
var/nearby_people = 0
|
||||
for(var/mob/living/carbon/human/H in oview(3, quirk_holder))
|
||||
@@ -501,6 +507,43 @@
|
||||
if(prob(1))
|
||||
new/obj/item/reagent_containers/food/snacks/spaghetti/pastatomato(get_turf(H)) //now that's what I call spaghetti code
|
||||
|
||||
// small chance to make eye contact with inanimate objects/mindless mobs because of nerves
|
||||
/datum/quirk/social_anxiety/proc/looks_at_floor(datum/source, atom/A)
|
||||
var/mob/living/mind_check = A
|
||||
if(prob(85) || (istype(mind_check) && mind_check.mind))
|
||||
return
|
||||
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, quirk_holder, "<span class='smallnotice'>You make eye contact with [A].</span>"), 3)
|
||||
|
||||
/datum/quirk/social_anxiety/proc/eye_contact(datum/source, mob/living/other_mob, triggering_examiner)
|
||||
if(prob(75))
|
||||
return
|
||||
var/msg
|
||||
if(triggering_examiner)
|
||||
msg = "You make eye contact with [other_mob], "
|
||||
else
|
||||
msg = "[other_mob] makes eye contact with you, "
|
||||
|
||||
switch(rand(1,3))
|
||||
if(1)
|
||||
quirk_holder.Jitter(10)
|
||||
msg += "causing you to start fidgeting!"
|
||||
if(2)
|
||||
quirk_holder.stuttering = max(3, quirk_holder.stuttering)
|
||||
msg += "causing you to start stuttering!"
|
||||
if(3)
|
||||
quirk_holder.Stun(2 SECONDS)
|
||||
msg += "causing you to freeze up!"
|
||||
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "anxiety_eyecontact", /datum/mood_event/anxiety_eyecontact)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, quirk_holder, "<span class='userdanger'>[msg]</span>"), 3) // so the examine signal has time to fire and this will print after
|
||||
return COMSIG_BLOCK_EYECONTACT
|
||||
|
||||
/datum/mood_event/anxiety_eyecontact
|
||||
description = "<span class='warning'>Sometimes eye contact makes me so nervous...</span>\n"
|
||||
mood_change = -5
|
||||
timeout = 3 MINUTES
|
||||
|
||||
/datum/quirk/junkie
|
||||
name = "Junkie"
|
||||
desc = "You can't get enough of hard drugs."
|
||||
|
||||
@@ -1184,3 +1184,6 @@
|
||||
S.generate(BP, W)
|
||||
S.fake = TRUE
|
||||
QDEL_NULL(W)
|
||||
|
||||
/mob/living/carbon/is_face_visible()
|
||||
return !(wear_mask?.flags_inv & HIDEFACE) && !(head?.flags_inv & HIDEFACE)
|
||||
|
||||
@@ -1556,3 +1556,7 @@
|
||||
switch(stat) //Current stat.
|
||||
if(UNCONSCIOUS)
|
||||
become_blind(UNCONSCIOUS_BLIND)
|
||||
|
||||
/// Only defined for carbons who can wear masks and helmets, we just assume other mobs have visible faces
|
||||
/mob/living/proc/is_face_visible()
|
||||
return TRUE
|
||||
|
||||
@@ -419,10 +419,12 @@
|
||||
var/list/result
|
||||
if(client)
|
||||
LAZYINITLIST(client.recent_examines)
|
||||
if(isnull(client.recent_examines[A]) || client.recent_examines[A] < world.time) // originally this wasn't an assoc list, but sometimes the timer failed and atoms stayed in a client's recent_examines, so we check here manually
|
||||
client.recent_examines[A] = world.time + EXAMINE_MORE_TIME
|
||||
if(isnull(client.recent_examines[A]) || client.recent_examines[A] < world.time)
|
||||
result = A.examine(src)
|
||||
client.recent_examines[A] = world.time + EXAMINE_MORE_TIME // set the value to when the examine cooldown ends
|
||||
RegisterSignal(A, COMSIG_PARENT_QDELETING, .proc/clear_from_recent_examines, override=TRUE) // to flush the value if deleted early
|
||||
addtimer(CALLBACK(src, .proc/clear_from_recent_examines, A), EXAMINE_MORE_TIME)
|
||||
handle_eye_contact(A)
|
||||
else
|
||||
result = A.examine_more(src)
|
||||
else
|
||||
@@ -432,10 +434,37 @@
|
||||
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
|
||||
|
||||
/mob/proc/clear_from_recent_examines(atom/A)
|
||||
if(QDELETED(A) || !client)
|
||||
if(!client)
|
||||
return
|
||||
UnregisterSignal(A, COMSIG_PARENT_QDELETING)
|
||||
LAZYREMOVE(client.recent_examines, A)
|
||||
|
||||
/**
|
||||
* handle_eye_contact() is called when we examine() something. If we examine an alive mob with a mind who has examined us in the last second within 5 tiles, we make eye contact!
|
||||
*
|
||||
* Note that if either party has their face obscured, the other won't get the notice about the eye contact
|
||||
* Also note that examine_more() doesn't proc this or extend the timer, just because it's simpler this way and doesn't lose much.
|
||||
* The nice part about relying on examining is that we don't bother checking visibility, because we already know they were both visible to each other within the last second, and the one who triggers it is currently seeing them
|
||||
*/
|
||||
/mob/proc/handle_eye_contact(mob/living/examined_mob)
|
||||
return
|
||||
|
||||
/mob/living/handle_eye_contact(mob/living/examined_mob)
|
||||
if(!istype(examined_mob) || src == examined_mob || examined_mob.stat >= UNCONSCIOUS || !client || !examined_mob.client?.recent_examines || !(src in examined_mob.client.recent_examines))
|
||||
return
|
||||
|
||||
if(get_dist(src, examined_mob) > EYE_CONTACT_RANGE)
|
||||
return
|
||||
|
||||
// check to see if their face is blocked or, if not, a signal blocks it
|
||||
if(examined_mob.is_face_visible() && SEND_SIGNAL(src, COMSIG_MOB_EYECONTACT, examined_mob, TRUE) != COMSIG_BLOCK_EYECONTACT)
|
||||
var/msg = "<span class='smallnotice'>You make eye contact with [examined_mob].</span>"
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, src, msg), 3) // so the examine signal has time to fire and this will print after
|
||||
|
||||
if(is_face_visible() && SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT)
|
||||
var/msg = "<span class='smallnotice'>[src] makes eye contact with you.</span>"
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, examined_mob, msg), 3)
|
||||
|
||||
/**
|
||||
* Point at an atom
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user