diff --git a/code/__SANDCODE/DEFINES/lewd.dm b/code/__SANDCODE/DEFINES/lewd.dm
index 54856f90eacb..db32e3e5d2ce 100644
--- a/code/__SANDCODE/DEFINES/lewd.dm
+++ b/code/__SANDCODE/DEFINES/lewd.dm
@@ -10,6 +10,31 @@ GLOBAL_LIST_INIT(lewd_prefs_choices, list(
"No"
))
+// Moaning Sounds
+GLOBAL_LIST_INIT(lewd_moans_male, list(
+ 'modular_sand/sound/interactions/moan_m1.ogg',
+ 'modular_sand/sound/interactions/moan_m2.ogg',
+ 'modular_sand/sound/interactions/moan_m3.ogg'
+))
+
+GLOBAL_LIST_INIT(lewd_moans_female, list(
+ 'modular_sand/sound/interactions/moan_f1.ogg',
+ 'modular_sand/sound/interactions/moan_f2.ogg',
+ 'modular_sand/sound/interactions/moan_f3.ogg',
+ 'modular_sand/sound/interactions/moan_f4.ogg',
+ 'modular_sand/sound/interactions/moan_f5.ogg',
+ 'modular_sand/sound/interactions/moan_f6.ogg',
+ 'modular_sand/sound/interactions/moan_f7.ogg'
+))
+// Kissing sounds
+GLOBAL_LIST_INIT(lewd_kiss_sounds, list(
+ 'modular_sand/sound/interactions/kiss1.ogg',
+ 'modular_sand/sound/interactions/kiss2.ogg',
+ 'modular_sand/sound/interactions/kiss3.ogg',
+ 'modular_sand/sound/interactions/kiss4.ogg',
+ 'modular_sand/sound/interactions/kiss5.ogg'
+))
+
#define CUM_TARGET_MOUTH "mouth"
#define CUM_TARGET_THROAT "throat"
#define CUM_TARGET_VAGINA "vagina"
diff --git a/code/__SANDCODE/DEFINES/misc.dm b/code/__SANDCODE/DEFINES/misc.dm
index 83a266dac974..4672f0416c9b 100644
--- a/code/__SANDCODE/DEFINES/misc.dm
+++ b/code/__SANDCODE/DEFINES/misc.dm
@@ -1,2 +1,4 @@
/// Adds an utf-8 header...? only ever used on circuitry so when wiremod arrives...
#define UTF8HEADER ""
+/// A shorthand for ternary operators to simulate a null-coalescing operator. Returns the first argument if its defined, otherwise, second.
+#define NULL_COALESCE(var, default) (isnull(var) ? (default) : (var))
diff --git a/code/__SANDCODE/HELPERS/math.dm b/code/__SANDCODE/HELPERS/math.dm
new file mode 100644
index 000000000000..05eca8146c13
--- /dev/null
+++ b/code/__SANDCODE/HELPERS/math.dm
@@ -0,0 +1,4 @@
+/proc/percentage_between(x,a,b,centesimal = TRUE)
+ if (a > b)
+ return percentage_between(x, b, a, centesimal)
+ return clamp((x-a)/(b-a),0,1) * (centesimal ? 100 : 1)
diff --git a/html/changelogs/archive/2024-08.yml b/html/changelogs/archive/2024-08.yml
index af2299c06167..572b8f6cdf38 100644
--- a/html/changelogs/archive/2024-08.yml
+++ b/html/changelogs/archive/2024-08.yml
@@ -5,3 +5,12 @@
2024-08-04:
SandPoot:
- code_imp: Coders can now use a list of sounds for basic interactions.
+2024-08-09:
+ xTheLifex:
+ - rscadd: Kiss interaction now has sounds.
+ - rscadd: Added arousal multiplier preference option
+ - rscadd: Added moaning chance preference option
+ - tweak: Moaning chance should no longer be under two probability checks.
+ - soundadd: Added new kissing sounds
+ - soundadd: Added new moaning sounds
+ - soundadd: Added new male climax sounds
diff --git a/modular_sand/code/datums/components/interaction_menu_granter.dm b/modular_sand/code/datums/components/interaction_menu_granter.dm
index 41964f95055f..0df302fae90f 100644
--- a/modular_sand/code/datums/components/interaction_menu_granter.dm
+++ b/modular_sand/code/datums/components/interaction_menu_granter.dm
@@ -415,43 +415,49 @@
var/datum/preferences/prefs = self?.client.prefs
if(prefs)
+ //Lust stuff, appears at the very top
+ .["use_arousal_multiplier"] = prefs.use_arousal_multiplier
+ .["arousal_multiplier"] = prefs.arousal_multiplier
+ .["use_moaning_multiplier"] = prefs.use_moaning_multiplier
+ .["moaning_multiplier"] = prefs.moaning_multiplier
+
//Let's get their favorites!
- .["favorite_interactions"] = SANITIZE_LIST(prefs.favorite_interactions)
+ .["favorite_interactions"] = SANITIZE_LIST(prefs.favorite_interactions)
//Getting char prefs
- .["erp_pref"] = pref_to_num(prefs.erppref)
- .["noncon_pref"] = pref_to_num(prefs.nonconpref)
- .["vore_pref"] = pref_to_num(prefs.vorepref)
- .["extreme_pref"] = pref_to_num(prefs.extremepref)
- .["extreme_harm"] = pref_to_num(prefs.extremeharm)
- .["unholy_pref"] = pref_to_num(prefs.unholypref)
+ .["erp_pref"] = pref_to_num(prefs.erppref)
+ .["noncon_pref"] = pref_to_num(prefs.nonconpref)
+ .["vore_pref"] = pref_to_num(prefs.vorepref)
+ .["extreme_pref"] = pref_to_num(prefs.extremepref)
+ .["extreme_harm"] = pref_to_num(prefs.extremeharm)
+ .["unholy_pref"] = pref_to_num(prefs.unholypref)
//Getting preferences
- .["verb_consent"] = !!CHECK_BITFIELD(prefs.toggles, VERB_CONSENT)
- .["lewd_verb_sounds"] = !!CHECK_BITFIELD(prefs.toggles, LEWD_VERB_SOUNDS)
- .["arousable"] = prefs.arousable
- .["genital_examine"] = !!CHECK_BITFIELD(prefs.cit_toggles, GENITAL_EXAMINE)
- .["vore_examine"] = !!CHECK_BITFIELD(prefs.cit_toggles, VORE_EXAMINE)
- .["medihound_sleeper"] = !!CHECK_BITFIELD(prefs.cit_toggles, MEDIHOUND_SLEEPER)
- .["eating_noises"] = !!CHECK_BITFIELD(prefs.cit_toggles, EATING_NOISES)
- .["digestion_noises"] = !!CHECK_BITFIELD(prefs.cit_toggles, DIGESTION_NOISES)
- .["trash_forcefeed"] = !!CHECK_BITFIELD(prefs.cit_toggles, TRASH_FORCEFEED)
- .["forced_fem"] = !!CHECK_BITFIELD(prefs.cit_toggles, FORCED_FEM)
- .["forced_masc"] = !!CHECK_BITFIELD(prefs.cit_toggles, FORCED_MASC)
- .["hypno"] = !!CHECK_BITFIELD(prefs.cit_toggles, HYPNO)
- .["bimbofication"] = !!CHECK_BITFIELD(prefs.cit_toggles, BIMBOFICATION)
- .["breast_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, BREAST_ENLARGEMENT)
- .["penis_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, PENIS_ENLARGEMENT)
- .["butt_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, BUTT_ENLARGEMENT)
- .["belly_inflation"] = !!CHECK_BITFIELD(prefs.cit_toggles, BELLY_INFLATION)
- .["never_hypno"] = !CHECK_BITFIELD(prefs.cit_toggles, NEVER_HYPNO)
- .["no_aphro"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_APHRO)
- .["no_ass_slap"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_ASS_SLAP)
- .["no_auto_wag"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_AUTO_WAG)
- .["chastity_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, CHASTITY)
- .["stimulation_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, STIMULATION)
- .["edging_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, EDGING)
- .["cum_onto_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, CUM_ONTO)
+ .["verb_consent"] = !!CHECK_BITFIELD(prefs.toggles, VERB_CONSENT)
+ .["lewd_verb_sounds"] = !!CHECK_BITFIELD(prefs.toggles, LEWD_VERB_SOUNDS)
+ .["arousable"] = prefs.arousable
+ .["genital_examine"] = !!CHECK_BITFIELD(prefs.cit_toggles, GENITAL_EXAMINE)
+ .["vore_examine"] = !!CHECK_BITFIELD(prefs.cit_toggles, VORE_EXAMINE)
+ .["medihound_sleeper"] = !!CHECK_BITFIELD(prefs.cit_toggles, MEDIHOUND_SLEEPER)
+ .["eating_noises"] = !!CHECK_BITFIELD(prefs.cit_toggles, EATING_NOISES)
+ .["digestion_noises"] = !!CHECK_BITFIELD(prefs.cit_toggles, DIGESTION_NOISES)
+ .["trash_forcefeed"] = !!CHECK_BITFIELD(prefs.cit_toggles, TRASH_FORCEFEED)
+ .["forced_fem"] = !!CHECK_BITFIELD(prefs.cit_toggles, FORCED_FEM)
+ .["forced_masc"] = !!CHECK_BITFIELD(prefs.cit_toggles, FORCED_MASC)
+ .["hypno"] = !!CHECK_BITFIELD(prefs.cit_toggles, HYPNO)
+ .["bimbofication"] = !!CHECK_BITFIELD(prefs.cit_toggles, BIMBOFICATION)
+ .["breast_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, BREAST_ENLARGEMENT)
+ .["penis_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, PENIS_ENLARGEMENT)
+ .["butt_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, BUTT_ENLARGEMENT)
+ .["belly_inflation"] = !!CHECK_BITFIELD(prefs.cit_toggles, BELLY_INFLATION)
+ .["never_hypno"] = !CHECK_BITFIELD(prefs.cit_toggles, NEVER_HYPNO)
+ .["no_aphro"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_APHRO)
+ .["no_ass_slap"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_ASS_SLAP)
+ .["no_auto_wag"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_AUTO_WAG)
+ .["chastity_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, CHASTITY)
+ .["stimulation_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, STIMULATION)
+ .["edging_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, EDGING)
+ .["cum_onto_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, CUM_ONTO)
/datum/component/interaction_menu_granter/ui_static_data(mob/user)
. = ..()
@@ -609,6 +615,15 @@
if("pref")
var/datum/preferences/prefs = parent_mob.client.prefs
switch(params["pref"])
+ if("use_arousal_multiplier")
+ prefs.use_arousal_multiplier = !prefs.use_arousal_multiplier
+ if("arousal_multiplier")
+ prefs.arousal_multiplier = params["amount"]
+ if("use_moaning_multiplier")
+ prefs.use_moaning_multiplier = !prefs.use_moaning_multiplier
+ if("moaning_multiplier")
+ prefs.moaning_multiplier = params["amount"]
+
if("verb_consent")
TOGGLE_BITFIELD(prefs.toggles, VERB_CONSENT)
if("lewd_verb_sounds")
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
index 4aded3a99ee8..bcdc93126be1 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
@@ -18,3 +18,4 @@
user.visible_message(span_lewd("\The [user] gives an intense, lingering kiss to \the [partner]."))
else
user.visible_message(span_lewd("\The [user] kisses \the [partner] deeply."))
+ playlewdinteractionsound(user.loc, pick(GLOB.lewd_kiss_sounds), 90, 0, 0)
diff --git a/modular_sand/code/datums/interactions/lewd_definitions.dm b/modular_sand/code/datums/interactions/lewd_definitions.dm
index d7a8911b0b0f..48fc55aa8364 100644
--- a/modular_sand/code/datums/interactions/lewd_definitions.dm
+++ b/modular_sand/code/datums/interactions/lewd_definitions.dm
@@ -284,16 +284,33 @@
return TRUE
/mob/living/proc/moan()
- if(!(prob(get_lust() / get_lust_tolerance() * 65)))
+ if(is_muzzled() || (mind?.miming))
+ var/message_to_display = pick("mime%S% a pleasured moan","moan%S% in silence")
+ visible_message(span_lewd("\The [src] [replacetext(message_to_display, "%S%", "s")]."),
+ span_lewd("You [replacetext(message_to_display, "%S%", "")]."))
return
- var/moan = rand(1, 7)
- if(moan == lastmoan)
- moan--
- if(!is_muzzled())
- visible_message(message = span_lewd("\The [src] [pick("moans", "moans in pleasure")]."), ignored_mobs = get_unconsenting())
- if(is_muzzled())//immursion
- audible_message(span_lewd("[src] [pick("mimes a pleasured moan","moans in silence")]."))
- lastmoan = moan
+ var/message_to_display = pick("moan%S%", "moan%S% in pleasure")
+ visible_message(span_lewd("\The [src] [replacetext(message_to_display, "%S%", "s")]."),
+ span_lewd("You [replacetext(message_to_display, "%S%", "")]."),
+ span_lewd("You hear some moaning."),
+ ignored_mobs = get_unconsenting(), omni = TRUE)
+
+ // Get reference of the list we're using based on gender.
+ var/list/moans
+ if (gender == FEMALE)
+ moans = GLOB.lewd_moans_female
+ else
+ moans = GLOB.lewd_moans_male
+
+ // Pick a sound from the list.
+ var/sound = pick(moans)
+
+ // If the sound is repeated, get a new from a list without it.
+ if (lastmoan == sound)
+ sound = pick(LAZYCOPY(moans) - lastmoan)
+
+ playlewdinteractionsound(loc, sound, 80, 0, 0)
+ lastmoan = sound
/mob/living/proc/cum(mob/living/partner, target_orifice, cum_inside = FALSE, anonymous = FALSE) //SPLURT EDIT - extra argument `cum_inside` and 'anonymous'
if(HAS_TRAIT(src, TRAIT_NEVERBONER))
@@ -771,17 +788,48 @@
if(stat != CONSCIOUS)
return FALSE
+ var/datum/preferences/prefs = client?.prefs
+ var/use_arousal_multiplier = NULL_COALESCE(prefs?.use_arousal_multiplier, FALSE)
+ var/arousal_multiplier = NULL_COALESCE(prefs?.arousal_multiplier, 100)
+ var/use_moaning_multiplier = NULL_COALESCE(prefs?.use_moaning_multiplier, FALSE)
+ var/moaning_multiplier = NULL_COALESCE(prefs?.moaning_multiplier, 25)
+
if(amount)
- add_lust(amount)
+ if (use_arousal_multiplier)
+ add_lust(amount * (arousal_multiplier/100))
+ else
+ add_lust(amount)
+
+ if (use_moaning_multiplier)
+ if(prob(moaning_multiplier))
+ moan()
+
+ // Below is an overengineered bezier curve based chance of moaning.
+ /// The current lust (arousal) amount.
var/lust = get_lust()
+ /// The lust tolerance as defined in preferences.
var/lust_tolerance = get_lust_tolerance()
- if(lust >= lust_tolerance)
- if(prob(10))
+ /// The arousal limit upon which you climax.
+ var/climax = lust_tolerance * 3
+ /// Threshold where you start moaning.
+ var/threshold = climax/2
+ ///Calculation of 't' in bezier quadratic curve. It's a 0 to 1 version of threshold to climax.
+ var/t = percentage_between(lust, threshold, climax, FALSE)
+ // The Y axis value of the point in the bezier curve.
+ var/bezier = 2 * (1 - t) * t * 13.8 + ((t*t) * 100)
+ /// Probability chance resulting from bezier curve.
+ var/chance = clamp(round(bezier),0,100)
+
+ if (lust >= threshold)
+ if(prob(30))
to_chat(src, "You struggle to not orgasm!")
- moan()
- return FALSE
- if(lust >= (lust_tolerance * 3))
- if(cum(partner, orifice, cum_inside, anonymous)) //SPLURT EDIT - extra argument `cum_inside` and `anonymous`
+
+ if (!use_moaning_multiplier)
+ if(prob(chance))
+ moan()
+
+ if (lust > climax)
+ if (cum(partner, orifice, cum_inside, anonymous)) //SPLURT EDIT - extra argument `cum_inside` and `anonymous`
return TRUE
return FALSE
diff --git a/modular_sand/code/modules/client/preferences.dm b/modular_sand/code/modules/client/preferences.dm
index 6af55cb20a13..3bc14f3e50ed 100644
--- a/modular_sand/code/modules/client/preferences.dm
+++ b/modular_sand/code/modules/client/preferences.dm
@@ -1,6 +1,16 @@
/datum/preferences
+ /// My favorites! they show up in their own tab inside the ui.
var/list/favorite_interactions
+ /// Enable the 'arousal_multiplier' to be applied to lust amount
+ var/use_arousal_multiplier = FALSE
+ /// A separate arousal multiplier that the user has control of (although we could just tap into lust or replace it.)
+ var/arousal_multiplier = 100
+ /// Enable the 'moaning_multiplier' to be used as a % chance of moaning instead of default calculation.
+ var/use_moaning_multiplier = FALSE
+ /// Chance of moaning during an interaction
+ var/moaning_multiplier = 65
+
//SANDSTORM EDIT - extra language
/datum/preferences/proc/SetLanguage(mob/user)
var/list/dat = list()
diff --git a/modular_sand/code/modules/client/preferences_savefile.dm b/modular_sand/code/modules/client/preferences_savefile.dm
index d89f7df70aee..15bace80f341 100644
--- a/modular_sand/code/modules/client/preferences_savefile.dm
+++ b/modular_sand/code/modules/client/preferences_savefile.dm
@@ -29,13 +29,23 @@
. = ..()
if(!istype(., /savefile))
return FALSE
- WRITE_FILE(.["favorite_interactions"], favorite_interactions)
+ WRITE_FILE(.["favorite_interactions"], favorite_interactions)
+
+ WRITE_FILE(.["use_arousal_multiplier"], use_arousal_multiplier)
+ WRITE_FILE(.["arousal_multiplier"], arousal_multiplier)
+ WRITE_FILE(.["use_moaning_multiplier"], use_moaning_multiplier)
+ WRITE_FILE(.["moaning_multiplier"], moaning_multiplier)
/datum/preferences/load_preferences(bypass_cooldown)
. = ..()
if(!istype(., /savefile))
return FALSE
- .["favorite_interactions"] >> favorite_interactions
+ .["favorite_interactions"] >> favorite_interactions
+
+ .["use_arousal_multiplier"] >> use_arousal_multiplier
+ .["arousal_multiplier"] >> arousal_multiplier
+ .["use_moaning_multiplier"] >> use_moaning_multiplier
+ .["moaning_multiplier"] >> moaning_multiplier
favorite_interactions = SANITIZE_LIST(favorite_interactions)
@@ -47,3 +57,8 @@
if(!initial(interaction_path.description))
LAZYREMOVE(favorite_interactions, interaction)
continue
+
+ use_arousal_multiplier = sanitize_integer(use_arousal_multiplier, 0, 1, initial(use_arousal_multiplier))
+ arousal_multiplier = sanitize_integer(arousal_multiplier, 0, 300, initial(arousal_multiplier))
+ use_moaning_multiplier = sanitize_integer(use_moaning_multiplier, 0, 1, initial(use_moaning_multiplier))
+ moaning_multiplier = sanitize_integer(moaning_multiplier, 0, 100, initial(moaning_multiplier))
diff --git a/modular_sand/code/modules/mob/emote.dm b/modular_sand/code/modules/mob/emote.dm
index caa12f509bfb..5f555e705b5c 100644
--- a/modular_sand/code/modules/mob/emote.dm
+++ b/modular_sand/code/modules/mob/emote.dm
@@ -50,3 +50,16 @@
return
user.nextsoundemote = world.time + 7
playsound(user, 'modular_citadel/sound/voice/peep.ogg', 50, 1, -1)
+
+/datum/emote/living/carbon/moan
+ emote_type = EMOTE_OMNI
+ stat_allowed = CONSCIOUS
+
+/datum/emote/living/carbon/moan/run_emote(mob/living/user, params, type_override, intentional)
+ . = TRUE
+ if(!can_run_emote(user, TRUE, intentional))
+ return FALSE
+ if(!COOLDOWN_FINISHED(user, nextsoundemote))
+ return FALSE
+ COOLDOWN_START(user, nextsoundemote, 7)
+ user.moan()
diff --git a/modular_sand/sound/interactions/final_m1.ogg b/modular_sand/sound/interactions/final_m1.ogg
index 5f7bf5399395..6ef14a3d2d46 100644
Binary files a/modular_sand/sound/interactions/final_m1.ogg and b/modular_sand/sound/interactions/final_m1.ogg differ
diff --git a/modular_sand/sound/interactions/final_m2.ogg b/modular_sand/sound/interactions/final_m2.ogg
index 12ddb5d65bd1..128d5f933b82 100644
Binary files a/modular_sand/sound/interactions/final_m2.ogg and b/modular_sand/sound/interactions/final_m2.ogg differ
diff --git a/modular_sand/sound/interactions/final_m3.ogg b/modular_sand/sound/interactions/final_m3.ogg
index 148f6c46c3a0..b57d0f438288 100644
Binary files a/modular_sand/sound/interactions/final_m3.ogg and b/modular_sand/sound/interactions/final_m3.ogg differ
diff --git a/modular_sand/sound/interactions/final_m4.ogg b/modular_sand/sound/interactions/final_m4.ogg
index a81233409137..128d5f933b82 100644
Binary files a/modular_sand/sound/interactions/final_m4.ogg and b/modular_sand/sound/interactions/final_m4.ogg differ
diff --git a/modular_sand/sound/interactions/final_m5.ogg b/modular_sand/sound/interactions/final_m5.ogg
index 977d01e8ff5c..b57d0f438288 100644
Binary files a/modular_sand/sound/interactions/final_m5.ogg and b/modular_sand/sound/interactions/final_m5.ogg differ
diff --git a/modular_sand/sound/interactions/kiss1.ogg b/modular_sand/sound/interactions/kiss1.ogg
new file mode 100644
index 000000000000..f4bd73433837
Binary files /dev/null and b/modular_sand/sound/interactions/kiss1.ogg differ
diff --git a/modular_sand/sound/interactions/kiss2.ogg b/modular_sand/sound/interactions/kiss2.ogg
new file mode 100644
index 000000000000..18f12d6f04a9
Binary files /dev/null and b/modular_sand/sound/interactions/kiss2.ogg differ
diff --git a/modular_sand/sound/interactions/kiss3.ogg b/modular_sand/sound/interactions/kiss3.ogg
new file mode 100644
index 000000000000..0f89617f002b
Binary files /dev/null and b/modular_sand/sound/interactions/kiss3.ogg differ
diff --git a/modular_sand/sound/interactions/kiss4.ogg b/modular_sand/sound/interactions/kiss4.ogg
new file mode 100644
index 000000000000..a7c47dd8af7b
Binary files /dev/null and b/modular_sand/sound/interactions/kiss4.ogg differ
diff --git a/modular_sand/sound/interactions/kiss5.ogg b/modular_sand/sound/interactions/kiss5.ogg
new file mode 100644
index 000000000000..31a48c4d6227
Binary files /dev/null and b/modular_sand/sound/interactions/kiss5.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f1.ogg b/modular_sand/sound/interactions/moan_f1.ogg
index 836ecee5f8d0..5f1ceff6fed6 100644
Binary files a/modular_sand/sound/interactions/moan_f1.ogg and b/modular_sand/sound/interactions/moan_f1.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f2.ogg b/modular_sand/sound/interactions/moan_f2.ogg
index fd2f26723607..22160295fc69 100644
Binary files a/modular_sand/sound/interactions/moan_f2.ogg and b/modular_sand/sound/interactions/moan_f2.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f3.ogg b/modular_sand/sound/interactions/moan_f3.ogg
index 7e3a35b4462e..9654b020e923 100644
Binary files a/modular_sand/sound/interactions/moan_f3.ogg and b/modular_sand/sound/interactions/moan_f3.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f4.ogg b/modular_sand/sound/interactions/moan_f4.ogg
index 71ac8c9b8553..6fcb314058f3 100644
Binary files a/modular_sand/sound/interactions/moan_f4.ogg and b/modular_sand/sound/interactions/moan_f4.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f5.ogg b/modular_sand/sound/interactions/moan_f5.ogg
index 8e3396a4ac6d..7b3831961082 100644
Binary files a/modular_sand/sound/interactions/moan_f5.ogg and b/modular_sand/sound/interactions/moan_f5.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f6.ogg b/modular_sand/sound/interactions/moan_f6.ogg
index cf6f12900495..c3b368e3a8b9 100644
Binary files a/modular_sand/sound/interactions/moan_f6.ogg and b/modular_sand/sound/interactions/moan_f6.ogg differ
diff --git a/modular_sand/sound/interactions/moan_f7.ogg b/modular_sand/sound/interactions/moan_f7.ogg
index 9eb7f7364318..09d3bb3fafba 100644
Binary files a/modular_sand/sound/interactions/moan_f7.ogg and b/modular_sand/sound/interactions/moan_f7.ogg differ
diff --git a/modular_sand/sound/interactions/moan_m1.ogg b/modular_sand/sound/interactions/moan_m1.ogg
index 93e6d1410cdd..6ef14a3d2d46 100644
Binary files a/modular_sand/sound/interactions/moan_m1.ogg and b/modular_sand/sound/interactions/moan_m1.ogg differ
diff --git a/modular_sand/sound/interactions/moan_m2.ogg b/modular_sand/sound/interactions/moan_m2.ogg
index 3bae5e073c67..128d5f933b82 100644
Binary files a/modular_sand/sound/interactions/moan_m2.ogg and b/modular_sand/sound/interactions/moan_m2.ogg differ
diff --git a/modular_sand/sound/interactions/moan_m3.ogg b/modular_sand/sound/interactions/moan_m3.ogg
index a37eefe4cd8f..b57d0f438288 100644
Binary files a/modular_sand/sound/interactions/moan_m3.ogg and b/modular_sand/sound/interactions/moan_m3.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index c08951ccf0eb..1f01505064fe 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -275,6 +275,7 @@
#include "code\__SANDCODE\DEFINES\dcs\signals\lewd.dm"
#include "code\__SANDCODE\DEFINES\dcs\signals\signals_mob_main.dm"
#include "code\__SANDCODE\DEFINES\dcs\signals\sizecode.dm"
+#include "code\__SANDCODE\HELPERS\math.dm"
#include "code\__SANDCODE\HELPERS\silicon.dm"
#include "code\__SANDCODE\HELPERS\sizecode.dm"
#include "code\__SPLURTCODE\DEFINES\access.dm"
diff --git a/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx b/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx
index d17cbbbf4362..a5ecc83cf5f4 100644
--- a/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx
+++ b/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx
@@ -1,5 +1,5 @@
import { useBackend } from '../../backend';
-import { BlockQuote, Icon, ProgressBar, Section, Stack } from '../../components';
+import { BlockQuote, Button, Icon, ProgressBar, Section, Stack, Slider, Tooltip } from '../../components';
type HeaderInfo = {
isTargetSelf: boolean;
@@ -10,6 +10,12 @@ type HeaderInfo = {
theirAttributes: string[];
theirLust: number;
theirMaxLust: number;
+
+ // Arousal prefs stuff
+ use_arousal_multiplier: boolean;
+ arousal_multiplier: number;
+ use_moaning_multiplier: boolean;
+ moaning_multiplier: number;
}
export const InfoSection = (props, context) => {
@@ -23,6 +29,12 @@ export const InfoSection = (props, context) => {
theirAttributes,
theirLust,
theirMaxLust,
+
+ // Arousal prefs stuff
+ use_arousal_multiplier,
+ arousal_multiplier,
+ use_moaning_multiplier,
+ moaning_multiplier,
} = data;
return (
@@ -67,6 +79,80 @@ export const InfoSection = (props, context) => {
) : (null))}
+
+
+
+
+
+
+
+ {(!!use_arousal_multiplier && (
+
+
+ act("pref", { pref: 'arousal_multiplier', amount: value })}
+ />
+
+
+ ))}
+
+
+
+
+
+
+
+ {(!!use_moaning_multiplier && (
+
+
+ act("pref", { pref: 'moaning_multiplier', amount: value })}
+ />
+
+
+ ))}
+
+
+
+
+
);
diff --git a/tgui/packages/tgui/interfaces/MobInteraction/index.tsx b/tgui/packages/tgui/interfaces/MobInteraction/index.tsx
index 2bfbbed3b0c9..920be3796da1 100644
--- a/tgui/packages/tgui/interfaces/MobInteraction/index.tsx
+++ b/tgui/packages/tgui/interfaces/MobInteraction/index.tsx
@@ -11,7 +11,7 @@ export const MobInteraction = () => {
resizable>
-
+