diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index eab95d05eb3..909cba565c5 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -220,10 +220,12 @@
#define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags"
///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact"
-///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force)
+///called on a movable (NOT living) when it starts pulling (atom/movable/pulled, state, force)
#define COMSIG_ATOM_START_PULL "movable_start_pull"
-///called on /living when someone starts pulling it (atom/movable/puller, state, force)
+///called on /living when someone starts pulling (atom/movable/pulled, state, force)
#define COMSIG_LIVING_START_PULL "living_start_pull"
+///called on /living when someone is pulled (mob/living/puller)
+#define COMSIG_LIVING_GET_PULLED "living_start_pulled"
/// from /datum/component/singularity/proc/can_move(), as well as /obj/energy_ball/proc/can_move()
/// if a callback returns `SINGULARITY_TRY_MOVE_BLOCK`, then the singularity will not move to that turf
@@ -470,8 +472,12 @@
///From /obj/item/gun/proc/check_botched()
#define COMSIG_MOB_CLUMSY_SHOOT_FOOT "mob_clumsy_shoot_foot"
-///When a carbon mob hugs someone, this is called on the carbon mob.
+///When a carbon mob hugs someone, this is called on the carbon that is hugging. (mob/living/hugger, mob/living/hugged)
#define COMSIG_CARBON_HUG "carbon_hug"
+///When a carbon mob is hugged, this is called on the carbon that is hugged. (mob/living/hugger)
+#define COMSIG_CARBON_HUGGED "carbon_hugged"
+///When a carbon mob is headpatted, this is called on the carbon that is headpatted. (mob/living/headpatter)
+#define COMSIG_CARBON_HEADPAT "carbon_headpatted"
///When a carbon slips. Called on /turf/open/handle_slip()
#define COMSIG_ON_CARBON_SLIP "carbon_slip"
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 4655b4d36c9..7ba5fbd7bb3 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -281,6 +281,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_GRABWEAKNESS "grab_weakness"
#define TRAIT_SNOB "snob"
#define TRAIT_BALD "bald"
+#define TRAIT_BADTOUCH "bad_touch"
///Trait for dryable items
#define TRAIT_DRYABLE "trait_dryable"
///Trait for dried items
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index a78d8f99319..b398a428ee3 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -153,7 +153,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_FRIENDLY" = TRAIT_FRIENDLY,
"TRAIT_GRABWEAKNESS" = TRAIT_GRABWEAKNESS,
"TRAIT_SNOB" = TRAIT_SNOB,
- "TRAIT_BALD" = TRAIT_BALD
+ "TRAIT_BALD" = TRAIT_BALD,
+ "TRAIT_BADTOUCH" = TRAIT_BADTOUCH
),
/obj/item/bodypart = list(
diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm
index 68ab39a28f7..6b7b3a99933 100644
--- a/code/controllers/subsystem/processing/quirks.dm
+++ b/code/controllers/subsystem/processing/quirks.dm
@@ -20,7 +20,13 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
if(!quirks.len)
SetupQuirks()
- quirk_blacklist = list(list("Blind","Nearsighted"),list("Jolly","Depression","Apathetic","Hypersensitive"),list("Ageusia","Vegetarian","Deviant Tastes"),list("Ananas Affinity","Ananas Aversion"),list("Alcohol Tolerance","Light Drinker"),list("Clown Fan","Mime Fan"))
+ quirk_blacklist = list(list("Blind","Nearsighted"), \
+ list("Jolly","Depression","Apathetic","Hypersensitive"), \
+ list("Ageusia","Vegetarian","Deviant Tastes"), \
+ list("Ananas Affinity","Ananas Aversion"), \
+ list("Alcohol Tolerance","Light Drinker"), \
+ list("Clown Fan","Mime Fan"), \
+ list("Bad Touch", "Friendly"))
return ..()
/datum/controller/subsystem/processing/quirks/proc/SetupQuirks()
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index cf8d5645ddf..5b2866ff039 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -285,3 +285,13 @@
/datum/mood_event/bald
description ="I need something to cover my head...\n"
mood_change = -3
+
+/datum/mood_event/bad_touch
+ description = "I don't like when people touch me.\n"
+ mood_change = -3
+ timeout = 4 MINUTES
+
+/datum/mood_event/very_bad_touch
+ description = "I really don't like when people touch me.\n"
+ mood_change = -5
+ timeout = 4 MINUTES
diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index 7dd7e26bd2a..05bea7980ac 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -735,6 +735,32 @@
carbon_quirk_holder.vomit()
carbon_quirk_holder.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_APPENDIX,ORGAN_SLOT_LUNGS,ORGAN_SLOT_HEART,ORGAN_SLOT_LIVER,ORGAN_SLOT_STOMACH),10)
+/datum/quirk/bad_touch
+ name = "Bad Touch"
+ desc = "You don't like hugs. You'd really prefer if people just left you alone."
+ mob_trait = TRAIT_BADTOUCH
+ value = -1
+ gain_text = "You just want people to leave you alone."
+ lose_text = "You could use a big hug."
+ medical_record_text = "Patient has disdain for being touched. Potentially has undiagnosed haphephobia."
+ mood_quirk = TRUE
+ hardcore_value = 1
+
+/datum/quirk/bad_touch/add()
+ RegisterSignal(quirk_holder, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HUGGED, COMSIG_CARBON_HEADPAT), .proc/uncomfortable_touch)
+
+/datum/quirk/bad_touch/remove()
+ UnregisterSignal(quirk_holder, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HUGGED, COMSIG_CARBON_HEADPAT))
+
+/datum/quirk/bad_touch/proc/uncomfortable_touch()
+ SIGNAL_HANDLER
+
+ var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
+ if(mood.sanity <= SANITY_NEUTRAL)
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_touch", /datum/mood_event/very_bad_touch)
+ else
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_touch", /datum/mood_event/bad_touch)
+
#undef LOCATION_LPOCKET
#undef LOCATION_RPOCKET
#undef LOCATION_BACKPACK
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index d109c9ab14a..0fad7fbdd0d 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -472,8 +472,11 @@
//SKYRAT EDIT ADDITION END
else if(check_zone(M.zone_selected) == BODY_ZONE_HEAD) //Headpats!
+ SEND_SIGNAL(src, COMSIG_CARBON_HEADPAT, M)
M.visible_message("[M] gives [src] a pat on the head to make [p_them()] feel better!", \
- "You give [src] a pat on the head to make [p_them()] feel better!")
+ null, "You hear a soft patter.", DEFAULT_MESSAGE_RANGE, list(M, src))
+ to_chat(M, "You give [src] a pat on the head to make [p_them()] feel better!")
+ to_chat(src, "[M] gives you a pat on the head to make you feel better! ")
//SKYRAT EDIT ADDITION BEGIN - EMOTES
if(HAS_TRAIT(src, TRAIT_EXCITABLE))
if(!src.dna.species.is_wagging_tail(src))
@@ -481,6 +484,7 @@
//SKYRAT EDIT ADDITION END
else
+ SEND_SIGNAL(src, COMSIG_CARBON_HUGGED, M)
SEND_SIGNAL(M, COMSIG_CARBON_HUG, M, src)
M.visible_message("[M] hugs [src] to make [p_them()] feel better!", \
null, "You hear the rustling of clothes.", DEFAULT_MESSAGE_RANGE, list(M, src))
@@ -489,11 +493,15 @@
// Warm them up with hugs
share_bodytemperature(M)
- if(bodytemperature > M.bodytemperature)
- SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/warmhug, src) // Hugger got a warm hug
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug) // Reciver always gets a mood for being hugged
- else
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/warmhug, M) // You got a warm hug
+
+ // No moodlets for people who hate touches
+ if(!HAS_TRAIT(src, TRAIT_BADTOUCH))
+ if(bodytemperature > M.bodytemperature)
+ if(!HAS_TRAIT(M, TRAIT_BADTOUCH))
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/warmhug, src) // Hugger got a warm hug (Unless they hate hugs)
+ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug) // Reciver always gets a mood for being hugged
+ else
+ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/warmhug, M) // You got a warm hug
// Let people know if they hugged someone really warm or really cold
if(M.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT)
@@ -507,12 +515,13 @@
to_chat(M, "It feels like [src] is freezing as you hug them.")
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
- var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
- if (mood.sanity >= SANITY_GREAT)
+ var/datum/component/mood/hugger_mood = M.GetComponent(/datum/component/mood)
+ if (hugger_mood.sanity >= SANITY_GREAT)
new /obj/effect/temp_visual/heart(loc)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
- else if (mood.sanity >= SANITY_DISTURBED)
+ else if (hugger_mood.sanity >= SANITY_DISTURBED)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/betterhug, M)
+
AdjustStun(-60)
AdjustKnockdown(-60)
AdjustUnconscious(-60)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 30832332226..76a3af5fedc 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -311,6 +311,7 @@
M.LAssailant = usr
if(isliving(M))
var/mob/living/L = M
+ SEND_SIGNAL(M, COMSIG_LIVING_GET_PULLED, src)
//Share diseases that are spread by touch
for(var/thing in diseases)
var/datum/disease/D = thing