diff --git a/code/__SANDCODE/DEFINES/lewd.dm b/code/__SANDCODE/DEFINES/lewd.dm
index 18dca99ea2..789ab5599b 100644
--- a/code/__SANDCODE/DEFINES/lewd.dm
+++ b/code/__SANDCODE/DEFINES/lewd.dm
@@ -9,3 +9,29 @@ GLOBAL_LIST_INIT(lewd_prefs_choices, list(
"Ask",
"No"
))
+
+#define CUM_TARGET_MOUTH "mouth"
+#define CUM_TARGET_THROAT "throat"
+#define CUM_TARGET_VAGINA "vagina"
+#define CUM_TARGET_ANUS "anus"
+#define CUM_TARGET_HAND "hand"
+#define CUM_TARGET_BREASTS "breasts"
+#define CUM_TARGET_FEET "feet"
+#define CUM_TARGET_PENIS "penis"
+//Weird defines go here
+#define CUM_TARGET_EARS "ears"
+#define CUM_TARGET_EYES "eyes"
+//
+#define GRINDING_FACE_WITH_ANUS "faceanus"
+#define GRINDING_FACE_WITH_FEET "facefeet"
+#define GRINDING_MOUTH_WITH_FEET "mouthfeet"
+#define THIGH_SMOTHERING "thigh_smother"
+#define NUTS_TO_FACE "nut_face"
+
+#define NORMAL_LUST 10
+#define LOW_LUST 1
+
+#define REQUIRE_NONE 0
+#define REQUIRE_EXPOSED 1
+#define REQUIRE_UNEXPOSED 2
+#define REQUIRE_ANY 3
diff --git a/modular_sand/code/datums/interactions/interaction_mob.dm b/modular_sand/code/datums/interactions/interaction_mob.dm
index e440e260d7..4fa398ea72 100644
--- a/modular_sand/code/datums/interactions/interaction_mob.dm
+++ b/modular_sand/code/datums/interactions/interaction_mob.dm
@@ -1,36 +1,14 @@
/mob/living/proc/has_hands()
- return FALSE
-
-/mob/living/has_hands()
return TRUE
/mob/living/proc/has_mouth()
return TRUE
/mob/living/proc/mouth_is_free()
- return TRUE
+ return !is_mouth_covered()
/mob/living/proc/foot_is_free()
- return TRUE
+ return is_barefoot()
/mob/living/carbon/human/has_mouth()
- var/obj/item/bodypart/head/headass
- for(var/obj/item/bodypart/head/shoeonhead in bodyparts)
- headass = shoeonhead
- if(headass)
- return TRUE
- return FALSE
-
-/mob/living/mouth_is_free()
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- return !H.wear_mask
- else
- return TRUE
-
-/mob/living/foot_is_free()
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- return !H.shoes
- else
- return TRUE
+ return get_bodypart(BODY_ZONE_HEAD)
diff --git a/modular_sand/code/datums/interactions/lewd/_lewd.dm b/modular_sand/code/datums/interactions/lewd/_lewd.dm
index 6639e2ac7d..0553f0997e 100644
--- a/modular_sand/code/datums/interactions/lewd/_lewd.dm
+++ b/modular_sand/code/datums/interactions/lewd/_lewd.dm
@@ -1,28 +1,3 @@
-#define CUM_TARGET_MOUTH "mouth"
-#define CUM_TARGET_THROAT "throat"
-#define CUM_TARGET_VAGINA "vagina"
-#define CUM_TARGET_ANUS "anus"
-#define CUM_TARGET_HAND "hand"
-#define CUM_TARGET_BREASTS "breasts"
-#define CUM_TARGET_FEET "feet"
-#define CUM_TARGET_PENIS "penis"
-//Weird defines go here
-#define CUM_TARGET_EARS "ears"
-#define CUM_TARGET_EYES "eyes"
-//
-#define GRINDING_FACE_WITH_ANUS "faceanus"
-#define GRINDING_FACE_WITH_FEET "facefeet"
-#define GRINDING_MOUTH_WITH_FEET "mouthfeet"
-#define THIGH_SMOTHERING "thigh_smother"
-#define NUTS_TO_FACE "nut_face"
-
-#define NORMAL_LUST 10
-#define LOW_LUST 1
-
-#define REQUIRE_NONE 0
-#define REQUIRE_EXPOSED 1
-#define REQUIRE_UNEXPOSED 2
-#define REQUIRE_ANY 3
/*--------------------------------------------------
-------------------MOB STUFF----------------------
@@ -30,9 +5,27 @@
*/
//I'm sorry, lewd should not have mob procs such as life() and such in it. //NO SHIT IT SHOULDNT I REMOVED THEM
-// Lewd interactions have a blacklist for certain mobs. When we evalute the user and target, both of
-// their requirements must be satisfied, and the mob must not be of a blacklisted type.
-// This should not be too weighty on the server, as the check is only run to generate the menu options.
+/*
+ * Lewd interactions have a blacklist for certain mobs. When we evalute the user and target, both of
+ * their requirements must be satisfied, and the mob must not be of a blacklisted type.
+*/
+/datum/interaction/lewd
+ var/list/blacklisted_mobs = list(/mob/living/simple_animal/pet,
+ /mob/living/simple_animal/cockroach,
+ /mob/living/simple_animal/babyKiwi,
+ /mob/living/simple_animal/butterfly,
+ /mob/living/simple_animal/chick,
+ /mob/living/simple_animal/chicken,
+ /mob/living/simple_animal/cow,
+ /mob/living/simple_animal/crab,
+ /mob/living/simple_animal/kiwi,
+ /mob/living/simple_animal/parrot,
+ /mob/living/simple_animal/sloth,
+ /mob/living/simple_animal/pickle,
+ /mob/living/simple_animal/hostile/retaliate/goat)
+
+
+/// This should not be too weighty on the server, as the check is only run to generate the menu options.
/datum/interaction/lewd/evaluate_user(mob/living/user, silent, action_check)
. = ..()
if(.)
@@ -136,14 +129,14 @@
lust = num
lastlusttime = world.time
-/mob/living/proc/has_penis(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_penis(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_penis && !istype(C))
return TRUE
if(istype(C))
var/obj/item/organ/genital/peepee = C.getorganslot(ORGAN_SLOT_PENIS)
if(peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -160,12 +153,12 @@
return TRUE
return FALSE
-/mob/living/proc/has_balls(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_balls(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/organ/genital/peepee = C.getorganslot(ORGAN_SLOT_TESTICLES)
if(peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -182,14 +175,14 @@
return TRUE
return FALSE
-/mob/living/proc/has_vagina(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_vagina(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_vagina && !istype(C))
return TRUE
if(istype(C))
var/obj/item/organ/genital/peepee = C.getorganslot(ORGAN_SLOT_VAGINA)
if(peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -206,14 +199,14 @@
return TRUE
return FALSE
-/mob/living/proc/has_breasts(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_breasts(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_breasts && !istype(C))
return TRUE
if(istype(C))
var/obj/item/organ/genital/peepee = C.getorganslot(ORGAN_SLOT_BREASTS)
if(peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -230,10 +223,10 @@
return TRUE
return FALSE
-/mob/living/proc/has_anus(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_anus(visibility = REQUIRE_ANY)
if(has_anus && !iscarbon(src))
return TRUE
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -261,7 +254,7 @@
else
return TRUE
-/mob/living/proc/has_hand(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_hand(visibility = REQUIRE_ANY)
if(iscarbon(src))
var/mob/living/carbon/C = src
var/handcount = 0
@@ -276,7 +269,7 @@
covered = G.body_parts_covered
if(covered & HANDS)
iscovered = TRUE
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return handcount
if(REQUIRE_EXPOSED)
@@ -293,7 +286,7 @@
return handcount
return FALSE
-/mob/living/proc/has_feet(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_feet(visibility = REQUIRE_ANY)
if(iscarbon(src))
var/mob/living/carbon/C = src
var/feetcount = 0
@@ -307,7 +300,7 @@
covered = TRUE
if(covered)
iscovered = TRUE
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return feetcount
if(REQUIRE_EXPOSED)
@@ -328,12 +321,12 @@
return has_feet(REQUIRE_ANY)
//weird procs go here
-/mob/living/proc/has_ears(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_ears(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EARS)
if(peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -350,12 +343,12 @@
return TRUE
return FALSE
-/mob/living/proc/has_earsockets(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_earsockets(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EARS)
if(!peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -372,12 +365,12 @@
return TRUE
return FALSE
-/mob/living/proc/has_eyes(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_eyes(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EYES)
if(peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -394,12 +387,12 @@
return TRUE
return FALSE
-/mob/living/proc/has_eyesockets(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_eyesockets(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EYES)
if(!peepee)
- switch(nintendo)
+ switch(visibility)
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
@@ -418,30 +411,33 @@
///Are we wearing something that covers our chest?
/mob/living/proc/is_topless()
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- if((!(H.wear_suit) || !(H.wear_suit.body_parts_covered & CHEST)) && (!(H.w_uniform) || !(H.w_uniform.body_parts_covered & CHEST)) && (!(H.w_shirt) || !(H.w_shirt.body_parts_covered & CHEST)))
- return TRUE
- else
- return TRUE
+ for(var/slot in GLOB.slots)
+ var/obj/item/clothing = vars[slot]
+ if(clothing)
+ if(clothing.body_parts_covered & CHEST)
+ return FALSE
+ // If didn't stop before, then we're topless
+ return TRUE
///Are we wearing something that covers our groin?
/mob/living/proc/is_bottomless()
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- if((!(H.wear_suit) || !(H.wear_suit.body_parts_covered & GROIN)) && (!(H.w_uniform) || !(H.w_uniform.body_parts_covered & GROIN)) && (!(H.w_underwear) || !(H.w_underwear.body_parts_covered & GROIN)))
- return TRUE
- else
- return TRUE
+ for(var/slot in GLOB.slots)
+ var/obj/item/clothing = vars[slot]
+ if(clothing)
+ if(clothing.body_parts_covered & GROIN)
+ return FALSE
+ // If didn't stop before, then we're bottomless
+ return TRUE
///Are we wearing something that covers our shoes?
/mob/living/proc/is_barefoot()
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- if((!(H.wear_suit) || !(H.wear_suit.body_parts_covered & GROIN)) && (!(H.w_socks) || !(H.w_socks.body_parts_covered & FEET)))
- return TRUE
- else
- return TRUE
+ for(var/slot in GLOB.slots)
+ var/obj/item/clothing = vars[slot]
+ if(clothing)
+ if(clothing.body_parts_covered & FEET)
+ return FALSE
+ // If didn't stop before, then we're barefoot
+ return TRUE
/mob/living/proc/moan()
if(!(prob(get_lust() / get_lust_tolerance() * 65)))
@@ -836,789 +832,12 @@
return TRUE
return FALSE
-/mob/living/proc/set_is_fucking(mob/living/partner, orifice, var/obj/item/organ/genital/genepool)
+/mob/living/proc/set_is_fucking(mob/living/partner, orifice, obj/item/organ/genital/genepool)
last_partner = partner
last_orifice = orifice
last_genital = genepool
-/*
- --------------------------------------------------
- ---------------LEWD PROCESS DATUM-----------------
- --------------------------------------------------
-*/
-
-/mob/living/proc/do_oral(mob/living/partner, var/fucktarget = "penis")
- var/message
- var/obj/item/organ/genital/peepee = null
- var/lust_increase = NORMAL_LUST
- var/u_His = p_their()
- var/u_He = p_they()
- var/u_Were = p_theyre()
-
- if(partner.is_fucking(src, CUM_TARGET_MOUTH))
- if(prob(partner.get_sexual_potency()))
- if(istype(src, /mob/living)) // Argh.
- var/mob/living/H = src
- H.adjustOxyLoss(3)
- message = "goes in deep on \the [partner]."
- lust_increase += 5
- else
- var/improv = FALSE
- switch(fucktarget)
- if("vagina")
- if(partner.has_vagina())
- message = pick(
- "licks \the [partner]'s pussy.",
- "runs [u_His] tongue up the shape of \the [partner]'s pussy.",
- "traces \the [partner]'s slit with [u_His] tongue.",
- "darts the tip of [u_His] tongue around \the [partner]'s clit.",
- "laps slowly at \the [partner].",
- "kisses \the [partner]'s delicate folds.",
- "tastes \the [partner].",
- )
- else
- improv = TRUE
- if("penis")
- if(partner.has_penis())
- message = pick(
- "sucks \the [partner]'s off.",
- "runs [u_His] tongue up the shape of \the [partner]'s cock.",
- "traces \the [partner]'s cock with [u_His] tongue.",
- "darts the tip of [u_His] tongue around tip of \the [partner]'s cock.",
- "laps slowly at \the [partner]'s shaft.",
- "kisses the base of \the [partner]'s shaft.",
- "takes \the [partner] deeper into [u_His] mouth.",
- )
- else
- improv = TRUE
- if(improv)
- // get confused about how to do the sex
- message = pick(
- "licks \the [partner].",
- "looks a little unsure of where to lick \the [partner].",
- "runs [u_His] tongue between \the [partner]'s legs.",
- "kisses \the [partner]'s thigh.",
- "tries [u_His] best with \the [partner].",
- )
- else
- var/improv = FALSE
- switch(fucktarget)
- if("vagina")
- if(partner.has_vagina())
- message = pick(
- "buries [u_His] face in \the [partner]'s pussy.",
- "nuzzles \the [partner]'s wet sex.",
- "finds [u_His] face caught between \the [partner]'s thighs.",
- "kneels down between \the [partner]'s legs.",
- "grips \the [partner]'s legs, pushing them apart.",
- "sinks [u_His] face in between \the [partner]'s thighs.",
- )
- else
- improv = TRUE
- if("penis")
- if(partner.has_penis())
- message = pick(
- "takes \the [partner]'s cock into [u_His] mouth.",
- "wraps [u_His] lips around \the [partner]'s cock.",
- "finds [u_His] face between \the [partner]'s thighs.",
- "kneels down between \the [partner]'s legs.",
- "grips \the [partner]'s legs, kissing at the tip of [u_His] cock.",
- "goes down on \the [partner].",
- )
- else
- improv = TRUE
- if(improv)
- message = pick(
- "begins to lick \the [partner].",
- "starts kissing \the [partner]'s thigh.",
- "sinks down between \the [partner]'s thighs.",
- "briefly flashes a puzzled look from between \the [partner]'s legs.",
- "looks unsure of how to handle \the [partner]'s lack of genitalia.",
- "seems like [u_He] [u_Were] expecting \the [partner] to have a cock or a pussy or ... something.",
- )
- peepee = null
- else
- if(ishuman(partner))
- var/mob/living/carbon/human/pardner = partner
- switch(fucktarget)
- if("vagina")
- peepee = pardner.getorganslot(ORGAN_SLOT_VAGINA)
- if("penis")
- peepee = pardner.getorganslot(ORGAN_SLOT_PENIS)
- partner.set_is_fucking(src, CUM_TARGET_MOUTH, peepee)
-
- playlewdinteractionsound(get_turf(src), pick('modular_sand/sound/interactions/bj1.ogg',
- 'modular_sand/sound/interactions/bj2.ogg',
- 'modular_sand/sound/interactions/bj3.ogg',
- 'modular_sand/sound/interactions/bj4.ogg',
- 'modular_sand/sound/interactions/bj5.ogg',
- 'modular_sand/sound/interactions/bj6.ogg',
- 'modular_sand/sound/interactions/bj7.ogg',
- 'modular_sand/sound/interactions/bj8.ogg',
- 'modular_sand/sound/interactions/bj9.ogg',
- 'modular_sand/sound/interactions/bj10.ogg',
- 'modular_sand/sound/interactions/bj11.ogg'), 50, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(lust_increase, CUM_TARGET_MOUTH, src)
- lust_increase = NORMAL_LUST //RESET IT REE
-
-/mob/living/proc/do_facefuck(mob/living/partner, var/fucktarget = "penis")
- var/message
- var/obj/item/organ/genital/peepee = null
- var/retaliation_message = FALSE
-
- var/u_His = p_their()
- var/t_Him = partner.p_them()
- var/t_Hes = partner.p_theyre()
-
- if(is_fucking(partner, CUM_TARGET_MOUTH))
- var/improv = FALSE
- switch(fucktarget)
- if("vagina")
- if(has_vagina())
- message = pick(
- "grinds [u_His] pussy into \the [partner]'s face.",
- "grips the back of \the [partner]'s head, forcing [t_Him] onto [u_His] pussy.",
- "rolls [u_His] pussy against \the [partner]'s tongue.",
- "slides \the [partner]'s mouth between [u_His] legs.",
- "looks \the [partner]'s in the eyes as [u_His] pussy presses into a waiting tongue.",
- "sways [u_His] hips, pushing [u_His] sex into \the [partner]'s face.",
- )
- if(partner.a_intent == INTENT_HARM)
- // adjustBruteLoss(5)
- retaliation_message = pick(
- "looks deeply displeased to be there.",
- "struggles to escape from between \the [src]'s thighs.",
- )
- else
- improv = TRUE
- if("penis")
- if(has_penis())
- message = pick(
- "roughly fucks \the [partner]'s mouth.",
- "forces [u_His] cock down \the [partner]'s throat.",
- "pushes in against \the [partner]'s tongue until a tight gagging sound comes.",
- "grips \the [partner]'s hair and draws [t_Him] to the base of the cock.",
- "looks \the [partner]'s in the eyes as [u_His] cock presses into a waiting tongue.",
- "rolls [u_His] hips hard, sinking into \the [partner]'s mouth.",
- )
- if(partner.a_intent == INTENT_HARM)
- // adjustBruteLoss(5)
- retaliation_message = pick(
- "stares up from between \the [src]'s knees, trying to squirm away.",
- "struggles to escape from between \the [src]'s legs.",
- )
- else
- improv = TRUE
- if(improv)
- message = pick(
- "grinds against \the [partner]'s face.",
- "feels \the [partner]'s face between bare legs.",
- "pushes in against \the [partner]'s tongue.",
- "grips \the [partner]'s hair, drawing [t_Him] into the strangely sexless spot between [u_His] legs.",
- "looks \the [partner]'s in the eyes as [t_Hes] caught beneath two thighs.",
- "rolls [u_His] hips hard against \the [partner]'s face.",
- )
- if(partner.a_intent == INTENT_HARM)
- // adjustBruteLoss(5)
- retaliation_message = pick(
- "stares up from between \the [src]'s knees, trying to squirm away.",
- "struggles to escape from between \the [src]'s legs.",
- )
- else
- var/improv = FALSE
- switch(fucktarget)
- if("vagina")
- if(has_vagina())
- message = "forces \the [partner]'s face into [u_His] pussy."
- else
- improv = TRUE
- if("penis")
- if(has_penis())
- if(is_fucking(partner, CUM_TARGET_THROAT))
- message = "retracts [u_His] cock from \the [partner]'s throat"
- else
- message = "shoves [u_His] cock into \the [partner]'s mouth"
- else
- improv = TRUE
- if(improv)
- message = "shoves [u_His] crotch into \the [partner]'s face."
- else
- if(ishuman(partner))
- var/mob/living/carbon/human/pardner = partner
- switch(fucktarget)
- if("vagina")
- peepee = pardner.getorganslot(ORGAN_SLOT_VAGINA)
- if("penis")
- peepee = pardner.getorganslot(ORGAN_SLOT_PENIS)
- set_is_fucking(partner , CUM_TARGET_MOUTH, peepee)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/oral1.ogg',
- 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- if(retaliation_message)
- visible_message(message = "\The [partner] [retaliation_message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_MOUTH, partner)
-
-/mob/living/proc/thigh_smother(mob/living/partner, var/fucktarget = "penis")
- var/message
- var/obj/item/organ/genital/peepee = null
- var/lust_increase = 1
-
- var/u_His = p_their()
- var/t_His = partner.p_their()
- var/t_Him = partner.p_them()
- var/t_Hes = partner.p_theyre()
-
- if(is_fucking(partner, THIGH_SMOTHERING))
- var/improv = FALSE
- switch(fucktarget)
- if("vagina")
- if(has_vagina())
- message = pick(list(
- "presses [u_His] weight down onto \the [partner]'s face, blocking [t_His] vision completely.",
- "rides \the [partner]'s face, grinding [u_His] wet pussy all over it."))
- else
- improv = TRUE
- if("penis")
- if(has_penis())
- message = pick(list("presses [u_His] weight down onto \the [partner]'s face, blocking [t_His] vision completely.",
- "forces [u_His] dick and nutsack into \the [partner]'s face as [t_Hes] stuck locked in between [u_His] thighs.",
- "slips [u_His] cock into \the [partner]'s helpless mouth, keeping [u_His] shaft pressed hard into [t_His] face."))
- else
- improv = TRUE
- if(improv)
- message = "rubs [u_His] groin up and down \the [partner]'s face."
- else
- var/improv = FALSE
- switch(fucktarget)
- if("vagina")
- if(has_vagina())
- message = pick(list(
- "clambers over \the [partner]'s face and pins [t_Him] down with [u_His] thighs, [u_His] moist slit rubbing all over \the [partner]'s mouth and nose.",
- "locks [u_His] legs around \the [partner]'s head before pulling it into [u_His] mound."))
- else
- improv = TRUE
- if("penis")
- if(has_penis())
- message = pick(list(
- "clambers over \the [partner]'s face and pins [t_Him] down with [u_His] thighs, then slowly inching closer and covering [t_His] eyes and nose with [u_His] leaking erection.",
- "locks [u_His] legs around \the [partner]'s head before pulling it into [u_His] fat package, smothering [t_Him]."))
- else
- improv = TRUE
- if(improv)
- message = "deviously locks [u_His] legs around \the [partner]'s head and smothers it in [u_His] thighs."
- else
- if(ishuman(partner))
- var/mob/living/carbon/human/pardner = partner
- switch(fucktarget)
- if("vagina")
- peepee = pardner.getorganslot(ORGAN_SLOT_VAGINA)
- if("penis")
- peepee = pardner.getorganslot(ORGAN_SLOT_PENIS)
- set_is_fucking(partner , THIGH_SMOTHERING, peepee)
-
- var/file = pick('modular_sand/sound/interactions/bj10.ogg',
- 'modular_sand/sound/interactions/bj3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg')
- playlewdinteractionsound(loc, file, 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(lust_increase, THIGH_SMOTHERING, partner)
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/oral1.ogg',
- 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
- handle_post_sex(NORMAL_LUST, CUM_TARGET_MOUTH, partner)
-
-/mob/living/proc/do_throatfuck(mob/living/partner)
- var/message
- var/obj/item/organ/genital/peepee = null
- var/retaliation_message = FALSE
-
- var/u_His = p_their()
- var/t_His = partner.p_their()
- var/t_Him = partner.p_them()
-
- if(is_fucking(partner, CUM_TARGET_THROAT))
- message = "[pick(
- "brutally shoves [u_His] cock into \the [partner]'s throat to make [t_Him] gag.",
- "chokes \the [partner] on [u_His] dick, going in balls deep.",
- "slams in and out of \the [partner]'s mouth, [u_His] balls slapping off [t_His] face.")]"
- if(rand(3))
- partner.emote("chokes on \The [src]")
- if(prob(1) && istype(partner, /mob/living))
- var/mob/living/H = partner
- H.adjustOxyLoss(5)
- if(partner.a_intent == INTENT_HARM)
- // adjustBruteLoss(5)
- retaliation_message = pick(
- "stares up from between \the [src]'s knees, trying to squirm away.",
- "struggles to escape from between \the [src]'s legs.",
- )
- else if(is_fucking(partner, CUM_TARGET_MOUTH))
- message = "thrusts deeper into \the [partner]'s mouth and down [t_His] throat."
- if(ishuman(src))
- var/mob/living/carbon/human/coomer = partner
- peepee = coomer.getorganslot(ORGAN_SLOT_PENIS)
- set_is_fucking(partner , CUM_TARGET_THROAT, peepee)
- else
- message = "forces [u_His] dick deep down \the [partner]'s throat"
- if(ishuman(src))
- var/mob/living/carbon/human/coomer = partner
- peepee = coomer.getorganslot(ORGAN_SLOT_PENIS)
- set_is_fucking(partner , CUM_TARGET_THROAT, peepee)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/oral1.ogg',
- 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- if(retaliation_message)
- visible_message(message = "\The [partner] [retaliation_message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_THROAT, partner)
-
-/mob/living/proc/nut_face(var/mob/living/partner)
-
- var/message
-
- var/u_His = p_their()
- var/t_His = partner.p_their()
-
- var/lust_increase = 1
-
- if(is_fucking(partner, NUTS_TO_FACE))
- message = pick(list(
- "grabs the back of [partner]'s head and pulls it into [u_His] crotch.",
- "jams [u_His] nutsack right into [partner]'s face.",
- "roughly grinds [u_His] fat nutsack into [partner]'s mouth.",
- "pulls out [u_His] saliva-covered nuts from [partner]'s violated mouth and then wipes off the slime onto [t_His] face."))
- else
- message = pick(list("wedges a digit into the side of [partner]'s jaw and pries it open before using [u_His] other hand to shove [u_His] whole nutsack inside!", "stands with [u_His] groin inches away from [partner]'s face, then thrusting [u_His] hips forward and smothering [partner]'s whole face with [u_His] heavy ballsack."))
- set_is_fucking(partner , NUTS_TO_FACE, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- /*playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/nuts1.ogg',
- 'modular_sand/sound/interactions/nuts2.ogg',
- 'modular_sand/sound/interactions/nuts3.ogg',
- 'modular_sand/sound/interactions/nuts4.ogg'), 70, 1, -1)*/ //These files don't even exist but nobody noticed because double-quotes were used instead of single.
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(lust_increase, CUM_TARGET_MOUTH, partner)
-
-/mob/living/proc/do_anal(mob/living/partner)
- var/message
-
- var/u_His = p_their()
- var/t_His = partner.p_their()
-
- if(is_fucking(partner, CUM_TARGET_ANUS))
- message = "[pick(
- "thrusts in and out of \the [partner]'s ass.",
- "pounds \the [partner]'s ass.",
- "slams [u_His] hips up against \the [partner]'s ass hard.",
- "goes balls deep into \the [partner]'s ass over and over again.")]"
- else
- message = "[pick(
- "works [u_His] cock into \the [partner]'s asshole.",
- "grabs the base of [u_His] twitching cock and presses the tip into \the [partner]'s asshole.",
- "shoves [u_His] dick deep inside of \the [partner]'s ass, making [t_His] rear jiggle.")]"
- set_is_fucking(partner, CUM_TARGET_ANUS, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang1.ogg',
- 'modular_sand/sound/interactions/bang2.ogg',
- 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_ANUS, partner)
- partner.handle_post_sex(NORMAL_LUST, null, src)
-
-/mob/living/proc/do_vaginal(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(partner, CUM_TARGET_VAGINA))
- message = "[pick(
- "pounds \the [partner]'s pussy.",
- "shoves [u_His] dick deep into \the [partner]'s pussy",
- "thrusts in and out of \the [partner]'s cunt.",
- "goes balls deep into \the [partner]'s pussy over and over again.")]"
- else
- message = "slides [u_His] cock into \the [partner]'s pussy."
- set_is_fucking(partner, CUM_TARGET_VAGINA, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/champ1.ogg',
- 'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, partner)
- partner.handle_post_sex(NORMAL_LUST, null, src)
-
-/mob/living/proc/do_mount(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_VAGINA))
- message = "[pick("rides \the [partner]'s dick.",
- "forces [partner]'s cock on [u_His] pussy")]"
- else
- message = "slides [u_His] pussy onto \the [partner]'s cock."
- partner.set_is_fucking(src, CUM_TARGET_VAGINA, partner.getorganslot(ORGAN_SLOT_PENIS) ? partner.getorganslot(ORGAN_SLOT_PENIS) : null)
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang1.ogg',
- 'modular_sand/sound/interactions/bang2.ogg',
- 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, src)
- handle_post_sex(NORMAL_LUST, null, partner)
-
-/mob/living/proc/do_mountass(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_ANUS))
- message = "[pick("rides \the [partner]'s dick.",
- "forces [partner]'s cock on [u_His] ass")]"
- else
- message = "lowers [u_His] ass onto \the [partner]'s cock."
- partner.set_is_fucking(src, CUM_TARGET_ANUS, partner.getorganslot(ORGAN_SLOT_PENIS) ? partner.getorganslot(ORGAN_SLOT_PENIS) : null)
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang1.ogg',
- 'modular_sand/sound/interactions/bang2.ogg',
- 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_ANUS, src)
- handle_post_sex(NORMAL_LUST, null, partner)
-
-/mob/living/proc/do_tribadism(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_VAGINA))
- message = "[pick("grinds [u_His] pussy against \the [partner]'s cunt.",
- "rubs [u_His] cunt against \the [partner]'s pussy.",
- "thrusts against \the [partner]'s pussy.",
- "humps \the [partner], [u_His] pussies grinding against each other.")]"
- else
- message = "presses [u_His] pussy into \the [partner]'s own."
- partner.set_is_fucking(src, CUM_TARGET_VAGINA, partner.getorganslot(ORGAN_SLOT_VAGINA) ? partner.getorganslot(ORGAN_SLOT_VAGINA) : null)
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/squelch1.ogg',
- 'modular_sand/sound/interactions/squelch2.ogg',
- 'modular_sand/sound/interactions/squelch3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, src)
- handle_post_sex(NORMAL_LUST, null, partner)
-
-/mob/living/proc/do_fingering(mob/living/partner)
- visible_message(message = "\The [src] [pick("fingers \the [partner].",
- "fingers \the [partner]'s pussy.",
- "fingers \the [partner] hard.")]", ignored_mobs = get_unconsenting())
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- partner.handle_post_sex(NORMAL_LUST, null, src)
-
-/mob/living/proc/do_fingerass(mob/living/partner)
- visible_message(message = "\The [src] [pick("fingers \the [partner].",
- "fingers \the [partner]'s asshole.",
- "fingers \the [partner] hard.")]", ignored_mobs = get_unconsenting())
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- partner.handle_post_sex(NORMAL_LUST, null, src)
-
-/mob/living/proc/do_rimjob(mob/living/partner)
- visible_message(message = "\The [src] licks \the [partner]'s asshole.", ignored_mobs = get_unconsenting())
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- partner.handle_post_sex(NORMAL_LUST, null, src)
-
-/mob/living/proc/do_handjob(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_HAND))
- message = "[pick("jerks \the [partner] off.",
- "works \the [partner]'s shaft.",
- "wanks \the [partner]'s cock hard.")]"
- else
- message = "[pick("wraps [u_His] hand around \the [partner]'s cock.",
- "starts playing with \the [partner]'s cock")]"
- partner.set_is_fucking(src, CUM_TARGET_HAND, partner.getorganslot(ORGAN_SLOT_PENIS) ? partner.getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(src, pick('modular_sand/sound/interactions/bang1.ogg',
- 'modular_sand/sound/interactions/bang2.ogg',
- 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, src)
-
-/mob/living/proc/do_breastfuck(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(partner, CUM_TARGET_BREASTS))
- message = "[pick("fucks \the [partner]'s' breasts.",
- "grinds [u_His] cock between \the [partner]'s boobs.",
- "thrusts into \the [partner]'s tits.",
- "grabs \the [partner]'s breasts together and presses [u_His] dick between them.")]"
- else
- message = "pushes \the [partner]'s breasts together and presses [u_His] dick between them."
- set_is_fucking(partner , CUM_TARGET_BREASTS, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang1.ogg',
- 'modular_sand/sound/interactions/bang2.ogg',
- 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_BREASTS, partner)
-
-/mob/living/proc/do_mountface(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(partner, GRINDING_FACE_WITH_ANUS))
- message = "[pick("grinds [u_His] ass into \the [partner]'s face.",
- "shoves [u_His] ass into \the [partner]'s face.")]"
- else
- message = "[pick(
- "grabs the back of \the [partner]'s head and forces it into [u_His] asscheeks.",
- "squats down and plants [u_His] ass right on \the [partner]'s face")]"
- set_is_fucking(partner , GRINDING_FACE_WITH_ANUS, null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/squelch1.ogg',
- 'modular_sand/sound/interactions/squelch2.ogg',
- 'modular_sand/sound/interactions/squelch3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(LOW_LUST, null, src)
-
-/mob/living/proc/do_lickfeet(mob/living/partner)
- var/message
-
- if(partner.get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "licks \the [partner]'s [partner.get_shoes()]."
- else
- message = "licks \the [partner]'s [partner.has_feet() == 1 ? "foot" : "feet"]."
-
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(LOW_LUST, null, src)
-
-/*Grinding YOUR feet in TARGET's face*/
-/mob/living/proc/do_grindface(mob/living/partner)
- var/message
-
- var/u_His = p_their()
- var/t_His = partner.p_their()
-
- if(is_fucking(partner, GRINDING_FACE_WITH_FEET))
- if(get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "[pick(list("grinds [u_His] [get_shoes()] into [partner]'s face.",
- "presses [u_His] footwear down hard on [partner]'s face.",
- "rubs off the dirt from [u_His] [get_shoes()] onto [partner]'s face."))]"
- else
- message = "[pick(list("grinds [u_His] bare feet into [partner]'s face.",
- "deviously covers [partner]'s mouth and nose with [u_His] bare feet.",
- "runs the soles of [u_His] bare feet against [partner]'s lips."))]"
-
- else if(is_fucking(partner, GRINDING_MOUTH_WITH_FEET))
- if(get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "[pick(list("pulls [u_His] [get_shoes()] out of [partner]'s mouth and puts them on [t_His] face.",
- "slowly retracts [u_His] [get_shoes()] from [partner]'s mouth, putting them on [t_His] face instead."))]"
- else
- message = "[pick(list("pulls [u_His] bare feet out of [partner]'s mouth and rests them on [t_His] face instead.",
- "retracts [u_His] bare feet from [partner]'s mouth and grinds them into [t_His] face instead."))]"
-
- set_is_fucking(partner , GRINDING_FACE_WITH_FEET, null)
-
- else
- if(get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "[pick(list("plants [u_His] [get_shoes()] ontop of [partner]'s face.",
- "rests [u_His] [get_shoes()] on [partner]'s face and presses down hard.",
- "harshly places [u_His] [get_shoes()] atop [partner]'s face."))]"
- else
- message = "[pick(list("plants [u_His] bare feet ontop of [partner]'s face.",
- "rests [u_His] feet on [partner]'s face, smothering them.",
- "positions [u_His] bare feet atop [partner]'s face."))]"
-
- set_is_fucking(partner, GRINDING_FACE_WITH_FEET, null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry2.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_dry4.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(LOW_LUST, null, src)
-
-/*Grinding YOUR feet in TARGET's mouth*/
-/mob/living/proc/do_grindmouth(mob/living/partner)
- var/message
-
- var/u_His = p_their()
- var/t_His = partner.p_their()
- var/t_Him = partner.p_them()
- var/t_He = partner.p_they()
- var/t_S = partner.p_s()
-
- if(is_fucking(partner, GRINDING_MOUTH_WITH_FEET))
- if(get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "[pick(list("roughly shoves [u_His] [get_shoes()] deeper into [partner]'s mouth.",
- "harshly forces another inch of [u_His] [get_shoes()] into [partner]'s mouth.",
- "presses [u_His] weight down, [u_His] [get_shoes()] prying deeper into [partner]'s mouth."))]"
- else
- message = "[pick(list("wiggles [u_His] toes deep inside [partner]'s mouth.",
- "crams [u_His] barefeet down deeper into [partner]'s mouth, making [t_Him] gag.",
- "roughly grinds [u_His] feet on [partner]'s tongue."))]"
-
- else if(is_fucking(partner, GRINDING_FACE_WITH_FEET))
- if(get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "[pick(list("decides to force [u_His] [get_shoes()] deep into [partner]'s mouth.",
- "pressed the tip of [u_His] [get_shoes()] against [partner]'s lips and shoves inwards."))]"
- else
- message = "[pick(list("pries open [partner]'s mouth with [u_His] toes and shoves [u_His] bare foot in.",
- "presses down [u_His] foot even harder, cramming [u_His] foot into [partner]'s mouth."))]"
-
- set_is_fucking(partner , GRINDING_MOUTH_WITH_FEET, null)
-
- else
- if(get_item_by_slot(ITEM_SLOT_FEET) != null)
- message = "[pick(list("readies themselves and in one swift motion, shoves [u_His] [get_shoes()] into [partner]'s mouth.",
- "grinds the tip of [u_His] [get_shoes()] against [partner]'s mouth before pushing themselves in."))]"
- else
- message = "[pick(list("rubs [u_His] dirty bare feet across [partner]'s face before prying them into [t_His] muzzle.",
- "forces [u_His] barefeet into [partner]'s mouth.",
- "covers [partner]'s mouth and nose with [u_His] foot until [t_He] gasp[t_S] for breath, then shoves both feet inside before [t_He] can react."))]"
- set_is_fucking(partner , GRINDING_MOUTH_WITH_FEET, null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg',
- 'modular_sand/sound/interactions/foot_wet3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(LOW_LUST, null, src)
-
-/mob/living/proc/do_footfuck(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(src, CUM_TARGET_FEET))
- message = "[pick("fucks \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].",
- "rubs [u_His] dick on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].",
- "grinds [u_His] cock on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].")]"
- else
- message = "[pick("positions [u_His] cock on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].",
- "positions [u_His] cock on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot","sole")].",
- "starts grinding [u_His] cock against \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].")]"
- set_is_fucking(src, CUM_TARGET_FEET, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, src)
-
-/mob/living/proc/do_dfootfuck(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(src, CUM_TARGET_FEET))
- message = "[pick("fucks \the [partner]'s [partner.get_shoes() ? partner.get_shoes() : pick("feet", "soles")].",
- "rubs [u_His] dick between \the [partner]'s [partner.get_shoes() ? partner.get_shoes() : pick("feet", "soles")].",
- "thrusts [u_His] cock between \the [partner]'s [partner.get_shoes() ? partner.get_shoes() : pick("feet", "soles")].")]"
- else
- message = "[pick("positions [u_His] cock between \the [partner]'s [partner.get_shoes() ? partner.get_shoes() : pick("feet", "soles")].",
- "starts grinding [u_His] cock against \the [partner]'s [partner.get_shoes() ? partner.get_shoes() : pick("feet", "soles")].",
- "starts grinding [u_His] cock between \the [partner]'s [partner.get_shoes() ? partner.get_shoes() : pick("feet", "soles")].")]"
- set_is_fucking(src, CUM_TARGET_FEET, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, src)
-
-/mob/living/proc/do_vfootfuck(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(src, CUM_TARGET_FEET))
- message = "[pick("grinds [u_His] pussy against \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].",
- "rubs [u_His] clit on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].",
- "ruts on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].")]"
- else
- message = "[pick("positions [u_His] vagina on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].",
- "positions [u_His] clit on \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot","sole")].",
- "starts grinding [u_His] pussy against \the [partner]'s [partner.get_shoes() ? partner.get_shoes(TRUE) : pick("foot", "sole")].")]"
- set_is_fucking(src, CUM_TARGET_FEET, getorganslot(ORGAN_SLOT_VAGINA) ? getorganslot(ORGAN_SLOT_VAGINA) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, src)
-
-/mob/living/proc/do_footjob(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_FEET))
- message = "[pick("jerks \the [partner] off with [u_His] [get_shoes() ? get_shoes(TRUE) : pick("foot", "sole")].",
- "rubs [u_His] [get_shoes() ? get_shoes(TRUE) : pick("foot", "sole", "toes")] on \the [partner]'s shaft.",
- "works [u_His] [get_shoes() ? get_shoes(TRUE) : pick("foot", "sole")] up and down on \the [partner]'s cock.")]"
- else
- message = "[pick("[get_shoes() ? "positions [u_His] [get_shoes(TRUE)] on" :"positions [u_His] foot on"] \the [partner]'s cock.",
- "starts playing around with \the [partner]'s cock, using [u_His] [get_shoes() ? get_shoes(TRUE) :"foot"].")]"
- partner.set_is_fucking(src, CUM_TARGET_FEET, partner.getorganslot(ORGAN_SLOT_PENIS) ? partner.getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, src)
-
-/mob/living/proc/do_dfootjob(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_FEET))
- message = "[pick("jerks \the [partner] off with [u_His] [get_shoes() ? get_shoes() : pick("feet", "soles")].",
- "rubs [u_His] [get_shoes() ? get_shoes() : pick("feet", "soles")] on \the [partner]'s shaft.",
- "rubs [get_shoes() ? "[u_His] [get_shoes()]" : "all of [u_His] toes"] on \the [partner]'s cock.",
- "works [u_His] [get_shoes() ? get_shoes() : pick("feet", "soles")] up and down on \the [partner]'s cock.")]"
- else
- message = "[pick("[get_shoes() ? "wraps [u_His] [get_shoes()] around" : "wraps [u_His] [pick("feet", "soles")] around"] \the [partner]'s cock.",
- "starts playing around with \the [partner]'s cock, using [u_His] [get_shoes() ? get_shoes() : "feet"].")]"
- partner.set_is_fucking(src, CUM_TARGET_FEET, partner.getorganslot(ORGAN_SLOT_PENIS) ? partner.getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, src)
-
-/mob/living/proc/do_footjob_v(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(partner.is_fucking(src, CUM_TARGET_FEET))
- message = "[pick("rubs \the [partner] clit with [u_His] [get_shoes() ? get_shoes(TRUE) : pick("foot", "sole")].",
- "rubs [u_His] [get_shoes() ? get_shoes(TRUE) : pick("foot", "sole", "toes")] on \the [partner]'s coochie.",
- "rubs [u_His] [get_shoes() ? get_shoes(TRUE) : pick("foot", "sole", "toes")] on \the [partner]'s vagina.",
- "rubs [u_His] foot up and down on \the [partner]'s pussy.")]"
- else
- message = "[pick("[get_shoes() ? "positions [u_His] [get_shoes(TRUE)] on" : "positions [u_His] foot on"] \the [partner]'s pussy.",
- "starts playing around with \the [partner]'s pussy, using [u_His] [get_shoes() ? get_shoes(TRUE) : "foot"].")]"
- partner.set_is_fucking(src, CUM_TARGET_FEET, partner.getorganslot(ORGAN_SLOT_VAGINA) ? partner.getorganslot(ORGAN_SLOT_VAGINA) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/foot_dry1.ogg',
- 'modular_sand/sound/interactions/foot_dry3.ogg',
- 'modular_sand/sound/interactions/foot_wet1.ogg',
- 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, src)
-
-/mob/living/proc/get_shoes(var/singular = FALSE)
+/mob/living/proc/get_shoes(singular = FALSE)
var/obj/A = get_item_by_slot(ITEM_SLOT_FEET)
if(A)
var/txt = A.name
@@ -1650,7 +869,7 @@
moan()
return FALSE
-/mob/living/proc/get_unconsenting(var/extreme = FALSE, var/list/ignored_mobs)
+/mob/living/proc/get_unconsenting(extreme = FALSE, list/ignored_mobs)
var/list/nope = list()
nope += ignored_mobs
for(var/mob/M in range(7, src))
@@ -1663,64 +882,3 @@
else
nope += M
return nope
-
-//Yep, weird shit goes down here.
-/mob/living/proc/do_eyefuck(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(partner, CUM_TARGET_EYES))
- message = "[pick(
- "pounds into \the [partner]'s [has_eyes() ? "eye":"eyesocket"].",
- "shoves [u_His] dick deep into \the [partner]'s skull",
- "thrusts in and out of \the [partner]'s [has_eyes() ? "eye":"eyesocket"].",
- "goes balls deep into \the [partner]'s cranium over and over again.")]"
- var/client/cli = partner.client
- var/mob/living/carbon/C = partner
- if(cli && istype(C))
- if(cli.prefs.extremeharm != "No")
- if(prob(15))
- C.bleed(2)
- if(prob(25))
- C.adjustOrganLoss(ORGAN_SLOT_EYES,rand(3,7))
- C.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(3,7))
- else
- message = "forcefully slides [u_His] cock inbetween \the [partner]'s [has_eyes() ? "eyelid":"eyesocket"]."
- set_is_fucking(partner, CUM_TARGET_EYES, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/champ1.ogg',
- 'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting(TRUE))
- handle_post_sex(NORMAL_LUST, CUM_TARGET_EYES, partner)
- partner.handle_post_sex(LOW_LUST, null, src)
-
-/mob/living/proc/do_earfuck(mob/living/partner)
- var/message
-
- var/u_His = p_their()
-
- if(is_fucking(partner, CUM_TARGET_EARS))
- message = "[pick(
- "pounds into \the [partner]'s [has_eyes() ? "ear":"earsocker"].",
- "shoves [u_His] dick deep into \the [partner]'s skull",
- "thrusts in and out of \the [partner]'s [has_eyes() ? "ear":"eyesocket"].",
- "goes balls deep into \the [partner]'s cranium over and over again.")]"
- var/client/cli = partner.client
- var/mob/living/carbon/C = partner
- if(cli && istype(C))
- if(cli.prefs.extremeharm != "No")
- if(prob(15))
- C.bleed(2)
- if(prob(25))
- C.adjustOrganLoss(ORGAN_SLOT_EARS, rand(3,7))
- C.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(3,7))
- else
- message = "forcefully slides [u_His] cock inside \the [partner]'s [has_ears() ? "ear":"earsocket"]."
- set_is_fucking(partner, CUM_TARGET_EARS, getorganslot(ORGAN_SLOT_PENIS) ? getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/champ1.ogg',
- 'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting(TRUE))
- handle_post_sex(NORMAL_LUST, CUM_TARGET_EARS, partner)
- partner.handle_post_sex(LOW_LUST, null, src)
diff --git a/modular_sand/code/datums/interactions/lewd/_lewd_extra.dm b/modular_sand/code/datums/interactions/lewd/_lewd_extra.dm
deleted file mode 100644
index 9b4e85dca7..0000000000
--- a/modular_sand/code/datums/interactions/lewd/_lewd_extra.dm
+++ /dev/null
@@ -1,123 +0,0 @@
-/mob/living/proc/do_frot(mob/living/target)
- var/message
- var/t_His = p_their()
-
- message = "rubs [t_His] penis against [target]'s."
- set_is_fucking(target, CUM_TARGET_PENIS, getorganslot(ORGAN_SLOT_PENIS))
- visible_message("\The [src] [message]", ignored_mobs = get_unconsenting())
- handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, target)
- target.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, src)
-
-/mob/living/proc/do_breastfeed(mob/living/target)
- var/message
- var/u_His = p_their()
- var/u_He = p_they()
- var/t_His = target.p_their()
- var/obj/item/organ/genital/breasts/milkers = getorganslot(ORGAN_SLOT_BREASTS)
- var/milktype = milkers?.fluid_id
- var/modifier
- var/list/lines
-
- if(!milkers || !milktype)
- return
- var/datum/reagent/b_fluid = new milktype
-
- if(target == src)
- lines = list(
- "brings [u_His] own milktanks to [u_His] mouth and sucks deeply into them",
- "takes a big sip of [u_His] own fresh [b_fluid.name]",
- "fills [u_His] own mouth with a big gulp of [u_His] warm [b_fluid.name]"
- )
- else
- lines = list(
- "pushes [u_His] breasts against \the [target]'s mouth, squirting [u_His] warm [b_fluid.name] into [t_His] mouth",
- "fills \the [target]'s mouth with warm, sweet [b_fluid.name] as [u_He] squeezes [u_His] boobs, panting",
- "lets a large stream of [u_His] own abundant [b_fluid.name] coat the back of \the [target]'s throat"
- )
-
- message = "\The [src] [pick(lines)]"
- visible_message(message, ignored_mobs = get_unconsenting())
- playlewdinteractionsound(src, pick('modular_sand/sound/interactions/oral1.ogg',
- 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
-
- switch(milkers.size)
- if("c", "d", "e")
- modifier = 2
- if("f", "g", "h")
- modifier = 3
- else
- if(milkers.size in milkers.breast_values)
- modifier = clamp(milkers.breast_values[milkers.size] - 5, 0, INFINITY)
- else
- modifier = 1
- target.reagents.add_reagent(milktype, rand(1,3 * modifier))
-
-/mob/living/proc/do_jackoff(mob/living/user)
- var/message
- var/t_His = p_their()
- var/t_Him = p_them()
-
- if(user.is_fucking(src, CUM_TARGET_HAND))
- message = "[pick("jerks [t_Him]self off.",
- "works [t_His] shaft.",
- "strokes [t_His] penis.",
- "wanks [t_His] cock hard.")]"
- else
- message = "[pick("wraps [t_His] hand around [t_His] cock.",
- "starts to stroke [t_His] cock.",
- "starts playing with [t_His] cock.")]"
- user.set_is_fucking(src, CUM_TARGET_HAND, user.getorganslot(ORGAN_SLOT_PENIS) ? user.getorganslot(ORGAN_SLOT_PENIS) : null)
-
- playlewdinteractionsound(src, pick('modular_sand/sound/interactions/bang1.ogg',
- 'modular_sand/sound/interactions/bang2.ogg',
- 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, src)
-
-/mob/living/proc/do_fingerass_self(mob/living/user)
- var/t_His = p_their()
- var/t_Him = p_them()
-
- visible_message(message = "\The [src] [pick("fingers [t_Him]self.",
- "fingers [t_His] asshole.",
- "fingers [t_Him]self hard.")]", ignored_mobs = get_unconsenting())
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, src)
-
-/mob/living/proc/do_fingering_self(mob/living/user)
- var/t_His = p_their()
-
- visible_message(message = "\The [src] [pick("fingers [t_His] pussy deep.",
- "fingers [t_His] pussy.",
- "plays with [t_His] pussy.",
- "fingers [t_His] own pussy hard.")]", ignored_mobs = get_unconsenting())
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, src)
-
-/mob/living/proc/do_titgrope_self(mob/living/user)
- var/message
- var/t_His = p_their()
-
- if(user.a_intent == INTENT_HARM)
- message = "[pick("aggressively gropes [t_His] breast.",
- "grabs [t_His] breasts.",
- "tightly squeezes [t_His] breasts.",
- "slaps at [t_His] breasts.",
- "gropes [t_His] breasts roughly.")]"
- else
- message = "[pick("gently gropes [t_His] breast.",
- "softly squeezes [t_His] breasts.",
- "grips [t_His] breasts.",
- "runs a few fingers over [t_His] breast.",
- "delicately teases [t_His] nipple.",
- "traces a touch across [t_His] breast.")]"
- if(prob(5 + user.get_lust()))
- visible_message(message = "\The [src] [pick("shivers in arousal.",
- "moans quietly.",
- "breathes out a soft moan.",
- "gasps.",
- "shudders softly.",
- "trembles as [t_His] hands run across bare skin.")]")
- visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting())
- playlewdinteractionsound(loc, 'modular_sand/sound/interactions/squelch1.ogg', 50, 1, -1)
- user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, src)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/breasts.dm b/modular_sand/code/datums/interactions/lewd/interactions/breasts.dm
new file mode 100644
index 0000000000..267f4a3c6b
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/breasts.dm
@@ -0,0 +1,114 @@
+/datum/interaction/lewd/do_breastfeed
+ command = "do_breastfeed"
+ description = "Breastfeed them"
+ require_user_breasts = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ max_distance = 1
+ write_log_user = "breastfed"
+ write_log_target = "was breastfed by"
+ interaction_sound = null
+
+/datum/interaction/lewd/do_breastfeed/display_interaction(mob/living/user, mob/living/target)
+ var/message
+ var/u_His = user.p_their()
+ var/u_He = user.p_they()
+ var/t_His = target.p_their()
+ var/obj/item/organ/genital/breasts/milkers = user.getorganslot(ORGAN_SLOT_BREASTS)
+ var/milktype = milkers?.fluid_id
+ var/modifier
+ var/list/lines
+
+ if(!milkers || !milktype)
+ return
+
+ var/milktext = initial(milktype)
+
+ lines = list(
+ "pushes [u_His] breasts against \the [target]'s mouth, squirting [u_His] warm [lowertext(milktext)] into [t_His] mouth",
+ "fills \the [target]'s mouth with warm, sweet [lowertext(milktext)] as [u_He] squeezes [u_His] boobs, panting",
+ "lets a large stream of [u_His] own abundant [lowertext(milktext)] coat the back of \the [target]'s throat"
+ )
+
+ message = "\The [user] [pick(lines)]"
+ user.visible_message(message, ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
+ 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
+
+ switch(milkers.size)
+ if("c", "d", "e")
+ modifier = 2
+ if("f", "g", "h")
+ modifier = 3
+ else
+ if(milkers.size in milkers.breast_values)
+ modifier = clamp(milkers.breast_values[milkers.size] - 5, 0, INFINITY)
+ else
+ modifier = 1
+ target.reagents.add_reagent(milktype, rand(1,3 * modifier))
+
+/datum/interaction/lewd/titgrope
+ command = "titgrope"
+ description = "Grope their breasts."
+ require_user_hands = TRUE
+ require_target_breasts = REQUIRE_ANY
+ write_log_user = "groped"
+ write_log_target = "was groped by"
+ interaction_sound = null
+ max_distance = 1
+
+/datum/interaction/lewd/titgrope/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
+ if(user.a_intent == INTENT_HELP)
+ user.visible_message(
+ pick("\The [user] gently gropes \the [target]'s breast.",
+ "\The [user] softly squeezes \the [target]'s breasts.",
+ "\The [user] grips \the [target]'s breasts.",
+ "\The [user] runs a few fingers over \the [target]'s breast.",
+ "\The [user] delicately teases \the [target]'s nipple.",
+ "\The [user] traces a touch across \the [target]'s breast."))
+ if(user.a_intent == INTENT_HARM)
+ user.visible_message(
+ pick("\The [user] aggressively gropes \the [target]'s breast.",
+ "\The [user] grabs \the [target]'s breasts.",
+ "\The [user] tightly squeezes \the [target]'s breasts.",
+ "\The [user] slaps at \the [target]'s breasts.",
+ "\The [user] gropes \the [target]'s breasts roughly."))
+ if(prob(5 + target.get_lust()))
+ if(target.a_intent == INTENT_HELP)
+ user.visible_message(
+ pick("\The [target] shivers in arousal.",
+ "\The [target] moans quietly.",
+ "\The [target] breathes out a soft moan.",
+ "\The [target] gasps.",
+ "\The [target] shudders softly.",
+ "\The [target] trembles as hands run across bare skin."))
+ if(target.get_lust() < 5)
+ target.set_lust(5)
+ if(target.a_intent == INTENT_DISARM)
+ if (target.restrained())
+ user.visible_message(
+ pick("\The [target] twists playfully against the restraints.",
+ "\The [target] squirms away from [user]'s hand.",
+ "\The [target] slides back from [user]'s roaming hand.",
+ "\The [target] thrusts bare breasts forward into [user]'s hands."))
+ else
+ user.visible_message(
+ pick("\The [target] playfully bats at [user]'s hand.",
+ "\The [target] squirms away from [user]'s hand.",
+ "\The [target] guides [user]'s hand across bare breasts.",
+ "\The [target] teasingly laces a few fingers over [user]'s knuckles."))
+ if(target.get_lust() < 10)
+ target.add_lust(1)
+ if(target.a_intent == INTENT_GRAB)
+ user.visible_message(
+ pick("\The [target] grips [user]'s wrist tight.",
+ "\The [target] digs nails into [user]'s arm.",
+ "\The [target] grabs [user]'s wrist for a second."))
+ if(target.a_intent == INTENT_HARM)
+ user.adjustBruteLoss(1)
+ user.visible_message(
+ pick("\The [target] pushes [user] roughly away.",
+ "\The [target] digs nails angrily into [user]'s arm.",
+ "\The [target] fiercely struggles against [user].",
+ "\The [target] claws [user]'s forearm, drawing blood.",
+ "\The [target] slaps [user]'s hand away."))
+ return
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/cursed/earfuck.dm b/modular_sand/code/datums/interactions/lewd/interactions/cursed/earfuck.dm
new file mode 100644
index 0000000000..e44a89290c
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/cursed/earfuck.dm
@@ -0,0 +1,48 @@
+/datum/interaction/lewd/earfuck
+ command = "earfuck"
+ description = "Fuck their ear."
+ interaction_sound = null
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_ears = REQUIRE_EXPOSED
+ max_distance = 1
+ write_log_user = "earfucked"
+ write_log_target = "had their ear fucked by"
+ extreme = TRUE
+
+/datum/interaction/lewd/earfuck/earsocketfuck
+ command = "earsocketfuck"
+ description = "Fuck their earsocket."
+ require_target_ears = null
+ require_target_earsockets = REQUIRE_EXPOSED
+ write_log_user = "earsocket fucked"
+ write_log_target = "had their earsocket fucked by"
+
+/datum/interaction/lewd/earfuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(user.is_fucking(partner, CUM_TARGET_EARS))
+ message = "[pick(
+ "pounds into \the [partner]'s [partner.has_ears() ? "ear":"earsocker"].",
+ "shoves [u_His] dick deep into \the [partner]'s skull",
+ "thrusts in and out of \the [partner]'s [partner.has_ears() ? "ear":"eyesocket"].",
+ "goes balls deep into \the [partner]'s cranium over and over again.")]"
+ var/client/cli = partner.client
+ var/mob/living/carbon/C = partner
+ if(cli && istype(C))
+ if(cli.prefs.extremeharm != "No")
+ if(prob(15))
+ C.bleed(2)
+ if(prob(25))
+ C.adjustOrganLoss(ORGAN_SLOT_EARS, rand(3,7))
+ C.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(3,7))
+ else
+ message = "forcefully slides [u_His] cock inside \the [partner]'s [partner.has_ears() ? "ear":"earsocket"]."
+ user.set_is_fucking(partner, CUM_TARGET_EARS, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
+ 'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting(TRUE))
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_EARS, partner)
+ partner.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/cursed/eyefuck.dm b/modular_sand/code/datums/interactions/lewd/interactions/cursed/eyefuck.dm
new file mode 100644
index 0000000000..1407741cfe
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/cursed/eyefuck.dm
@@ -0,0 +1,48 @@
+/datum/interaction/lewd/eyefuck
+ command = "eyefuck"
+ description = "Fuck their eye."
+ interaction_sound = null
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_eyes = REQUIRE_EXPOSED
+ max_distance = 1
+ write_log_user = "eyefucked"
+ write_log_target = "had their eye fucked by"
+ extreme = TRUE
+
+/datum/interaction/lewd/eyefuck/eyesocketfuck
+ command = "eyesocketfuck"
+ description = "Fuck their eyesocket."
+ require_target_eyes = null
+ require_target_eyesockets = REQUIRE_EXPOSED
+ write_log_user = "eyesocketfucked"
+ write_log_target = "had their eyesocket fucked by"
+
+/datum/interaction/lewd/eyefuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(user.is_fucking(partner, CUM_TARGET_EYES))
+ message = "[pick(
+ "pounds into \the [partner]'s [partner.has_eyes() ? "eye":"eyesocket"].",
+ "shoves [u_His] dick deep into \the [partner]'s skull",
+ "thrusts in and out of \the [partner]'s [partner.has_eyes() ? "eye":"eyesocket"].",
+ "goes balls deep into \the [partner]'s cranium over and over again.")]"
+ var/client/cli = partner.client
+ var/mob/living/carbon/C = partner
+ if(cli && istype(C))
+ if(cli.prefs.extremeharm != "No")
+ if(prob(15))
+ C.bleed(2)
+ if(prob(25))
+ C.adjustOrganLoss(ORGAN_SLOT_EYES,rand(3,7))
+ C.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(3,7))
+ else
+ message = "forcefully slides [u_His] cock inbetween \the [partner]'s [partner.has_eyes() ? "eyelid":"eyesocket"]."
+ user.set_is_fucking(partner, CUM_TARGET_EYES, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
+ 'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting(TRUE))
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_EYES, partner)
+ partner.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/facefuck.dm b/modular_sand/code/datums/interactions/lewd/interactions/facefuck.dm
new file mode 100644
index 0000000000..d05756236c
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/facefuck.dm
@@ -0,0 +1,163 @@
+/datum/interaction/lewd/facefuck
+ command = "facefuck"
+ description = "Fuck their mouth using your penis"
+ interaction_sound = null
+ require_target_mouth = TRUE
+ require_user_penis = REQUIRE_EXPOSED
+ max_distance = 1
+ var/fucktarget = "penis"
+
+/datum/interaction/lewd/facefuck/vag
+ command = "facefuckvag"
+ description = "Fuck their mouth using your vagina"
+ require_user_penis = null
+ require_user_vagina = REQUIRE_EXPOSED
+ fucktarget = "vagina"
+
+/datum/interaction/lewd/facefuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+ var/obj/item/organ/genital/genital = null
+ var/retaliation_message = FALSE
+
+ var/u_His = user.p_their()
+ var/t_Him = partner.p_them()
+ var/t_Hes = partner.p_theyre()
+
+ if(user.is_fucking(partner, CUM_TARGET_MOUTH))
+ var/improv = FALSE
+ switch(fucktarget)
+ if("vagina")
+ if(user.has_vagina())
+ message = pick(
+ "grinds [u_His] pussy into \the [partner]'s face.",
+ "grips the back of \the [partner]'s head, forcing [t_Him] onto [u_His] pussy.",
+ "rolls [u_His] pussy against \the [partner]'s tongue.",
+ "slides \the [partner]'s mouth between [u_His] legs.",
+ "looks \the [partner]'s in the eyes as [u_His] pussy presses into a waiting tongue.",
+ "sways [u_His] hips, pushing [u_His] sex into \the [partner]'s face.",
+ )
+ if(partner.a_intent == INTENT_HARM)
+ // adjustBruteLoss(5)
+ retaliation_message = pick(
+ "looks deeply displeased to be there.",
+ "struggles to escape from between \the [user]'s thighs.",
+ )
+ else
+ improv = TRUE
+ if("penis")
+ if(user.has_penis())
+ message = pick(
+ "roughly fucks \the [partner]'s mouth.",
+ "forces [u_His] cock down \the [partner]'s throat.",
+ "pushes in against \the [partner]'s tongue until a tight gagging sound comes.",
+ "grips \the [partner]'s hair and draws [t_Him] to the base of the cock.",
+ "looks \the [partner]'s in the eyes as [u_His] cock presses into a waiting tongue.",
+ "rolls [u_His] hips hard, sinking into \the [partner]'s mouth.",
+ )
+ if(partner.a_intent == INTENT_HARM)
+ // adjustBruteLoss(5)
+ retaliation_message = pick(
+ "stares up from between \the [user]'s knees, trying to squirm away.",
+ "struggles to escape from between \the [user]'s legs.",
+ )
+ else
+ improv = TRUE
+ if(improv)
+ message = pick(
+ "grinds against \the [partner]'s face.",
+ "feels \the [partner]'s face between bare legs.",
+ "pushes in against \the [partner]'s tongue.",
+ "grips \the [partner]'s hair, drawing [t_Him] into the strangely sexless spot between [u_His] legs.",
+ "looks \the [partner]'s in the eyes as [t_Hes] caught beneath two thighs.",
+ "rolls [u_His] hips hard against \the [partner]'s face.",
+ )
+ if(partner.a_intent == INTENT_HARM)
+ // adjustBruteLoss(5)
+ retaliation_message = pick(
+ "stares up from between \the [user]'s knees, trying to squirm away.",
+ "struggles to escape from between \the [user]'s legs.",
+ )
+ else
+ var/improv = FALSE
+ switch(fucktarget)
+ if("vagina")
+ if(user.has_vagina())
+ message = "forces \the [partner]'s face into [u_His] pussy."
+ else
+ improv = TRUE
+ if("penis")
+ if(user.has_penis())
+ if(user.is_fucking(partner, CUM_TARGET_THROAT))
+ message = "retracts [u_His] cock from \the [partner]'s throat"
+ else
+ message = "shoves [u_His] cock into \the [partner]'s mouth"
+ else
+ improv = TRUE
+ if(improv)
+ message = "shoves [u_His] crotch into \the [partner]'s face."
+ else
+ switch(fucktarget)
+ if("vagina")
+ genital = partner.getorganslot(ORGAN_SLOT_VAGINA)
+ if("penis")
+ genital = partner.getorganslot(ORGAN_SLOT_PENIS)
+ user.set_is_fucking(partner, CUM_TARGET_MOUTH, genital)
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
+ 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ if(retaliation_message)
+ user.visible_message("\The [partner] [retaliation_message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_MOUTH, partner)
+
+/datum/interaction/lewd/throatfuck
+ command = "throatfuck"
+ description = "Fuck their throat. | Does oxy damage."
+ interaction_sound = null
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ max_distance = 1
+
+/datum/interaction/lewd/throatfuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+ var/obj/item/organ/genital/genital = null
+ var/retaliation_message = FALSE
+
+ var/u_His = user.p_their()
+ var/t_His = partner.p_their()
+ var/t_Him = partner.p_them()
+
+ if(user.is_fucking(partner, CUM_TARGET_THROAT))
+ message = "[pick(
+ "brutally shoves [u_His] cock into \the [partner]'s throat to make [t_Him] gag.",
+ "chokes \the [partner] on [u_His] dick, going in balls deep.",
+ "slams in and out of \the [partner]'s mouth, [u_His] balls slapping off [t_His] face.")]"
+ if(rand(3))
+ partner.emote("chokes on \the [user]")
+ if(prob(1) && istype(partner))
+ partner.adjustOxyLoss(5)
+ if(partner.a_intent == INTENT_HARM)
+ // adjustBruteLoss(5)
+ retaliation_message = pick(
+ "stares up from between \the [user]'s knees, trying to squirm away.",
+ "struggles to escape from between \the [user]'s legs.",
+ )
+ else if(user.is_fucking(partner, CUM_TARGET_MOUTH))
+ message = "thrusts deeper into \the [partner]'s mouth and down [t_His] throat."
+ var/check = user.getorganslot(ORGAN_SLOT_PENIS)
+ if(check)
+ genital = check
+ user.set_is_fucking(partner, CUM_TARGET_THROAT, genital)
+ else
+ message = "forces [u_His] dick deep down \the [partner]'s throat"
+ var/check = user.getorganslot(ORGAN_SLOT_PENIS)
+ if(check)
+ genital = check
+ user.set_is_fucking(partner, CUM_TARGET_THROAT, genital)
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
+ 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ if(retaliation_message)
+ user.visible_message(message = "\The [partner] [retaliation_message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_THROAT, partner)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/feet.dm b/modular_sand/code/datums/interactions/lewd/interactions/feet.dm
new file mode 100644
index 0000000000..2e24f6a157
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/feet.dm
@@ -0,0 +1,202 @@
+/datum/interaction/lewd/grindface
+ command = "grindface"
+ description = "Feet grind their face."
+ interaction_sound = null
+ require_target_mouth = TRUE
+ require_user_num_feet = 1
+ require_user_feet = REQUIRE_ANY
+ max_distance = 1
+
+/datum/interaction/lewd/grindface/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+ var/t_His = partner.p_their()
+
+ var/shoes = user.get_shoes()
+
+ if(user.is_fucking(partner, GRINDING_FACE_WITH_FEET))
+ if(shoes)
+ message = "[pick(list("grinds [u_His] [shoes] into [partner]'s face.",
+ "presses [u_His] footwear down hard on [partner]'s face.",
+ "rubs off the dirt from [u_His] [shoes] onto [partner]'s face."))]"
+ else
+ message = "[pick(list("grinds [u_His] bare feet into [partner]'s face.",
+ "deviously covers [partner]'s mouth and nose with [u_His] bare feet.",
+ "runs the soles of [u_His] bare feet against [partner]'s lips."))]"
+
+ else if(user.is_fucking(partner, GRINDING_MOUTH_WITH_FEET))
+ if(shoes)
+ message = "[pick(list("pulls [u_His] [shoes] out of [partner]'s mouth and puts them on [t_His] face.",
+ "slowly retracts [u_His] [shoes] from [partner]'s mouth, putting them on [t_His] face instead."))]"
+ else
+ message = "[pick(list("pulls [u_His] bare feet out of [partner]'s mouth and rests them on [t_His] face instead.",
+ "retracts [u_His] bare feet from [partner]'s mouth and grinds them into [t_His] face instead."))]"
+
+ user.set_is_fucking(partner, GRINDING_FACE_WITH_FEET, null)
+
+ else
+ if(shoes)
+ message = "[pick(list("plants [u_His] [shoes] ontop of [partner]'s face.",
+ "rests [u_His] [shoes] on [partner]'s face and presses down hard.",
+ "harshly places [u_His] [shoes] atop [partner]'s face."))]"
+ else
+ message = "[pick(list("plants [u_His] bare feet ontop of [partner]'s face.",
+ "rests [u_His] feet on [partner]'s face, smothering them.",
+ "positions [u_His] bare feet atop [partner]'s face."))]"
+
+ user.set_is_fucking(partner, GRINDING_FACE_WITH_FEET, null)
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry2.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_dry4.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(LOW_LUST, null, user)
+
+/datum/interaction/lewd/grindmouth
+ command = "grindmouth"
+ description = "Feet grind their mouth."
+ interaction_sound = null
+ require_target_mouth = TRUE
+ require_user_num_feet = 1
+ require_user_feet = REQUIRE_ANY
+ max_distance = 1
+
+/datum/interaction/lewd/grindmouth/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+ var/t_His = partner.p_their()
+ var/t_Him = partner.p_them()
+ var/t_He = partner.p_they()
+ var/t_S = partner.p_s()
+
+ var/shoes = user.get_shoes()
+
+ if(user.is_fucking(partner, GRINDING_MOUTH_WITH_FEET))
+ if(shoes)
+ message = "[pick(list("roughly shoves [u_His] [shoes] deeper into [partner]'s mouth.",
+ "harshly forces another inch of [u_His] [shoes] into [partner]'s mouth.",
+ "presses [u_His] weight down, [u_His] [shoes] prying deeper into [partner]'s mouth."))]"
+ else
+ message = "[pick(list("wiggles [u_His] toes deep inside [partner]'s mouth.",
+ "crams [u_His] barefeet down deeper into [partner]'s mouth, making [t_Him] gag.",
+ "roughly grinds [u_His] feet on [partner]'s tongue."))]"
+
+ else if(user.is_fucking(partner, GRINDING_FACE_WITH_FEET))
+ if(shoes)
+ message = "[pick(list("decides to force [u_His] [shoes] deep into [partner]'s mouth.",
+ "pressed the tip of [u_His] [shoes] against [partner]'s lips and shoves inwards."))]"
+ else
+ message = "[pick(list("pries open [partner]'s mouth with [u_His] toes and shoves [u_His] bare foot in.",
+ "presses down [u_His] foot even harder, cramming [u_His] foot into [partner]'s mouth."))]"
+
+ user.set_is_fucking(partner, GRINDING_MOUTH_WITH_FEET, null)
+
+ else
+ if(shoes)
+ message = "[pick(list("readies themselves and in one swift motion, shoves [u_His] [shoes] into [partner]'s mouth.",
+ "grinds the tip of [u_His] [shoes] against [partner]'s mouth before pushing themselves in."))]"
+ else
+ message = "[pick(list("rubs [u_His] dirty bare feet across [partner]'s face before prying them into [t_His] muzzle.",
+ "forces [u_His] barefeet into [partner]'s mouth.",
+ "covers [partner]'s mouth and nose with [u_His] foot until [t_He] gasp[t_S] for breath, then shoves both feet inside before [t_He] can react."))]"
+ user.set_is_fucking(partner, GRINDING_MOUTH_WITH_FEET, null)
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg',
+ 'modular_sand/sound/interactions/foot_wet3.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(LOW_LUST, null, user)
+
+/datum/interaction/lewd/footjob
+ command = "footjob"
+ description = "Jerk them off with your foot."
+ interaction_sound = null
+ require_user_num_feet = 1
+ require_user_feet = REQUIRE_ANY
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/footjob/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ var/shoes = user.get_shoes(TRUE)
+
+ if(partner.is_fucking(src, CUM_TARGET_FEET))
+ message = "[pick("jerks \the [partner] off with [u_His] [shoes ? shoes : pick("foot", "sole")].",
+ "rubs [u_His] [shoes ? shoes : pick("foot", "sole", "toes")] on \the [partner]'s shaft.",
+ "works [u_His] [shoes ? shoes : pick("foot", "sole")] up and down on \the [partner]'s cock.")]"
+ else
+ message = "[pick("[shoes ? "positions [u_His] [shoes] on" :"positions [u_His] foot on"] \the [partner]'s cock.",
+ "starts playing around with \the [partner]'s cock, using [u_His] [shoes ? shoes :"foot"].")]"
+ partner.set_is_fucking(user, CUM_TARGET_FEET, partner.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, user)
+
+/datum/interaction/lewd/footjob/double
+ command = "footjob_double"
+ description = "Jerk them off with both of your feet."
+ require_user_num_feet = 2
+
+/datum/interaction/lewd/footjob/double/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ var/shoes = user.get_shoes()
+
+ if(partner.is_fucking(user, CUM_TARGET_FEET))
+ message = "[pick("jerks \the [partner] off with [u_His] [shoes ? shoes : pick("feet", "soles")].",
+ "rubs [u_His] [shoes ? shoes : pick("feet", "soles")] on \the [partner]'s shaft.",
+ "rubs [shoes ? "[u_His] [shoes]" : "all of [u_His] toes"] on \the [partner]'s cock.",
+ "works [u_His] [shoes ? shoes : pick("feet", "soles")] up and down on \the [partner]'s cock.")]"
+ else
+ message = "[pick("[shoes ? "wraps [u_His] [shoes] around" : "wraps [u_His] [pick("feet", "soles")] around"] \the [partner]'s cock.",
+ "starts playing around with \the [partner]'s cock, using [u_His] [shoes ? shoes : "feet"].")]"
+ partner.set_is_fucking(user, CUM_TARGET_FEET, partner.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, user)
+
+/datum/interaction/lewd/footjob/vagina
+ command = "footjob_vaginal"
+ description = "Rub their vagina with your foot."
+ require_target_vagina = REQUIRE_EXPOSED
+ require_target_penis = null
+
+/datum/interaction/lewd/footjob/vagina/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ var/shoes = partner.get_shoes(TRUE)
+
+ if(partner.is_fucking(user, CUM_TARGET_FEET))
+ message = "[pick("rubs \the [partner] clit with [u_His] [shoes ? shoes : pick("foot", "sole")].",
+ "rubs [u_His] [shoes ? shoes : pick("foot", "sole", "toes")] on \the [partner]'s coochie.",
+ "rubs [u_His] [shoes ? shoes : pick("foot", "sole", "toes")] on \the [partner]'s vagina.",
+ "rubs [u_His] foot up and down on \the [partner]'s pussy.")]"
+ else
+ message = "[pick("[shoes ? "positions [u_His] [shoes] on" : "positions [u_His] foot on"] \the [partner]'s pussy.",
+ "starts playing around with \the [partner]'s pussy, using [u_His] [shoes ? shoes : "foot"].")]"
+ partner.set_is_fucking(user, CUM_TARGET_FEET, partner.getorganslot(ORGAN_SLOT_VAGINA))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/finger.dm b/modular_sand/code/datums/interactions/lewd/interactions/finger.dm
new file mode 100644
index 0000000000..1f483ab0fb
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/finger.dm
@@ -0,0 +1,29 @@
+/datum/interaction/lewd/finger
+ command = "finger"
+ description = "Finger their pussy."
+ require_user_hands = TRUE
+ require_target_vagina = REQUIRE_EXPOSED
+ interaction_sound = null
+ max_distance = 1
+
+/datum/interaction/lewd/finger/display_interaction(mob/living/user, mob/living/partner)
+ user.visible_message(message = "\The [user] [pick("fingers \the [partner].",
+ "fingers \the [partner]'s pussy.",
+ "fingers \the [partner] hard.")]", ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
+ partner.handle_post_sex(NORMAL_LUST, null, user)
+
+/datum/interaction/lewd/fingerass
+ command = "fingerm"
+ description = "Finger their ass."
+ interaction_sound = null
+ require_user_hands = TRUE
+ require_target_anus = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/fingerass/display_interaction(mob/living/user, mob/living/partner)
+ user.visible_message("\The [user] [pick("fingers \the [partner].",
+ "fingers \the [partner]'s asshole.",
+ "fingers \the [partner] hard.")]", ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
+ partner.handle_post_sex(NORMAL_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/frotting.dm b/modular_sand/code/datums/interactions/lewd/interactions/frotting.dm
new file mode 100644
index 0000000000..c1b189c59d
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/frotting.dm
@@ -0,0 +1,47 @@
+/datum/interaction/lewd/frotting
+ command = "frotting"
+ description = "Rub your penis against theirs"
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
+ write_log_user = "frotted"
+ write_log_target = "was frotted by"
+ interaction_sound = null
+
+/datum/interaction/lewd/frotting/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+ var/t_His = user.p_their()
+
+ message = "rubs [t_His] penis against [partner]'s."
+ user.set_is_fucking(partner, CUM_TARGET_PENIS, user.getorganslot(ORGAN_SLOT_PENIS))
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, partner)
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, user)
+
+/datum/interaction/lewd/tribadism
+ command = "tribadism"
+ description = "Grind your pussy against theirs."
+ interaction_sound = null
+ require_target_vagina = REQUIRE_EXPOSED
+ require_user_vagina = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/tribadism/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(partner.is_fucking(user, CUM_TARGET_VAGINA))
+ message = "[pick("grinds [u_His] pussy against \the [partner]'s cunt.",
+ "rubs [u_His] cunt against \the [partner]'s pussy.",
+ "thrusts against \the [partner]'s pussy.",
+ "humps \the [partner], [u_His] pussies grinding against each other.")]"
+ else
+ message = "presses [u_His] pussy into \the [partner]'s own."
+ partner.set_is_fucking(user, CUM_TARGET_VAGINA, partner.getorganslot(ORGAN_SLOT_VAGINA))
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/squelch1.ogg',
+ 'modular_sand/sound/interactions/squelch2.ogg',
+ 'modular_sand/sound/interactions/squelch3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, user)
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, partner)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/fuck.dm b/modular_sand/code/datums/interactions/lewd/interactions/fuck.dm
new file mode 100644
index 0000000000..4d8390ee58
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/fuck.dm
@@ -0,0 +1,187 @@
+/datum/interaction/lewd/fuck
+ command = "fuckvag"
+ description = "Fuck their pussy."
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_vagina = REQUIRE_EXPOSED
+ write_log_user = "fucked"
+ write_log_target = "was fucked by"
+ interaction_sound = null
+ max_distance = 1
+
+/datum/interaction/lewd/fuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(user.is_fucking(partner, CUM_TARGET_VAGINA))
+ message = "[pick(
+ "pounds \the [partner]'s pussy.",
+ "shoves [u_His] dick deep into \the [partner]'s pussy",
+ "thrusts in and out of \the [partner]'s cunt.",
+ "goes balls deep into \the [partner]'s pussy over and over again.")]"
+ else
+ message = "slides [u_His] cock into \the [partner]'s pussy."
+ user.set_is_fucking(partner, CUM_TARGET_VAGINA, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
+ 'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, partner)
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, user)
+
+/datum/interaction/lewd/fuck/anal
+ command = "fuckass"
+ description = "Fuck their ass."
+ require_target_vagina = null
+ require_target_anus = REQUIRE_EXPOSED
+
+/datum/interaction/lewd/fuck/anal/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+ var/t_His = partner.p_their()
+
+ if(user.is_fucking(partner, CUM_TARGET_ANUS))
+ message = "[pick(
+ "thrusts in and out of \the [partner]'s ass.",
+ "pounds \the [partner]'s ass.",
+ "slams [u_His] hips up against \the [partner]'s ass hard.",
+ "goes balls deep into \the [partner]'s ass over and over again.")]"
+ else
+ message = "[pick(
+ "works [u_His] cock into \the [partner]'s asshole.",
+ "grabs the base of [u_His] twitching cock and presses the tip into \the [partner]'s asshole.",
+ "shoves [u_His] dick deep inside of \the [partner]'s ass, making [t_His] rear jiggle.")]"
+ user.set_is_fucking(partner, CUM_TARGET_ANUS, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
+ 'modular_sand/sound/interactions/bang2.ogg',
+ 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_ANUS, partner)
+ partner.handle_post_sex(NORMAL_LUST, null, user)
+
+/datum/interaction/lewd/breastfuck
+ command = "breastfuck"
+ description = "Fuck their breasts."
+ interaction_sound = null
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_breasts = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/breastfuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(user.is_fucking(partner, CUM_TARGET_BREASTS))
+ message = "[pick("fucks \the [partner]'s' breasts.",
+ "grinds [u_His] cock between \the [partner]'s boobs.",
+ "thrusts into \the [partner]'s tits.",
+ "grabs \the [partner]'s breasts together and presses [u_His] dick between them.")]"
+ else
+ message = "pushes \the [partner]'s breasts together and presses [u_His] dick between them."
+ user.set_is_fucking(partner, CUM_TARGET_BREASTS, user.getorganslot(ORGAN_SLOT_PENIS))
+
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
+ 'modular_sand/sound/interactions/bang2.ogg',
+ 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_BREASTS, partner)
+
+/datum/interaction/lewd/footfuck
+ command = "footfuck"
+ description = "Rub your cock on their foot."
+ interaction_sound = null
+ require_target_num_feet = 1
+ require_target_feet = REQUIRE_ANY
+ require_user_penis = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/footfuck/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ var/shoes = partner.get_shoes(TRUE)
+
+ if(user.is_fucking(partner, CUM_TARGET_FEET))
+ message = "[pick("fucks \the [partner]'s [shoes ? shoes : pick("foot", "sole")].",
+ "rubs [u_His] dick on \the [partner]'s [shoes ? shoes : pick("foot", "sole")].",
+ "grinds [u_His] cock on \the [partner]'s [shoes ? shoes : pick("foot", "sole")].")]"
+ else
+ message = "[pick("positions [u_His] cock on \the [partner]'s [shoes ? shoes : pick("foot", "sole")].",
+ "positions [u_His] cock on \the [partner]'s [shoes ? shoes : pick("foot","sole")].",
+ "starts grinding [u_His] cock against \the [partner]'s [shoes ? shoes : pick("foot", "sole")].")]"
+ user.set_is_fucking(partner, CUM_TARGET_FEET, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, partner)
+
+/datum/interaction/lewd/footfuck/double
+ command = "footfuckdouble"
+ description = "Rub your cock between their feet."
+ require_target_num_feet = 2
+
+/datum/interaction/lewd/footfuck/double/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ var/shoes = partner.get_shoes()
+
+ if(user.is_fucking(partner, CUM_TARGET_FEET))
+ message = "[pick("fucks \the [partner]'s [shoes ? shoes : pick("feet", "soles")].",
+ "rubs [u_His] dick between \the [partner]'s [shoes ? shoes : pick("feet", "soles")].",
+ "thrusts [u_His] cock between \the [partner]'s [shoes ? shoes : pick("feet", "soles")].")]"
+ else
+ message = "[pick("positions [u_His] cock between \the [partner]'s [shoes ? shoes : pick("feet", "soles")].",
+ "starts grinding [u_His] cock against \the [partner]'s [shoes ? shoes : pick("feet", "soles")].",
+ "starts grinding [u_His] cock between \the [partner]'s [shoes ? shoes : pick("feet", "soles")].")]"
+ user.set_is_fucking(partner, CUM_TARGET_FEET, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, partner)
+
+/datum/interaction/lewd/footfuck/vag
+ command = "footfuckvag"
+ description = "Rub your vagina on their foot."
+ interaction_sound = null
+ require_target_num_feet = 1
+ require_target_feet = REQUIRE_ANY
+ require_user_vagina = REQUIRE_EXPOSED
+ require_user_penis = REQUIRE_NONE
+ max_distance = 1
+
+/datum/interaction/lewd/footfuck/vag/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ var/shoes = partner.get_shoes(TRUE)
+
+ if(user.is_fucking(partner, CUM_TARGET_FEET))
+ message = "[pick("grinds [u_His] pussy against \the [partner]'s [shoes ? shoes : pick("foot", "sole")].",
+ "rubs [u_His] clit on \the [partner]'s [shoes ? shoes : pick("foot", "sole")].",
+ "ruts on \the [partner]'s [shoes ? shoes : pick("foot", "sole")].")]"
+ else
+ message = "[pick("positions [u_His] vagina on \the [partner]'s [shoes ? shoes : pick("foot", "sole")].",
+ "positions [u_His] clit on \the [partner]'s [shoes ? shoes : pick("foot","sole")].",
+ "starts grinding [u_His] pussy against \the [partner]'s [shoes ? shoes : pick("foot", "sole")].")]"
+ user.set_is_fucking(partner, CUM_TARGET_FEET, user.getorganslot(ORGAN_SLOT_VAGINA))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_dry1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, partner)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/handjob.dm b/modular_sand/code/datums/interactions/lewd/interactions/handjob.dm
new file mode 100644
index 0000000000..4343e84de6
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/handjob.dm
@@ -0,0 +1,27 @@
+/datum/interaction/lewd/handjob
+ command = "handjob"
+ description = "Jerk them off."
+ interaction_sound = null
+ require_user_hands = TRUE
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/handjob/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(partner.is_fucking(user, CUM_TARGET_HAND))
+ message = "[pick("jerks \the [partner] off.",
+ "works \the [partner]'s shaft.",
+ "wanks \the [partner]'s cock hard.")]"
+ else
+ message = "[pick("wraps [u_His] hand around \the [partner]'s cock.",
+ "starts playing with \the [partner]'s cock")]"
+ partner.set_is_fucking(user, CUM_TARGET_HAND, partner.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
+ 'modular_sand/sound/interactions/bang2.ogg',
+ 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/kiss.dm b/modular_sand/code/datums/interactions/lewd/interactions/kiss.dm
new file mode 100644
index 0000000000..e4854be0cf
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/kiss.dm
@@ -0,0 +1,22 @@
+/datum/interaction/lewd/kiss
+ command = "deepkiss"
+ description = "Kiss them deeply."
+ require_user_mouth = TRUE
+ require_target_mouth = TRUE
+ write_log_user = "kissed"
+ write_log_target = "was kissed by"
+ interaction_sound = null
+ max_distance = 1
+
+/datum/interaction/lewd/kiss/post_interaction(mob/living/user, mob/living/partner)
+ . = ..()
+ if(user.get_lust() < 5)
+ user.set_lust(5)
+ if(partner.get_lust() < 5)
+ partner.set_lust(5)
+
+/datum/interaction/lewd/kiss/display_interaction(mob/living/user, mob/living/partner)
+ if(user.get_lust() >= 3)
+ user.visible_message("\The [user] gives an intense, lingering kiss to \the [partner].")
+ else
+ user.visible_message("\The [user] kisses \the [partner] deeply.")
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/lick.dm b/modular_sand/code/datums/interactions/lewd/interactions/lick.dm
new file mode 100644
index 0000000000..dc60eb9ede
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/lick.dm
@@ -0,0 +1,35 @@
+/datum/interaction/lewd/rimjob
+ command = "rimjob"
+ description = "Lick their ass."
+ interaction_sound = null
+ require_user_mouth = TRUE
+ require_target_anus = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/rimjob/display_interaction(mob/living/user, mob/living/partner)
+ user.visible_message("\The [user] licks \the [partner]'s asshole.", ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
+ partner.handle_post_sex(NORMAL_LUST, null, user)
+
+/datum/interaction/lewd/lickfeet
+ command = "lickfeet"
+ description = "Lick their feet."
+ interaction_sound = null
+ require_user_mouth = TRUE
+ require_target_feet = REQUIRE_ANY
+ require_target_num_feet = 1
+ max_distance = 1
+
+/datum/interaction/lewd/lickfeet/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/shoes = partner.get_shoes()
+
+ if(shoes)
+ message = "licks \the [partner]'s [shoes]."
+ else
+ message = "licks \the [partner]'s [partner.has_feet() == 1 ? "foot" : "feet"]."
+
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/mount.dm b/modular_sand/code/datums/interactions/lewd/interactions/mount.dm
new file mode 100644
index 0000000000..b199c1285a
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/mount.dm
@@ -0,0 +1,166 @@
+/datum/interaction/lewd/mount
+ command = "mount"
+ description = "Mount with your pussy."
+ interaction_sound = null
+ require_user_vagina = REQUIRE_EXPOSED
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/mount/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(partner.is_fucking(user, CUM_TARGET_VAGINA))
+ message = "[pick("rides \the [partner]'s dick.",
+ "forces [partner]'s cock on [u_His] pussy")]"
+ else
+ message = "slides [u_His] pussy onto \the [partner]'s cock."
+ partner.set_is_fucking(user, CUM_TARGET_VAGINA, partner.getorganslot(ORGAN_SLOT_PENIS))
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
+ 'modular_sand/sound/interactions/bang2.ogg',
+ 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, user)
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, partner)
+
+/datum/interaction/lewd/mountass
+ command = "mountm"
+ description = "Mount with your ass."
+ interaction_sound = null
+ require_user_anus = REQUIRE_EXPOSED
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/mountass/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(partner.is_fucking(user, CUM_TARGET_ANUS))
+ message = "[pick("rides \the [partner]'s dick.",
+ "forces [partner]'s cock on [u_His] ass")]"
+ else
+ message = "lowers [u_His] ass onto \the [partner]'s cock."
+ partner.set_is_fucking(user, CUM_TARGET_ANUS, partner.getorganslot(ORGAN_SLOT_PENIS))
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
+ 'modular_sand/sound/interactions/bang2.ogg',
+ 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_ANUS, user)
+ user.handle_post_sex(NORMAL_LUST, null, partner)
+
+/datum/interaction/lewd/mountface
+ command = "mountface"
+ description = "Ass to face."
+ interaction_sound = null
+ require_target_mouth = TRUE
+ require_user_anus = REQUIRE_EXPOSED
+ max_distance = 1
+
+/datum/interaction/lewd/mountface/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+
+ if(user.is_fucking(partner, GRINDING_FACE_WITH_ANUS))
+ message = "[pick("grinds [u_His] ass into \the [partner]'s face.",
+ "shoves [u_His] ass into \the [partner]'s face.")]"
+ else
+ message = "[pick(
+ "grabs the back of \the [partner]'s head and forces it into [u_His] asscheeks.",
+ "squats down and plants [u_His] ass right on \the [partner]'s face")]"
+ user.set_is_fucking(partner, GRINDING_FACE_WITH_ANUS, null)
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/squelch1.ogg',
+ 'modular_sand/sound/interactions/squelch2.ogg',
+ 'modular_sand/sound/interactions/squelch3.ogg'), 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(LOW_LUST, null, partner)
+
+/datum/interaction/lewd/thighs
+ command = "thigh_smother"
+ description = "Smother them using your penis."
+ max_distance = 1
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ interaction_sound = null
+ write_log_user = "thigh-trapped (penis)"
+ write_log_target = "was smothered (penis) by"
+ var/fucktarget = "penis"
+
+/datum/interaction/lewd/thighs/vagina
+ command = "thigh_smother_vag"
+ description = "Smother them using your vagina."
+ require_user_penis = REQUIRE_NONE
+ require_user_vagina = REQUIRE_EXPOSED
+ write_log_user = "thigh-trapped (vagina)"
+ write_log_target = "was smothered (vagina) by"
+ fucktarget = "vagina"
+
+/datum/interaction/lewd/thighs/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+ var/obj/item/organ/genital/genital = null
+ var/lust_increase = 1
+
+ var/u_His = user.p_their()
+ var/t_His = partner.p_their()
+ var/t_Him = partner.p_them()
+ var/t_Hes = partner.p_theyre()
+
+ if(user.is_fucking(partner, THIGH_SMOTHERING))
+ var/improv = FALSE
+ switch(fucktarget)
+ if("vagina")
+ if(user.has_vagina())
+ message = pick(list(
+ "presses [u_His] weight down onto \the [partner]'s face, blocking [t_His] vision completely.",
+ "rides \the [partner]'s face, grinding [u_His] wet pussy all over it."))
+ else
+ improv = TRUE
+ if("penis")
+ if(user.has_penis())
+ message = pick(list("presses [u_His] weight down onto \the [partner]'s face, blocking [t_His] vision completely.",
+ "forces [u_His] dick and nutsack into \the [partner]'s face as [t_Hes] stuck locked in between [u_His] thighs.",
+ "slips [u_His] cock into \the [partner]'s helpless mouth, keeping [u_His] shaft pressed hard into [t_His] face."))
+ else
+ improv = TRUE
+ if(improv)
+ message = "rubs [u_His] groin up and down \the [partner]'s face."
+ else
+ var/improv = FALSE
+ switch(fucktarget)
+ if("vagina")
+ if(user.has_vagina())
+ message = pick(list(
+ "clambers over \the [partner]'s face and pins [t_Him] down with [u_His] thighs, [u_His] moist slit rubbing all over \the [partner]'s mouth and nose.",
+ "locks [u_His] legs around \the [partner]'s head before pulling it into [u_His] mound."))
+ else
+ improv = TRUE
+ if("penis")
+ if(user.has_penis())
+ message = pick(list(
+ "clambers over \the [partner]'s face and pins [t_Him] down with [u_His] thighs, then slowly inching closer and covering [t_His] eyes and nose with [u_His] leaking erection.",
+ "locks [u_His] legs around \the [partner]'s head before pulling it into [u_His] fat package, smothering [t_Him]."))
+ else
+ improv = TRUE
+ if(improv)
+ message = "deviously locks [u_His] legs around \the [partner]'s head and smothers it in [u_His] thighs."
+ else
+ switch(fucktarget)
+ if("vagina")
+ genital = partner.getorganslot(ORGAN_SLOT_VAGINA)
+ if("penis")
+ genital = partner.getorganslot(ORGAN_SLOT_PENIS)
+ user.set_is_fucking(partner, THIGH_SMOTHERING, genital)
+
+ var/file = pick('modular_sand/sound/interactions/bj10.ogg',
+ 'modular_sand/sound/interactions/bj3.ogg',
+ 'modular_sand/sound/interactions/foot_wet1.ogg',
+ 'modular_sand/sound/interactions/foot_dry3.ogg')
+ playlewdinteractionsound(get_turf(user), file, 70, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(lust_increase, THIGH_SMOTHERING, partner)
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
+ 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_MOUTH, partner)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/nipsuck.dm b/modular_sand/code/datums/interactions/lewd/interactions/nipsuck.dm
new file mode 100644
index 0000000000..850464c195
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/nipsuck.dm
@@ -0,0 +1,142 @@
+/datum/interaction/lewd/nipsuck
+ command = "nipsuck"
+ description = "Suck their nipples."
+ require_target_topless = TRUE
+ require_user_mouth = TRUE
+ write_log_user = "sucked nipples"
+ write_log_target = "had their nipples sucked by"
+ interaction_sound = null
+ max_distance = 1
+
+/datum/interaction/lewd/nipsuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
+ if((user.a_intent == INTENT_HELP) || (user.a_intent == INTENT_DISARM))
+ user.visible_message(
+ pick("\The [user] gently sucks on \the [target]'s [pick("nipple", "nipples")].",
+ "\The [user] gently nibs \the [target]'s [pick("nipple", "nipples")].",
+ "\The [user] licks \the [target]'s [pick("nipple", "nipples")]."))
+ if(target.has_breasts(REQUIRE_EXPOSED))
+ var/modifier = 1
+ var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
+ switch(B.size)
+ if("c", "d", "e")
+ modifier = 2
+ if("f", "g", "h")
+ modifier = 3
+ else
+ if(B.size in B.breast_values)
+ modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
+ else
+ modifier = 1
+ if(B.fluid_id)
+ user.reagents.add_reagent(B.fluid_id, rand(1,2 * modifier))
+
+ if(user.a_intent == INTENT_HARM)
+ user.visible_message(
+ pick("\The [user] bites \the [target]'s [pick("nipple", "nipples")].",
+ "\The [user] aggressively sucks \the [target]'s [pick("nipple", "nipples")]."))
+ if(target.has_breasts(REQUIRE_EXPOSED))
+ var/modifier = 1
+ var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
+ switch(B.size)
+ if("c", "d", "e")
+ modifier = 2
+ if("f", "g", "h")
+ modifier = 3
+ else
+ if(B.size in B.breast_values)
+ modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
+ else
+ modifier = 1
+ if(B.fluid_id)
+ user.reagents.add_reagent(B.fluid_id, rand(1,3 * modifier)) //aggressive sucking leads to high rewards
+
+ if(user.a_intent == INTENT_GRAB)
+ user.visible_message(
+ pick("\The [user] sucks \the [target]'s [pick("nipple", "nipples")] intently.",
+ "\The [user] feasts \the [target]'s [pick("nipple", "nipples")].",
+ "\The [user] glomps \the [target]'s [pick("nipple", "nipples")]."))
+ if(target.has_breasts(REQUIRE_EXPOSED))
+ var/modifier = 1
+ var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
+ switch(B.size)
+ if("c", "d", "e")
+ modifier = 2
+ if("f", "g", "h")
+ modifier = 3
+ else
+ if(B.size in B.breast_values)
+ modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
+ else
+ modifier = 1
+ if(B.fluid_id)
+ user.reagents.add_reagent(B.fluid_id, rand(1,3 * modifier)) //aggressive sucking leads to high rewards
+
+ if(prob(5 + target.get_lust()))
+ if(target.a_intent == INTENT_HELP)
+ if(!target.has_breasts())
+ user.visible_message(
+ pick("\The [target] shivers in arousal.",
+ "\The [target] moans quietly.",
+ "\The [target] breathes out a soft moan.",
+ "\The [target] gasps.",
+ "\The [target] shudders softly.",
+ "\The [target] trembles as their chest gets molested."))
+ else
+ user.visible_message(
+ pick("\The [target] shivers in arousal.",
+ "\The [target] moans quietly.",
+ "\The [target] breathes out a soft moan.",
+ "\The [target] gasps.",
+ "\The [target] shudders softly.",
+ "\The [target] trembles as their breasts get molested.",
+ "\The [target] quivers in arousal as \the [user] delights themselves on their milk."))
+ if(target.get_lust() < 5)
+ target.set_lust(5)
+ if(target.a_intent == INTENT_DISARM)
+ if (target.restrained())
+ if(!target.has_breasts())
+ user.visible_message(
+ pick("\The [target] twists playfully against the restraints.",
+ "\The [target] squirms away from \the [user]'s mouth.",
+ "\The [target] slides back from \the [user]'s mouth.",
+ "\The [target] thrusts their bare chest forward into \the [user]'s mouth."))
+ else
+ user.visible_message(
+ pick("\The [target] twists playfully against the restraints.",
+ "\The [target] squirms away from \the [user]'s mouth.",
+ "\The [target] slides back from \the [user]'s mouth.",
+ "\The [target] thrust their bare breasts forward into \the [user]'s mouth."))
+ else
+ if(!target.has_breasts())
+ user.visible_message(
+ pick("\The [target] playfully shoos away \the [user]'s head.",
+ "\The [target] squirms away from \the [user]'s mouth.",
+ "\The [target] holds \the [user]'s head against their chest.",
+ "\The [target] teasingly caresses \the [user]'s neck."))
+ else
+ user.visible_message(
+ pick("\The [target] playfully shoos away \the [user]'s head.",
+ "\The [target] squirms away from \the [user]'s mouth.",
+ "\The [target] holds \the [user]'s head against their breast.",
+ "\The [target] teasingly caresses \the [user]'s neck.",
+ "\The [target] rubs their breasts against \the [user]'s head."))
+ if(target.get_lust() < 10)
+ target.add_lust(1)
+ if(target.a_intent == INTENT_GRAB)
+ user.visible_message(
+ pick("\The [target] grips \the [user]'s head tight.",
+ "\The [target] digs nails into \the [user]'s scalp.",
+ "\The [target] grabs and shoves \the [user]'s head away."))
+ if(target.a_intent == INTENT_HARM)
+ user.adjustBruteLoss(1)
+ user.visible_message(
+ pick("\The [target] slaps \the [user] away.",
+ "\The [target] scratches [user]'s face.",
+ "\The [target] fiercely struggles against [user].",
+ "\The [target] claws [user]'s face, drawing blood.",
+ "\The [target] elbows [user]'s mouth away."))
+ target.dir = get_dir(target, user)
+ user.dir = get_dir(user, target)
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
+ 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
+ return
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/nuts.dm b/modular_sand/code/datums/interactions/lewd/interactions/nuts.dm
new file mode 100644
index 0000000000..05e1e0ecda
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/nuts.dm
@@ -0,0 +1,45 @@
+/datum/interaction/lewd/nuts
+ command = "nut_face"
+ description = "Nuts to face."
+ interaction_sound = null
+ require_user_balls = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ max_distance = 1
+ write_log_user = "make-them-suck-their-nuts"
+ write_log_target = "was made to suck nuts by"
+
+/datum/interaction/lewd/nuts/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+
+ var/u_His = user.p_their()
+ var/t_His = partner.p_their()
+
+ var/lust_increase = 1
+
+ if(user.is_fucking(partner, NUTS_TO_FACE))
+ message = pick(list(
+ "grabs the back of [partner]'s head and pulls it into [u_His] crotch.",
+ "jams [u_His] nutsack right into [partner]'s face.",
+ "roughly grinds [u_His] fat nutsack into [partner]'s mouth.",
+ "pulls out [u_His] saliva-covered nuts from [partner]'s violated mouth and then wipes off the slime onto [t_His] face."))
+ else
+ message = pick(list("wedges a digit into the side of [partner]'s jaw and pries it open before using [u_His] other hand to shove [u_His] whole nutsack inside!", "stands with [u_His] groin inches away from [partner]'s face, then thrusting [u_His] hips forward and smothering [partner]'s whole face with [u_His] heavy ballsack."))
+ user.set_is_fucking(partner, NUTS_TO_FACE, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ /*playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/nuts1.ogg',
+ 'modular_sand/sound/interactions/nuts2.ogg',
+ 'modular_sand/sound/interactions/nuts3.ogg',
+ 'modular_sand/sound/interactions/nuts4.ogg'), 70, 1, -1)*/ //These files don't even exist but nobody noticed because double-quotes were used instead of single.
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(lust_increase, CUM_TARGET_MOUTH, partner)
+
+/datum/interaction/lewd/nut_smack
+ command = "smack_nuts"
+ description = "Smack their nuts."
+ interaction_sound = 'modular_sand/sound/interactions/slap.ogg'
+ simple_message = "USER slaps TARGET's nuts!"
+ require_target_balls = REQUIRE_EXPOSED
+ needs_physical_contact = TRUE
+ max_distance = 1
+ write_log_user = "slapped-nuts"
+ write_log_target = "had their nuts slapped by"
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/oral.dm b/modular_sand/code/datums/interactions/lewd/interactions/oral.dm
new file mode 100644
index 0000000000..0fc6aa8442
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/oral.dm
@@ -0,0 +1,127 @@
+/datum/interaction/lewd/oral
+ command = "suckvag"
+ description = "Go down on them."
+ require_user_mouth = TRUE
+ require_target_vagina = REQUIRE_EXPOSED
+ write_log_user = "gave head to"
+ write_log_target = "was given head by"
+ interaction_sound = null
+ max_distance = 1
+ var/fucktarget = "vagina"
+
+/datum/interaction/lewd/oral/blowjob
+ command = "suckcock"
+ description = "Suck them off."
+ require_target_vagina = null
+ require_target_penis = REQUIRE_EXPOSED
+ fucktarget = "penis"
+
+/datum/interaction/lewd/oral/display_interaction(mob/living/user, mob/living/partner)
+ var/message
+ var/obj/item/organ/genital/genital = null
+ var/lust_increase = NORMAL_LUST
+ var/u_His = user.p_their()
+ var/u_He = user.p_they()
+ var/u_Were = user.p_theyre()
+
+ if(partner.is_fucking(user, CUM_TARGET_MOUTH))
+ if(prob(partner.get_sexual_potency()))
+ user.adjustOxyLoss(3)
+ message = "goes in deep on \the [partner]."
+ lust_increase += 5
+ else
+ var/improv = FALSE
+ switch(fucktarget)
+ if("vagina")
+ if(partner.has_vagina())
+ message = pick(
+ "licks \the [partner]'s pussy.",
+ "runs [u_His] tongue up the shape of \the [partner]'s pussy.",
+ "traces \the [partner]'s slit with [u_His] tongue.",
+ "darts the tip of [u_His] tongue around \the [partner]'s clit.",
+ "laps slowly at \the [partner].",
+ "kisses \the [partner]'s delicate folds.",
+ "tastes \the [partner].",
+ )
+ else
+ improv = TRUE
+ if("penis")
+ if(partner.has_penis())
+ message = pick(
+ "sucks \the [partner]'s off.",
+ "runs [u_His] tongue up the shape of \the [partner]'s cock.",
+ "traces \the [partner]'s cock with [u_His] tongue.",
+ "darts the tip of [u_His] tongue around tip of \the [partner]'s cock.",
+ "laps slowly at \the [partner]'s shaft.",
+ "kisses the base of \the [partner]'s shaft.",
+ "takes \the [partner] deeper into [u_His] mouth.",
+ )
+ else
+ improv = TRUE
+ if(improv)
+ // get confused about how to do the sex
+ message = pick(
+ "licks \the [partner].",
+ "looks a little unsure of where to lick \the [partner].",
+ "runs [u_His] tongue between \the [partner]'s legs.",
+ "kisses \the [partner]'s thigh.",
+ "tries [u_His] best with \the [partner].",
+ )
+ else
+ var/improv = FALSE
+ switch(fucktarget)
+ if("vagina")
+ if(partner.has_vagina())
+ message = pick(
+ "buries [u_His] face in \the [partner]'s pussy.",
+ "nuzzles \the [partner]'s wet sex.",
+ "finds [u_His] face caught between \the [partner]'s thighs.",
+ "kneels down between \the [partner]'s legs.",
+ "grips \the [partner]'s legs, pushing them apart.",
+ "sinks [u_His] face in between \the [partner]'s thighs.",
+ )
+ else
+ improv = TRUE
+ if("penis")
+ if(partner.has_penis())
+ message = pick(
+ "takes \the [partner]'s cock into [u_His] mouth.",
+ "wraps [u_His] lips around \the [partner]'s cock.",
+ "finds [u_His] face between \the [partner]'s thighs.",
+ "kneels down between \the [partner]'s legs.",
+ "grips \the [partner]'s legs, kissing at the tip of [u_His] cock.",
+ "goes down on \the [partner].",
+ )
+ else
+ improv = TRUE
+ if(improv)
+ message = pick(
+ "begins to lick \the [partner].",
+ "starts kissing \the [partner]'s thigh.",
+ "sinks down between \the [partner]'s thighs.",
+ "briefly flashes a puzzled look from between \the [partner]'s legs.",
+ "looks unsure of how to handle \the [partner]'s lack of genitalia.",
+ "seems like [u_He] [u_Were] expecting \the [partner] to have a cock or a pussy or ... something.",
+ )
+ genital = null
+ else
+ switch(fucktarget)
+ if("vagina")
+ genital = partner.getorganslot(ORGAN_SLOT_VAGINA)
+ if("penis")
+ genital = partner.getorganslot(ORGAN_SLOT_PENIS)
+ partner.set_is_fucking(user, CUM_TARGET_MOUTH, genital)
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bj1.ogg',
+ 'modular_sand/sound/interactions/bj2.ogg',
+ 'modular_sand/sound/interactions/bj3.ogg',
+ 'modular_sand/sound/interactions/bj4.ogg',
+ 'modular_sand/sound/interactions/bj5.ogg',
+ 'modular_sand/sound/interactions/bj6.ogg',
+ 'modular_sand/sound/interactions/bj7.ogg',
+ 'modular_sand/sound/interactions/bj8.ogg',
+ 'modular_sand/sound/interactions/bj9.ogg',
+ 'modular_sand/sound/interactions/bj10.ogg',
+ 'modular_sand/sound/interactions/bj11.ogg'), 50, 1, -1)
+ user.visible_message("\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ partner.handle_post_sex(lust_increase, CUM_TARGET_MOUTH, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/self/breasts.dm b/modular_sand/code/datums/interactions/lewd/interactions/self/breasts.dm
new file mode 100644
index 0000000000..098cd5153a
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/self/breasts.dm
@@ -0,0 +1,86 @@
+/datum/interaction/lewd/titgrope_self
+ command = "titgrope_self"
+ description = "Grope your own breasts."
+ require_user_hands = TRUE
+ require_user_breasts = REQUIRE_ANY
+ user_is_target = TRUE
+ interaction_sound = null
+ max_distance = 0
+ write_log_user = "groped own breasts"
+ write_log_target = null
+
+/datum/interaction/lewd/titgrope_self/display_interaction(mob/living/user)
+ var/message
+ var/t_His = user.p_their()
+
+ if(user.a_intent == INTENT_HARM)
+ message = "[pick("aggressively gropes [t_His] breast.",
+ "grabs [t_His] breasts.",
+ "tightly squeezes [t_His] breasts.",
+ "slaps at [t_His] breasts.",
+ "gropes [t_His] breasts roughly.")]"
+ else
+ message = "[pick("gently gropes [t_His] breast.",
+ "softly squeezes [t_His] breasts.",
+ "grips [t_His] breasts.",
+ "runs a few fingers over [t_His] breast.",
+ "delicately teases [t_His] nipple.",
+ "traces a touch across [t_His] breast.")]"
+ if(prob(5 + user.get_lust()))
+ user.visible_message("\The [user] [pick("shivers in arousal.",
+ "moans quietly.",
+ "breathes out a soft moan.",
+ "gasps.",
+ "shudders softly.",
+ "trembles as [t_His] hands run across bare skin.")]")
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/squelch1.ogg', 50, 1, -1)
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
+
+
+/datum/interaction/lewd/self_nipsuck
+ command = "self_nipsuck"
+ description = "Suck your own nips."
+ require_user_breasts = REQUIRE_EXPOSED
+ require_user_mouth = TRUE
+ user_is_target = TRUE
+ interaction_sound = null
+ max_distance = 0
+ write_log_user = "sucked their own nips"
+ write_log_target = null
+
+/datum/interaction/lewd/self_nipsuck/display_interaction(mob/living/user, mob/living/target)
+ var/message
+ var/u_His = user.p_their()
+ var/obj/item/organ/genital/breasts/milkers = user.getorganslot(ORGAN_SLOT_BREASTS)
+ var/milktype = milkers?.fluid_id
+ var/modifier
+ var/list/lines
+
+ if(!milkers || !milktype)
+ return
+
+ var/milktext = initial(milktype)
+
+ lines = list(
+ "brings [u_His] own milk tanks to [u_His] mouth and sucks deeply into them",
+ "takes a big sip of [u_His] own fresh [lowertext(milktext)]",
+ "fills [u_His] own mouth with a big gulp of [u_His] warm [lowertext(milktext)]"
+ )
+
+ message = "\The [user] [pick(lines)]"
+ user.visible_message(message, ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
+ 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
+
+ switch(milkers.size)
+ if("c", "d", "e")
+ modifier = 2
+ if("f", "g", "h")
+ modifier = 3
+ else
+ if(milkers.size in milkers.breast_values)
+ modifier = clamp(milkers.breast_values[milkers.size] - 5, 0, INFINITY)
+ else
+ modifier = 1
+ user.reagents.add_reagent(milktype, rand(1,3 * modifier))
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/self/finger.dm b/modular_sand/code/datums/interactions/lewd/interactions/self/finger.dm
new file mode 100644
index 0000000000..2776852559
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/self/finger.dm
@@ -0,0 +1,41 @@
+/datum/interaction/lewd/fingerass_self
+ command = "fingerm_self"
+ description = "Finger yourself."
+ interaction_sound = null
+ require_user_hands = TRUE
+ require_user_anus = REQUIRE_EXPOSED
+ user_is_target = TRUE
+ max_distance = 0
+ write_log_user = "fingered self"
+ write_log_target = null
+
+/datum/interaction/lewd/fingerass_self/display_interaction(mob/living/user)
+ var/t_His = user.p_their()
+ var/t_Him = user.p_them()
+
+ user.visible_message("\The [user] [pick("fingers [t_Him]self.",
+ "fingers [t_His] asshole.",
+ "fingers [t_Him]self hard.")]", ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
+
+/datum/interaction/lewd/finger_self
+ command = "finger_self"
+ description = "Finger your own pussy."
+ require_user_hands = TRUE
+ require_user_vagina = REQUIRE_EXPOSED
+ interaction_sound = null
+ user_is_target = TRUE
+ max_distance = 0
+ write_log_user = "fingered own pussy"
+ write_log_target = null
+
+/datum/interaction/lewd/finger_self/display_interaction(mob/living/user)
+ var/t_His = user.p_their()
+
+ user.visible_message("\The [user] [pick("fingers [t_His] pussy deep.",
+ "fingers [t_His] pussy.",
+ "plays with [t_His] pussy.",
+ "fingers [t_His] own pussy hard.")]", ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
diff --git a/modular_sand/code/datums/interactions/lewd/interactions/self/jack.dm b/modular_sand/code/datums/interactions/lewd/interactions/self/jack.dm
new file mode 100644
index 0000000000..521ac4c615
--- /dev/null
+++ b/modular_sand/code/datums/interactions/lewd/interactions/self/jack.dm
@@ -0,0 +1,32 @@
+/datum/interaction/lewd/jack
+ command = "jack"
+ description = "Jerk yourself off."
+ interaction_sound = null
+ require_user_hands = TRUE
+ require_user_penis = REQUIRE_EXPOSED
+ user_is_target = TRUE
+ max_distance = 0
+ write_log_user = "jerked off"
+ write_log_target = null
+
+/datum/interaction/lewd/jack/display_interaction(mob/living/user)
+ var/message
+ var/t_His = user.p_their()
+ var/t_Him = user.p_them()
+
+ if(user.is_fucking(user, CUM_TARGET_HAND))
+ message = "[pick("jerks [t_Him]self off.",
+ "works [t_His] shaft.",
+ "strokes [t_His] penis.",
+ "wanks [t_His] cock hard.")]"
+ else
+ message = "[pick("wraps [t_His] hand around [t_His] cock.",
+ "starts to stroke [t_His] cock.",
+ "starts playing with [t_His] cock.")]"
+ user.set_is_fucking(user, CUM_TARGET_HAND, user.getorganslot(ORGAN_SLOT_PENIS))
+
+ playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
+ 'modular_sand/sound/interactions/bang2.ogg',
+ 'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
+ user.visible_message(message = "\The [user] [message]", ignored_mobs = user.get_unconsenting())
+ user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
diff --git a/modular_sand/code/datums/interactions/lewd/lewd_datums.dm b/modular_sand/code/datums/interactions/lewd/lewd_datums.dm
deleted file mode 100644
index 862c406fc6..0000000000
--- a/modular_sand/code/datums/interactions/lewd/lewd_datums.dm
+++ /dev/null
@@ -1,594 +0,0 @@
-/datum/interaction/lewd
- var/list/blacklisted_mobs = list(/mob/living/simple_animal/pet,
- /mob/living/simple_animal/cockroach,
- /mob/living/simple_animal/babyKiwi,
- /mob/living/simple_animal/butterfly,
- /mob/living/simple_animal/chick,
- /mob/living/simple_animal/chicken,
- /mob/living/simple_animal/cow,
- /mob/living/simple_animal/crab,
- /mob/living/simple_animal/kiwi,
- /mob/living/simple_animal/parrot,
- /mob/living/simple_animal/sloth,
- /mob/living/simple_animal/pickle,
- /mob/living/simple_animal/hostile/retaliate/goat)
-
-/datum/interaction/lewd/kiss
- command = "deepkiss"
- description = "Kiss them deeply."
- require_user_mouth = TRUE
- require_target_mouth = TRUE
- write_log_user = "kissed"
- write_log_target = "was kissed by"
- interaction_sound = null
- max_distance = 1
-
-/datum/interaction/lewd/kiss/post_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- . = ..()
- if(user.get_lust() < 5)
- user.set_lust(5)
- if(target.get_lust() < 5)
- target.set_lust(5)
-
-/datum/interaction/lewd/kiss/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- if(user.get_lust() >= 3)
- user.visible_message("\The [user] gives an intense, lingering kiss to \the [target].")
- else
- user.visible_message("\The [user] kisses \the [target] deeply.")
-
-/datum/interaction/lewd/titgrope
- command = "titgrope"
- description = "Grope their breasts."
- require_user_hands = TRUE
- require_target_breasts = REQUIRE_ANY
- write_log_user = "groped"
- write_log_target = "was groped by"
- interaction_sound = null
- max_distance = 1
-
-/datum/interaction/lewd/titgrope/post_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- . = ..()
-
-/datum/interaction/lewd/titgrope/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- if(user.a_intent == INTENT_HELP)
- user.visible_message(
- pick("\The [user] gently gropes \the [target]'s breast.",
- "\The [user] softly squeezes \the [target]'s breasts.",
- "\The [user] grips \the [target]'s breasts.",
- "\The [user] runs a few fingers over \the [target]'s breast.",
- "\The [user] delicately teases \the [target]'s nipple.",
- "\The [user] traces a touch across \the [target]'s breast."))
- if(user.a_intent == INTENT_HARM)
- user.visible_message(
- pick("\The [user] aggressively gropes \the [target]'s breast.",
- "\The [user] grabs \the [target]'s breasts.",
- "\The [user] tightly squeezes \the [target]'s breasts.",
- "\The [user] slaps at \the [target]'s breasts.",
- "\The [user] gropes \the [target]'s breasts roughly."))
- if(prob(5 + target.get_lust()))
- if(target.a_intent == INTENT_HELP)
- user.visible_message(
- pick("\The [target] shivers in arousal.",
- "\The [target] moans quietly.",
- "\The [target] breathes out a soft moan.",
- "\The [target] gasps.",
- "\The [target] shudders softly.",
- "\The [target] trembles as hands run across bare skin."))
- if(target.get_lust() < 5)
- target.set_lust(5)
- if(target.a_intent == INTENT_DISARM)
- if (target.restrained())
- user.visible_message(
- pick("\The [target] twists playfully against the restraints.",
- "\The [target] squirms away from [user]'s hand.",
- "\The [target] slides back from [user]'s roaming hand.",
- "\The [target] thrusts bare breasts forward into [user]'s hands."))
- else
- user.visible_message(
- pick("\The [target] playfully bats at [user]'s hand.",
- "\The [target] squirms away from [user]'s hand.",
- "\The [target] guides [user]'s hand across bare breasts.",
- "\The [target] teasingly laces a few fingers over [user]'s knuckles."))
- if(target.get_lust() < 10)
- target.add_lust(1)
- if(target.a_intent == INTENT_GRAB)
- user.visible_message(
- pick("\The [target] grips [user]'s wrist tight.",
- "\The [target] digs nails into [user]'s arm.",
- "\The [target] grabs [user]'s wrist for a second."))
- if(target.a_intent == INTENT_HARM)
- user.adjustBruteLoss(1)
- user.visible_message(
- pick("\The [target] pushes [user] roughly away.",
- "\The [target] digs nails angrily into [user]'s arm.",
- "\The [target] fiercely struggles against [user].",
- "\The [target] claws [user]'s forearm, drawing blood.",
- "\The [target] slaps [user]'s hand away."))
- return
-
-/datum/interaction/lewd/nipsuck
- command = "nipsuck"
- description = "Suck their nipples."
- require_target_topless = TRUE
- require_user_mouth = TRUE
- write_log_user = "sucked nipples"
- write_log_target = "had their nipples sucked by"
- interaction_sound = null
- max_distance = 1
-
-/datum/interaction/lewd/nipsuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- if((user.a_intent == INTENT_HELP) || (user.a_intent == INTENT_DISARM))
- user.visible_message(
- pick("\The [user] gently sucks on \the [target]'s [pick("nipple", "nipples")].",
- "\The [user] gently nibs \the [target]'s [pick("nipple", "nipples")].",
- "\The [user] licks \the [target]'s [pick("nipple", "nipples")]."))
- if(target.has_breasts(REQUIRE_EXPOSED))
- var/modifier = 1
- var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
- switch(B.size)
- if("c", "d", "e")
- modifier = 2
- if("f", "g", "h")
- modifier = 3
- else
- if(B.size in B.breast_values)
- modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
- else
- modifier = 1
- if(B.fluid_id)
- user.reagents.add_reagent(B.fluid_id, rand(1,2 * modifier))
-
- if(user.a_intent == INTENT_HARM)
- user.visible_message(
- pick("\The [user] bites \the [target]'s [pick("nipple", "nipples")].",
- "\The [user] aggressively sucks \the [target]'s [pick("nipple", "nipples")]."))
- if(target.has_breasts(REQUIRE_EXPOSED))
- var/modifier = 1
- var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
- switch(B.size)
- if("c", "d", "e")
- modifier = 2
- if("f", "g", "h")
- modifier = 3
- else
- if(B.size in B.breast_values)
- modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
- else
- modifier = 1
- if(B.fluid_id)
- user.reagents.add_reagent(B.fluid_id, rand(1,3 * modifier)) //aggressive sucking leads to high rewards
-
- if(user.a_intent == INTENT_GRAB)
- user.visible_message(
- pick("\The [user] sucks \the [target]'s [pick("nipple", "nipples")] intently.",
- "\The [user] feasts \the [target]'s [pick("nipple", "nipples")].",
- "\The [user] glomps \the [target]'s [pick("nipple", "nipples")]."))
- if(target.has_breasts(REQUIRE_EXPOSED))
- var/modifier = 1
- var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
- switch(B.size)
- if("c", "d", "e")
- modifier = 2
- if("f", "g", "h")
- modifier = 3
- else
- if(B.size in B.breast_values)
- modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
- else
- modifier = 1
- if(B.fluid_id)
- user.reagents.add_reagent(B.fluid_id, rand(1,3 * modifier)) //aggressive sucking leads to high rewards
-
- if(prob(5 + target.get_lust()))
- if(target.a_intent == INTENT_HELP)
- if(!target.has_breasts())
- user.visible_message(
- pick("\The [target] shivers in arousal.",
- "\The [target] moans quietly.",
- "\The [target] breathes out a soft moan.",
- "\The [target] gasps.",
- "\The [target] shudders softly.",
- "\The [target] trembles as their chest gets molested."))
- else
- user.visible_message(
- pick("\The [target] shivers in arousal.",
- "\The [target] moans quietly.",
- "\The [target] breathes out a soft moan.",
- "\The [target] gasps.",
- "\The [target] shudders softly.",
- "\The [target] trembles as their breasts get molested.",
- "\The [target] quivers in arousal as \the [user] delights themselves on their milk."))
- if(target.get_lust() < 5)
- target.set_lust(5)
- if(target.a_intent == INTENT_DISARM)
- if (target.restrained())
- if(!target.has_breasts())
- user.visible_message(
- pick("\The [target] twists playfully against the restraints.",
- "\The [target] squirms away from \the [user]'s mouth.",
- "\The [target] slides back from \the [user]'s mouth.",
- "\The [target] thrusts their bare chest forward into \the [user]'s mouth."))
- else
- user.visible_message(
- pick("\The [target] twists playfully against the restraints.",
- "\The [target] squirms away from \the [user]'s mouth.",
- "\The [target] slides back from \the [user]'s mouth.",
- "\The [target] thrust their bare breasts forward into \the [user]'s mouth."))
- else
- if(!target.has_breasts())
- user.visible_message(
- pick("\The [target] playfully shoos away \the [user]'s head.",
- "\The [target] squirms away from \the [user]'s mouth.",
- "\The [target] holds \the [user]'s head against their chest.",
- "\The [target] teasingly caresses \the [user]'s neck."))
- else
- user.visible_message(
- pick("\The [target] playfully shoos away \the [user]'s head.",
- "\The [target] squirms away from \the [user]'s mouth.",
- "\The [target] holds \the [user]'s head against their breast.",
- "\The [target] teasingly caresses \the [user]'s neck.",
- "\The [target] rubs their breasts against \the [user]'s head."))
- if(target.get_lust() < 10)
- target.add_lust(1)
- if(target.a_intent == INTENT_GRAB)
- user.visible_message(
- pick("\The [target] grips \the [user]'s head tight.",
- "\The [target] digs nails into \the [user]'s scalp.",
- "\The [target] grabs and shoves \the [user]'s head away."))
- if(target.a_intent == INTENT_HARM)
- user.adjustBruteLoss(1)
- user.visible_message(
- pick("\The [target] slaps \the [user] away.",
- "\The [target] scratches [user]'s face.",
- "\The [target] fiercely struggles against [user].",
- "\The [target] claws [user]'s face, drawing blood.",
- "\The [target] elbows [user]'s mouth away."))
- target.dir = get_dir(target, user)
- user.dir = get_dir(user, target)
- playlewdinteractionsound(user.loc, pick('modular_sand/sound/interactions/oral1.ogg',
- 'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
- return
-
-/datum/interaction/lewd/oral
- command = "suckvag"
- description = "Go down on them."
- require_user_mouth = TRUE
- require_target_vagina = REQUIRE_EXPOSED
- write_log_user = "gave head to"
- write_log_target = "was given head by"
- interaction_sound = null
- max_distance = 1
-
-/datum/interaction/lewd/oral/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_oral(target, "vagina")
-
-/datum/interaction/lewd/oral/blowjob
- command = "suckcock"
- description = "Suck them off."
- require_target_vagina = REQUIRE_NONE
- require_target_penis = REQUIRE_EXPOSED
-
-/datum/interaction/lewd/oral/blowjob/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_oral(target, "penis")
-
-/datum/interaction/lewd/fuck
- command = "fuckvag"
- description = "Fuck their pussy."
- require_user_penis = REQUIRE_EXPOSED
- require_target_vagina = REQUIRE_EXPOSED
- write_log_user = "fucked"
- write_log_target = "was fucked by"
- interaction_sound = null
- max_distance = 1
-
-/datum/interaction/lewd/fuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_vaginal(target)
-
-/datum/interaction/lewd/fuck/anal
- command = "fuckass"
- description = "Fuck their ass."
- require_target_vagina = REQUIRE_NONE
- require_target_anus = REQUIRE_EXPOSED
-
-/datum/interaction/lewd/fuck/anal/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_anal(target)
-
-/datum/interaction/lewd/finger
- command = "finger"
- description = "Finger their pussy."
- require_user_hands = TRUE
- require_target_vagina = REQUIRE_EXPOSED
- interaction_sound = null
- max_distance = 1
-
-/datum/interaction/lewd/finger/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_fingering(target)
-
-/datum/interaction/lewd/fingerass
- command = "fingerm"
- description = "Finger their ass."
- interaction_sound = null
- require_user_hands = TRUE
- require_target_anus = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/fingerass/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_fingerass(target)
-
-
-/datum/interaction/lewd/facefuck
- command = "facefuck"
- description = "Fuck their mouth."
- interaction_sound = null
- require_target_mouth = TRUE
- require_user_penis = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/facefuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_facefuck(target)
-
-/datum/interaction/lewd/throatfuck
- command = "throatfuck"
- description = "Fuck their throat. | Does oxy damage."
- interaction_sound = null
- require_user_penis = REQUIRE_EXPOSED
- require_target_mouth = TRUE
- max_distance = 1
-
-/datum/interaction/lewd/throatfuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_throatfuck(target)
-
-/datum/interaction/lewd/handjob
- command = "handjob"
- description = "Jerk them off."
- interaction_sound = null
- require_user_hands = TRUE
- require_target_penis = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/handjob/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_handjob(target)
-
-/datum/interaction/lewd/breastfuck
- command = "breastfuck"
- description = "Fuck their breasts."
- interaction_sound = null
- require_user_penis = REQUIRE_EXPOSED
- require_target_breasts = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/breastfuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_breastfuck(target)
-
-/datum/interaction/lewd/mount
- command = "mount"
- description = "Mount with your pussy."
- interaction_sound = null
- require_user_vagina = REQUIRE_EXPOSED
- require_target_penis = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/mount/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_mount(target)
-
-/datum/interaction/lewd/mountass
- command = "mountm"
- description = "Mount with your ass."
- interaction_sound = null
- require_user_anus = REQUIRE_EXPOSED
- require_target_penis = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/mountass/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_mountass(target)
-
-/datum/interaction/lewd/tribadism
- command = "tribadism"
- description = "Grind your pussy against theirs."
- interaction_sound = null
- require_target_vagina = REQUIRE_EXPOSED
- require_user_vagina = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/tribadism/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_tribadism(target)
-
-/datum/interaction/lewd/rimjob
- command = "rimjob"
- description = "Lick their ass."
- interaction_sound = null
- require_user_mouth = TRUE
- require_target_anus = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/rimjob/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_rimjob(target)
-
-/datum/interaction/lewd/mountface
- command = "mountface"
- description = "Ass to face."
- interaction_sound = null
- require_target_mouth = TRUE
- require_user_anus = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/mountface/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_mountface(target)
-
-/datum/interaction/lewd/lickfeet
- command = "lickfeet"
- description = "Lick their feet."
- interaction_sound = null
- require_user_mouth = TRUE
- require_target_feet = REQUIRE_ANY
- require_target_num_feet = 1
- max_distance = 1
-
-/datum/interaction/lewd/lickfeet/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_lickfeet(target)
-
-/datum/interaction/lewd/grindface
- command = "grindface"
- description = "Feet grind their face."
- interaction_sound = null
- require_target_mouth = TRUE
- require_user_num_feet = 1
- require_user_feet = REQUIRE_ANY
- max_distance = 1
-
-/datum/interaction/lewd/grindface/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_grindface(target)
-
-/datum/interaction/lewd/grindmouth
- command = "grindmouth"
- description = "Feet grind their mouth."
- interaction_sound = null
- require_target_mouth = TRUE
- require_user_num_feet = 1
- require_user_feet = REQUIRE_ANY
- max_distance = 1
-
-/datum/interaction/lewd/grindmouth/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_grindmouth(target)
-
-/datum/interaction/lewd/footfuck
- command = "footfuck"
- description = "Rub your cock on their foot."
- interaction_sound = null
- require_target_num_feet = 1
- require_target_feet = REQUIRE_ANY
- require_user_penis = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/footfuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_footfuck(target)
-
-/datum/interaction/lewd/footfuck/double
- command = "footfuckdouble"
- description = "Rub your cock between their feet."
- require_target_num_feet = 2
-
-/datum/interaction/lewd/footfuck/double/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_dfootfuck(target)
-
-/datum/interaction/lewd/footjob
- command = "footjob"
- description = "Jerk them off with your foot."
- interaction_sound = null
- require_user_num_feet = 1
- require_user_feet = REQUIRE_ANY
- require_target_penis = REQUIRE_EXPOSED
- max_distance = 1
-
-/datum/interaction/lewd/footjob/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_footjob(target)
-
-/datum/interaction/lewd/footjob/double
- command = "footjob_double"
- description = "Jerk them off with both of your feet."
- require_user_num_feet = 2
-
-/datum/interaction/lewd/footjob/double/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_dfootjob(target)
-
-/datum/interaction/lewd/footjob/vagina
- command = "footjob_vaginal"
- description = "Rub their vagina with your foot."
- require_target_vagina = REQUIRE_EXPOSED
- require_target_penis = REQUIRE_NONE
-
-/datum/interaction/lewd/footjob/vagina/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_footjob_v(target)
-
-/datum/interaction/lewd/thighs
- command = "thigh_smother"
- description = "Smother them."
- max_distance = 1
- require_user_bottomless = TRUE
- require_target_mouth = TRUE
- interaction_sound = null
- write_log_user = "thigh-trapped"
- write_log_target = "was smothered by"
-
-/datum/interaction/lewd/thighs/display_interaction(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
- user.thigh_smother(target)
-
-/datum/interaction/lewd/nuts
- command = "nut_face"
- description = "Nuts to face."
- interaction_sound = null
- require_user_balls = REQUIRE_EXPOSED
- require_target_mouth = TRUE
- max_distance = 1
- write_log_user = "make-them-suck-their-nuts"
- write_log_target = "was made to suck nuts by"
-
-/datum/interaction/lewd/nuts/display_interaction(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
- user.nut_face(target)
-
-/datum/interaction/lewd/nut_smack
- command = "smack_nuts"
- description = "Smack their nuts."
- interaction_sound = 'modular_sand/sound/interactions/slap.ogg'
- simple_message = "USER slaps TARGET's nuts!"
- require_target_balls = REQUIRE_EXPOSED
- needs_physical_contact = TRUE
- max_distance = 1
- write_log_user = "slapped-nuts"
- write_log_target = "had their nuts slapped by"
-
-//Weird shit section
-/datum/interaction/lewd/earfuck
- command = "earfuck"
- description = "Fuck their ear."
- interaction_sound = null
- simple_message = "USER penetrates TARGET's ear!"
- require_user_penis = REQUIRE_EXPOSED
- require_target_ears = REQUIRE_EXPOSED
- max_distance = 1
- write_log_user = "earfucked"
- write_log_target = "had their ear fucked by"
- extreme = TRUE
-
-/datum/interaction/lewd/earfuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_earfuck(target)
-
-/datum/interaction/lewd/earfuck/earsocketfuck
- command = "earsocketfuck"
- description = "Fuck their earsocket."
- interaction_sound = null
- simple_message = "USER penetrates TARGET's earsocket!"
- require_user_penis = REQUIRE_EXPOSED
- require_target_earsockets = REQUIRE_EXPOSED
- max_distance = 1
- write_log_user = "earsocket fucked"
- write_log_target = "had their earsocket fucked by"
- extreme = TRUE
-
-/datum/interaction/lewd/eyefuck
- command = "eyefuck"
- description = "Fuck their eye."
- interaction_sound = null
- simple_message = "USER penetrates TARGET's eye!"
- require_user_penis = REQUIRE_EXPOSED
- require_target_eyes = REQUIRE_EXPOSED
- max_distance = 1
- write_log_user = "eyefucked"
- write_log_target = "had their eye fucked by"
- extreme = TRUE
-
-/datum/interaction/lewd/eyefuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- user.do_eyefuck(target)
-
-/datum/interaction/lewd/eyefuck/eyesocketfuck
- command = "eyesocketfuck"
- description = "Fuck their eyesocket."
- interaction_sound = null
- simple_message = "USER penetrates TARGET's eyesocket!"
- require_user_penis = REQUIRE_EXPOSED
- require_target_eyesockets = REQUIRE_EXPOSED
- max_distance = 1
- write_log_user = "eyesocketfucked"
- write_log_target = "had their eyesocket fucked by"
- extreme = TRUE
-//
diff --git a/modular_sand/code/datums/interactions/lewd/lewd_datums_extra.dm b/modular_sand/code/datums/interactions/lewd/lewd_datums_extra.dm
deleted file mode 100644
index 179e386a00..0000000000
--- a/modular_sand/code/datums/interactions/lewd/lewd_datums_extra.dm
+++ /dev/null
@@ -1,99 +0,0 @@
-/datum/interaction/lewd/frotting
- command = "frotting"
- description = "Rub your penis against theirs"
- require_user_penis = REQUIRE_EXPOSED
- require_target_penis = REQUIRE_EXPOSED
- max_distance = 1
- write_log_user = "frotted"
- write_log_target = "was frotted by"
- interaction_sound = null
-
-/datum/interaction/lewd/frotting/display_interaction(mob/living/user, mob/living/target)
- user.do_frot(target)
-
-/datum/interaction/lewd/do_breastfeed
- command = "do_breastfeed"
- description = "Breastfeed them"
- require_user_breasts = REQUIRE_EXPOSED
- require_target_mouth = TRUE
- max_distance = 1
- write_log_user = "breastfed"
- write_log_target = "was breastfed by"
- interaction_sound = null
-
-/datum/interaction/lewd/do_breastfeed/display_interaction(mob/living/user, mob/living/target)
- user.do_breastfeed(target)
-
-/**
- * Self Interactions!
- */
-
-/datum/interaction/lewd/jack
- command = "jack"
- description = "Jerk yourself off."
- interaction_sound = null
- require_user_hands = TRUE
- require_user_penis = REQUIRE_EXPOSED
- user_is_target = TRUE
- max_distance = 0
- write_log_user = "jerked off"
- write_log_target = null
-
-/datum/interaction/lewd/jack/display_interaction(mob/living/carbon/human/user)
- user.do_jackoff(user)
-
-/datum/interaction/lewd/fingerass_self
- command = "fingerm_self"
- description = "Finger yourself."
- interaction_sound = null
- require_user_hands = TRUE
- require_user_anus = REQUIRE_EXPOSED
- user_is_target = TRUE
- max_distance = 0
- write_log_user = "fingered self"
- write_log_target = null
-
-/datum/interaction/lewd/fingerass_self/display_interaction(mob/living/carbon/human/user)
- user.do_fingerass_self(user)
-
-/datum/interaction/lewd/finger_self
- command = "finger_self"
- description = "Finger your own pussy."
- require_user_hands = TRUE
- require_user_vagina = REQUIRE_EXPOSED
- interaction_sound = null
- user_is_target = TRUE
- max_distance = 0
- write_log_user = "fingered own pussy"
- write_log_target = null
-
-/datum/interaction/lewd/finger_self/display_interaction(mob/living/carbon/human/user)
- user.do_fingering_self(user)
-
-/datum/interaction/lewd/titgrope_self
- command = "titgrope_self"
- description = "Grope your own breasts."
- require_user_hands = TRUE
- require_user_breasts = REQUIRE_ANY
- user_is_target = TRUE
- interaction_sound = null
- max_distance = 0
- write_log_user = "groped own breasts"
- write_log_target = null
-
-/datum/interaction/lewd/titgrope_self/display_interaction(mob/living/carbon/human/user)
- user.do_titgrope_self(user)
-
-/datum/interaction/lewd/self_nipsuck
- command = "self_nipsuck"
- description = "Suck your own nips."
- require_user_breasts = REQUIRE_EXPOSED
- require_user_mouth = TRUE
- user_is_target = TRUE
- interaction_sound = null
- max_distance = 0
- write_log_user = "sucked their own nips"
- write_log_target = null
-
-/datum/interaction/lewd/self_nipsuck/display_interaction(mob/living/user, mob/living/target)
- user.do_breastfeed(user)
diff --git a/modular_sand/code/datums/interactions/lewd/lewd_interactions.dm b/modular_sand/code/datums/interactions/lewd/lewd_interactions.dm
index c9924f9489..fd83383f9b 100644
--- a/modular_sand/code/datums/interactions/lewd/lewd_interactions.dm
+++ b/modular_sand/code/datums/interactions/lewd/lewd_interactions.dm
@@ -514,7 +514,7 @@
user.cleartimer = addtimer(CALLBACK(user, /mob/living/proc/clear_lewd_datum), 300, TIMER_STOPPABLE)
return ..()
-/mob/living/list_interaction_attributes(var/mob/living/LM)
+/mob/living/list_interaction_attributes(mob/living/LM)
var/dat = ..()
if(get_refraction_dif())
dat += "...are sexually exhausted for the time being."
@@ -548,10 +548,13 @@
else
dat += "...have covered eyes."
//
- if(is_topless() && is_bottomless())
+ // check those loops only once, thanks
+ var/is_topless = is_topless()
+ var/is_bottomless = is_bottomless()
+ if(is_topless && is_bottomless)
dat += "...are naked."
else
- if((is_topless() && !is_bottomless()) || (!is_topless() && is_bottomless()))
+ if((is_topless && !is_bottomless) || (!is_topless && is_bottomless))
dat += "...are partially clothed."
else
dat += "...are clothed."
diff --git a/modular_sand/code/datums/interactions/lewd/lewd_species.dm b/modular_sand/code/datums/interactions/lewd/lewd_species.dm
deleted file mode 100644
index bf8c9e55a9..0000000000
--- a/modular_sand/code/datums/interactions/lewd/lewd_species.dm
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Seriously this is the worst way to do this,
- * warn me if there's ANY reason i would ever
- * use this. Humans have GENITALS, ACTUAL ORGANS,
- * we don't need to check booleans!
- * If this does not get an use sometime,
- * i want this file gone.
- */
-
-/*
-/datum/species
- var/has_genitals = TRUE //if this goes to 2, blame coders
- var/has_anus = TRUE //same with this
- var/has_breasts = FALSE
-
-/datum/species/proc/has_penis(mob/living/carbon/human/H)
- return has_genitals && H.has_penis
-
-/datum/species/proc/has_vagina(mob/living/carbon/human/H)
- return has_genitals && H.has_vagina
-
-/datum/species/proc/has_anus(mob/living/carbon/human/H)
- return has_anus
-
-/datum/species/proc/has_breasts(mob/living/carbon/human/H)
- return has_breasts
-*/
diff --git a/tgstation.dme b/tgstation.dme
index 418103fee8..90e6139423 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3879,12 +3879,26 @@
#include "modular_sand\code\datums\interactions\interaction_interface.dm"
#include "modular_sand\code\datums\interactions\interaction_mob.dm"
#include "modular_sand\code\datums\interactions\lewd\_lewd.dm"
-#include "modular_sand\code\datums\interactions\lewd\_lewd_extra.dm"
-#include "modular_sand\code\datums\interactions\lewd\lewd_datums.dm"
-#include "modular_sand\code\datums\interactions\lewd\lewd_datums_extra.dm"
#include "modular_sand\code\datums\interactions\lewd\lewd_interactions.dm"
-#include "modular_sand\code\datums\interactions\lewd\lewd_species.dm"
#include "modular_sand\code\datums\interactions\lewd\objects.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\breasts.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\facefuck.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\feet.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\finger.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\frotting.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\fuck.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\handjob.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\kiss.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\lick.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\mount.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\nipsuck.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\nuts.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\oral.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\cursed\earfuck.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\cursed\eyefuck.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\self\breasts.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\self\finger.dm"
+#include "modular_sand\code\datums\interactions\lewd\interactions\self\jack.dm"
#include "modular_sand\code\datums\mood_events\generic_negative_events.dm"
#include "modular_sand\code\datums\mood_events\needs_events.dm"
#include "modular_sand\code\datums\mutations\combined.dm"