diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 4b8a66423d..2cba494ed8 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -163,6 +163,8 @@
#define TRAIT_MUSICIAN "musician"
#define TRAIT_PERMABONER "permanent_arousal"
#define TRAIT_NEVERBONER "never_aroused"
+#define TRAIT_NYMPHO "nymphomania"
+#define TRAIT_MASO "masochism"
#define TRAIT_HIGH_BLOOD "high_blood"
#define TRAIT_PARA "paraplegic"
#define TRAIT_EMPATH "empath"
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index a241da9be8..ab2a69e7e9 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -88,6 +88,22 @@
if(quirk_holder)
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
+/datum/quirk/libido
+ name = "Nymphomania"
+ desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
+ value = 0
+ mob_trait = TRAIT_PERMABONER
+ gain_text = "You are feeling extra wild."
+ lose_text = "You don't feel that burning sensation anymore."
+
+/datum/quirk/maso
+ name = "Masochism"
+ desc = "You are aroused by pain."
+ value = 0
+ mob_trait = TRAIT_MASO
+ gain_text = "You desire to be hurt."
+ lose_text = "Pain has become less exciting for you."
+
/datum/quirk/alcohol_intolerance
name = "Alcohol Intolerance"
desc = "You take toxin damage from alcohol rather than getting drunk."
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index a8603a2a41..8a38f71076 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1582,6 +1582,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
)
user.do_attack_animation(target, ATTACK_EFFECT_FACE_SLAP)
user.adjustStaminaLossBuffered(3)
+ if (!HAS_TRAIT(target, TRAIT_PERMABONER))
+ stop_wagging_tail(target)
return FALSE
else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
if(target.client?.prefs.cit_toggles & NO_ASS_SLAP)
@@ -1589,6 +1591,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return FALSE
user.do_attack_animation(target, ATTACK_EFFECT_ASS_SLAP)
user.adjustStaminaLossBuffered(3)
+ target.adjust_arousal(20,maso = TRUE)
+ if (ishuman(target) && HAS_TRAIT(target, TRAIT_MASO) && target.has_dna() && prob(10))
+ target.mob_climax(forced_climax=TRUE)
+ if (!HAS_TRAIT(target, TRAIT_PERMABONER))
+ stop_wagging_tail(target)
playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1)
user.visible_message(\
"\The [user] slaps \the [target]'s ass!",\
@@ -1947,6 +1954,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(BP)
if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0))
H.update_damage_overlays()
+ if(HAS_TRAIT(H, TRAIT_MASO) && prob(damage_amount))
+ H.mob_climax(forced_climax=TRUE)
else//no bodypart, we deal damage with a more general method.
H.adjustBruteLoss(damage_amount)
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index ba4fe4909e..5403da93b3 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -966,14 +966,12 @@
M.emote("nya")
if(prob(20))
to_chat(M, "[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]")
- if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(5))
- for(var/obj/item/organ/genital/G in M.internal_organs)
- if(!G.aroused_state && prob(5*G.sensitivity))
- G.set_aroused_state(TRUE)
- G.update_appearance()
- if(G.aroused_state)
- to_chat(M, "You feel like playing with your [G.name]!")
-
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/list/adjusted = H.adjust_arousal(5,aphro = TRUE)
+ for(var/g in adjusted)
+ var/obj/item/organ/genital/G = g
+ to_chat(M, "You feel like playing with your [G.name]!")
..()
/datum/reagent/consumable/monkey_energy
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index a39746519a..894e48f5c2 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -2280,12 +2280,11 @@
M.emote("nya")
if(prob(20))
to_chat(M, "[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]")
- if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO && ishuman(M)))
+ if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/genital/G in H.internal_organs)
- if(!G.aroused_state && prob(2*G.sensitivity))
- G.set_aroused_state(TRUE)
- G.update_appearance()
- if(G.aroused_state)
- to_chat(M, "You feel like playing with your [G.name]!")
+ var/list/adjusted = H.adjust_arousal(2,aphro = TRUE)
+ for(var/g in adjusted)
+ var/obj/item/organ/genital/G = g
+ to_chat(M, "You feel like playing with your [G.name]!")
+
..()
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 7df7421c69..6dc1d1b6ce 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -822,6 +822,10 @@
continue
if (E.lewd)
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[E.enthrallGender] has praised me!!"), 5)
+ if(HAS_TRAIT(L, TRAIT_MASO))
+ E.enthrallTally -= power_multiplier
+ E.resistanceTally += power_multiplier
+ E.cooldown += 1
else
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've been praised for doing a good job!"), 5)
E.resistanceTally -= power_multiplier
@@ -839,7 +843,16 @@
if(L == user)
continue
if (E.lewd)
- addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've let [E.enthrallGender] down..."), 5)
+ if(HAS_TRAIT(L, TRAIT_MASO))
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ H.adjust_arousal(3*power_multiplier,maso = TRUE)
+ descmessage += "And yet, it feels so good..!" //I don't really understand masco, is this the right sort of thing they like?
+ E.enthrallTally += power_multiplier
+ E.resistanceTally -= power_multiplier
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've let [E.enthrallGender] down...!"), 5)
+ else
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've let [E.enthrallGender] down..."), 5)
else
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've failed [E.master]..."), 5)
E.resistanceTally += power_multiplier
diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm
index 4e43b6a8b7..fec807bef3 100644
--- a/modular_citadel/code/datums/status_effects/chems.dm
+++ b/modular_citadel/code/datums/status_effects/chems.dm
@@ -633,6 +633,9 @@
//Shocking truth!
else if (lowertext(customTriggers[trigger]) == "shock")
+ if (lewd && ishuman(C))
+ var/mob/living/carbon/human/H = C
+ H.adjust_arousal(5)
C.jitteriness += 100
C.stuttering += 25
C.Knockdown(60)
diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm
index 5f58121fd4..818c5c7b1e 100644
--- a/modular_citadel/code/modules/arousal/arousal.dm
+++ b/modular_citadel/code/modules/arousal/arousal.dm
@@ -41,6 +41,27 @@
update_body()
+
+/mob/living/carbon/human/proc/adjust_arousal(strength,aphro = FALSE,maso = FALSE) // returns all genitals that were adjust
+ var/list/obj/item/organ/genital/genit_list = list()
+ if(!client?.prefs.arousable || (aphro && (client?.prefs.cit_toggles & NO_APHRO)) || (maso && !HAS_TRAIT(src, TRAIT_MASO)))
+ return // no adjusting made here
+ if(strength>0)
+ for(var/obj/item/organ/genital/G in internal_organs)
+ if(!G.aroused_state && prob(strength*G.sensitivity))
+ G.set_aroused_state(TRUE)
+ G.update_appearance()
+ if(G.aroused_state)
+ genit_list += G
+ else
+ for(var/obj/item/organ/genital/G in internal_organs)
+ if(G.aroused_state && prob(strength*G.sensitivity))
+ G.set_aroused_state(FALSE)
+ G.update_appearance()
+ if(G.aroused_state)
+ genit_list += G
+ return genit_list
+
/obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found.
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
. = reagents
diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
index 9ec1c8b010..cbe2591528 100644
--- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
+++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
@@ -108,12 +108,10 @@
to_chat(M, "[aroused_message]")
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/genital/G in H.internal_organs)
- if(!G.aroused_state && prob(current_cycle*G.sensitivity))
- G.set_aroused_state(TRUE)
- G.update_appearance()
- if(G.aroused_state)
- to_chat(M, "[G.arousal_verb]!")
+ var/list/genits = H.adjust_arousal(current_cycle, aphro = TRUE) // redundant but should still be here
+ for(var/g in genits)
+ var/obj/item/organ/genital/G = g
+ to_chat(M, "[G.arousal_verb]!")
..()
/datum/reagent/drug/aphrodisiacplus
@@ -144,12 +142,10 @@
REMOVE_TRAIT(M,TRAIT_NEVERBONER,"aphro")
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/genital/G in H.internal_organs)
- if(!G.aroused_state)
- G.set_aroused_state(TRUE)
- G.update_appearance()
- if(G.aroused_state)
- to_chat(M, "[G.arousal_verb]!")
+ var/list/genits = H.adjust_arousal(100, aphro = TRUE) // redundant but should still be here
+ for(var/g in genits)
+ var/obj/item/organ/genital/G = g
+ to_chat(M, "[G.arousal_verb]!")
..()
/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M)
@@ -169,9 +165,9 @@
/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M)
if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33))
if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION))
- if(!HAS_TRAIT(M,TRAIT_PERMABONER)) //Less spam
+ if(!HAS_TRAIT(M,TRAIT_PERMABONER))
to_chat(M, "Your libido is going haywire!")
- ADD_TRAIT(M,TRAIT_PERMABONER,"aphro")
+ ADD_TRAIT(M,TRAIT_PERMABONER,"aphro")
..()
/datum/reagent/drug/anaphrodisiac
@@ -187,14 +183,9 @@
/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M)
if(M && M.client?.prefs.arousable && prob(16))
if(ishuman(M))
- var/unboner = FALSE
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/genital/G in H.internal_organs)
- if(G.aroused_state)
- G.set_aroused_state(FALSE)
- G.update_appearance()
- unboner = (G.aroused_state == FALSE)
- if(unboner)
+ var/list/genits = H.adjust_arousal(-100, aphro = TRUE)
+ if(genits.len)
to_chat(M, "You no longer feel aroused.")
..()
@@ -211,19 +202,16 @@
if(M && M.client?.prefs.arousable)
REMOVE_TRAIT(M,TRAIT_PERMABONER,"aphro")
if(ishuman(M))
- var/unboner = FALSE
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/genital/G in H.internal_organs)
- if(G.aroused_state)
- G.set_aroused_state(FALSE)
- G.update_appearance()
- unboner = (G.aroused_state == FALSE)
- if(unboner)
+ var/list/genits = H.adjust_arousal(-100, aphro = TRUE)
+ if(genits.len)
to_chat(M, "You no longer feel aroused.")
+
..()
/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M)
if(M && M.client?.prefs.arousable && prob(5))
+ to_chat(M, "You feel like you'll never feel aroused again...")
ADD_TRAIT(M,TRAIT_NEVERBONER,"aphro")
..()