Merge pull request #2308 from ktccd/Masturbation-Stuff

Male masturbation fix, forced orgasm, ejaculation in partner and aphro+/anaphro+ changes.
This commit is contained in:
LetterJay
2017-08-09 02:21:48 -05:00
committed by GitHub
9 changed files with 155 additions and 51 deletions
+129 -31
View File
@@ -6,7 +6,7 @@
var/arousal_rate = 1 //The base rate that arousal will increase in this mob.
var/arousal_loss_rate = 1 //How easily arousal can be relieved for this mob.
var/canbearoused = FALSE //Mob-level disabler for arousal. Starts off and can be enabled as features are added for different mob types.
var/mb_cd_length = 50 //5 second cooldown for masturbating because fuck spam
var/mb_cd_length = 100 //5 second cooldown for masturbating because fuck spam.
var/mb_cd_timer = 0 //The timer itself
/mob/living/carbon/human
@@ -150,14 +150,14 @@
return 0
var/mob/living/M = usr
if(M.canbearoused)
M.mob_masturbate()
M.mob_climax()
return 1
else
M << "<span class='warning'>Arousal is disabled. Feature is unavailable.</span>"
to_chat(M, "<span class='warning'>Arousal is disabled. Feature is unavailable.</span>")
/mob/living/proc/mob_masturbate()//This is just so I can test this shit without being forced to add actual content to get rid of arousal. Will be a very basic proc for a while.
/mob/living/proc/mob_climax()//This is just so I can test this shit without being forced to add actual content to get rid of arousal. Will be a very basic proc for a while.
set name = "Masturbate"
set category = "IC"
if(canbearoused && !restrained() && !stat)
@@ -179,45 +179,93 @@
PoolOrNew(/obj/effect/decal/cleanable/femcum, loc)
*/
else
src << "<span class='notice'>You aren't aroused enough for that.</span>"
to_chat(src, "<span class='notice'>You aren't aroused enough for that.</span>")
/mob/living/carbon/human/mob_masturbate()
/mob/living/carbon/human/mob_climax(forced_climax=FALSE) //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints
if(mb_cd_timer > world.time)
src << "<span class='warning'>You need to wait [round((mb_cd_timer - world.time)/(20))] seconds before you can do that again!</span>"
if(!forced_climax) //Don't spam the message to the victim if forced to come too fast
to_chat(src, "<span class='warning'>You need to wait [round((mb_cd_timer - world.time)/(20))] seconds before you can do that again!</span>")
return
mb_cd_timer = (world.time + mb_cd_length)
var/list/genitals_list = list()
var/obj/item/organ/genital/SG = null//originally selected_genital
var/list/containers_list = list()
var/obj/item/weapon/reagent_containers/SC = null
var/datum/reagents/fluid_source = null
var/into_container = 0
var/arms = get_num_arms()
var/free_hands = arms
var/free_hands = get_num_arms() //arms was only used to know if we had ANY at all
var/total_cum = 0
var/finished = 0
var/mb_time = 30
mb_cd_timer = (world.time + mb_cd_length)
if(canbearoused && has_dna())
if(restrained())
src << "<span class='warning'>You can't do that while restrained!</span>"
if(stat==2)
to_chat(src, "<span class='warning'>You can't do that while dead!</span>")
return
if(stat)
src << "<span class='warning'>You must be conscious to do that!</span>"
if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks
for(var/obj/item/organ/genital/G in internal_organs)
if(G.can_masturbate_with) //All capable genitals will orgasm with this
var/unable_to_come = FALSE
switch(G.type)
if(/obj/item/organ/genital/penis)
var/obj/item/organ/genital/penis/P = G
if(!P.linked_balls)
unable_to_come = TRUE
else
fluid_source = P.linked_balls.reagents
if(/obj/item/organ/genital/vagina)
var/obj/item/organ/genital/vagina/V = G
if(!V.linked_womb)
unable_to_come = TRUE
else
fluid_source = V.linked_womb.reagents
else //Weird, undefined genitalia behaviour
unable_to_come = TRUE
if(unable_to_come)
src.visible_message("<span class='danger'>[src] shudders, their [G.name] unable to cum.</span>", \
"<span class='userdanger'>Your [G.name] cannot cum, giving no relief.</span>", \
"<span class='userdanger'>Your [G.name] cannot cum, giving no relief.</span>")
else
if(fluid_source)
total_cum = fluid_source.total_volume
src.visible_message("<span class='danger'>[src] looks like they're about to cum.</span>", \
"<span class='green'>You feel yourself about to orgasm.</span>", \
"<span class='green'>You feel yourself about to orgasm.</span>")
if(do_after(src, mb_time, target = src))
if(total_cum > 5)
fluid_source.reaction(src.loc, TOUCH, 1, 0)
fluid_source.clear_reagents()
fluid_source = null //cleanup so this can be used for the next genitalia
src.visible_message("<span class='danger'>[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!</span>", \
"<span class='green'>You're forced to cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""] with your [G].</span>", \
"<span class='green'>Your [G] have been forced to climax.</span>")
finished = 1
if(finished)
setArousalLoss(min_arousal)
return //Do not proceed to masturbating if all genitals have been forced to orgasm.
if(stat==1) //Sleeping people can be forced chemically or with electrical stimulants, for example.
to_chat(src, "<span class='warning'>You must be conscious to do that!</span>")
return
if(restrained())
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
return
if(getArousalLoss() < 33)//flat number instead of percentage
src << "<span class='warning'>You aren't aroused enough for that!</span>"
to_chat(src, "<span class='warning'>You aren't aroused enough for that!</span>")
return
if(!is_groin_exposed())
src << "<span class='warning'>You need to undress, first!</span>"
to_chat(src, "<span class='warning'>You need to undress, first!</span>")
return
if(!arms)
src << "<span class='warning'>You need at least one arm.</span>"
if(!free_hands)
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
return
for(var/helditem in held_items)//how many hands are free
if(isobj(helditem))
free_hands--
if(free_hands <= 0)
src << "<span class='warning'>You need at least one free hand.</span>"
to_chat(src, "<span class='warning'>You need at least one free hand.</span>")
return
for(var/obj/item/organ/genital/G in internal_organs)
if(G.can_masturbate_with)//filter out what you can't masturbate with
@@ -240,12 +288,12 @@
if(/obj/item/organ/genital/penis)
var/obj/item/organ/genital/penis/P = SG
if(!P.linked_balls)
src << "<span class='warning'>Grow a pair!</span>"
to_chat(src, "<span class='warning'>You need a pair of testicles to do this.</span>")
return
fluid_source = P.linked_balls.reagents
total_cum = fluid_source.total_volume
if(into_container)//into a glass or beaker or whatever
src.visible_message("<span class='danger'>[src] starts [pick("jerking off","stroking")] their [SG] over [SC].</span>", \
src.visible_message("<span class='danger'>[src] starts [pick("jerking off","stroking")] their [SG.name] over [SC].</span>", \
"<span class='userdanger'>You start jerking off over [SC.name].</span>", \
"<span class='userdanger'>You start masturbating.</span>")
if(do_after(src, mb_time, target = src) && in_range(src, SC))
@@ -254,16 +302,71 @@
"<span class='green'>You cum into [SC].</span>", \
"<span class='green'>You have relieved yourself.</span>")
finished = 1
else //Not in a container
if(src.pulling)
if(iscarbon(src.pulling))
var/mob/living/carbon/C = src.pulling
if(!C.is_groin_exposed())
to_chat(src, "<span class='warning'>You must undress someone to climax inside them.</span>")
return
if(isliving(src.pulling)) //Gotta be alive to fuck it, don't wanna have to code fucking objects that ain't containers...
var/mob/living/partner = src.pulling
src.visible_message("[src] is about to climax inside [partner]!", \
"You're about to climax inside [partner]!", \
"<span class='danger'>You're preparing to climax inside someone!</span>")
switch(grab_state)
if(GRAB_PASSIVE)
if(do_after(src, mb_time, target = src) && in_range(src, partner))
var/spillage = 0.5 //Leaks a bit on passive grab
var/did_spill = FALSE
fluid_source.trans_to(partner, total_cum*(1-spillage))
total_cum = total_cum*spillage
if(total_cum > 5)
fluid_source.reaction(partner.loc, TOUCH, 1, 0)
did_spill = TRUE
fluid_source.clear_reagents()
src.visible_message("<span class='danger'>[src] ejaculates inside [partner][did_spill ? ", overflowing and spilling":""]!</span>", \
"<span class='green'>You ejaculate inside [partner][did_spill ? ", spilling out of them":""].</span>", \
"<span class='green'>You have climaxed inside someone[did_spill ? ", spilling out of them":""].</span>")
finished = 1
else //Aggressive or higher
if(do_after(src, mb_time, target = src) && in_range(src, partner))
var/spillage = 0.0 //Leakproofing seals
fluid_source.trans_to(partner, total_cum*(1-spillage))
total_cum = total_cum*spillage
if(total_cum > 5)
fluid_source.reaction(partner.loc, TOUCH, 1, 0)
fluid_source.clear_reagents()
src.visible_message("<span class='danger'>[src] ejaculates inside [partner], spilling nothing!</span>", \
"<span class='green'>You ejaculate inside [partner], spilling nothing.</span>", \
"<span class='green'>You have climaxed inside someone, spilling nothing.</span>")
finished = 1
//Don't care, not coding you fucking a unanchored girder
else //No pulling, or pulling non-living things
src.visible_message("<span class='danger'>[src] starts [pick("jerking off","stroking")] their [SG].</span>", \
"<span class='green'>You start masturbating.</span>", \
"<span class='green'>You start masturbating.</span>")
if(do_after(src, mb_time, target = src))
if(total_cum > 5)
fluid_source.reaction(src.loc, TOUCH, 1, 0)
fluid_source.clear_reagents()
src.visible_message("<span class='danger'>[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!</span>", \
"<span class='green'>You cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""].</span>", \
"<span class='green'>You have relieved yourself.</span>")
finished = 1
if(/obj/item/organ/genital/vagina)
var/obj/item/organ/genital/vagina/V = SG
if(!V.linked_womb)
src << "<span class='warning'>No womb!</span>"
to_chat(src, "<span class='warning'>You need a womb to do this.</span>")
return
fluid_source = V.linked_womb.reagents
total_cum = fluid_source.total_volume
if(into_container)//into a glass or beaker or whatever
src.visible_message("<span class='danger'>[src] starts fingering their vagina over [SC].</span>", \
src.visible_message("<span class='danger'>[src] starts fingering their [SG.name] over [SC].</span>", \
"<span class='userdanger'>You start fingering over [SC.name].</span>", \
"<span class='userdanger'>You start masturbating.</span>")
if(do_after(src, mb_time, target = src) && in_range(src, SC))
@@ -272,7 +375,7 @@
"<span class='green'>You cum into [SC].</span>", \
"<span class='green'>You have relieved yourself.</span>")
finished = 1
else//not into a container
src.visible_message("<span class='danger'>[src] starts fingering their vagina.</span>", \
"<span class='userdanger'>You start fingering your vagina.</span>", \
@@ -297,10 +400,5 @@
setArousalLoss(min_arousal)
else
src << "<span class='warning'>You have no genitals!</span>"
to_chat(src, "<span class='warning'>You have no genitals!</span>")
return
/mob/living/carbon/proc/force_orgasm(intensity)
if(canbearoused && has_dna() && (has_penis() || has_vagina()))
return 1
return 0
+18 -12
View File
@@ -105,7 +105,7 @@
M.emote(pick("moan","blush"))
if(prob(5))
var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.")
M << "<span class='love'>[aroused_message]</span>"
to_chat(M, "<span class='love'>[aroused_message]</span>")
..()
/datum/reagent/aphrodisiacplus
@@ -128,15 +128,13 @@
else
M.emote(pick("moan","blush"))
if(prob(5))
var/aroused_message
if(M.getArousalLoss() > 90)
var/aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
M << "<span class='love'>[aroused_message]</span>"
aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
else
var/aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.")
M << "<span class='love'>[aroused_message]</span>"
// if(iscarbon(M) && has_dna(M))
// M.force_ejaculation()
..()
aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.")
to_chat(M, "<span class='love'>[aroused_message]</span>")
/datum/reagent/aphrodisiacplus/addiction_act_stage2(mob/living/M)
if(prob(30))
M.adjustBrainLoss(2)
@@ -152,11 +150,17 @@
..()
/datum/reagent/aphrodisiacplus/overdose_process(mob/living/M)
if(prob(66))
if(prob(33))
if(M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna())
var/mob/living/carbon/human/H = M
to_chat(H, "<span class='love'>Your libido is going haywire!</span>")
H.mob_climax(forced_climax=TRUE)
if(M.min_arousal < 50)
M.min_arousal += 1
if(M.max_arousal < 200)
M.max_arousal += 1
to_chat(M, "<span class='love'>You're having a hard time thinkin about things other than sex!</span>")
if(M.min_arousal < M.max_arousal)
M.min_arousal += 1
to_chat(M, "<span class='love'>You feel your libido permanently increasing.</span>")
M.adjustArousalLoss(2)
..()
@@ -193,8 +197,10 @@
if(prob(33))
if(M.min_arousal > 0)
M.min_arousal -= 1
if(M.max_arousal > 75)
to_chat(M, "<span class='notice'>You feel your libido returning to more normal levels.</span>")
if(M.min_arousal > 50)
M.min_arousal -= 1
to_chat(M, "<span class='notice'>You feel like your overactive libido is calming down.</span>")
M.adjustArousalLoss(-2)
..()
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/breasts
name = "breasts"
name = "Breasts"
desc = "Female milk producing organs."
icon_state = "breasts"
icon = 'code/citadel/icons/breasts.dmi'
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/eggsack
name = "egg sack"
name = "Egg sack"
desc = "An egg producing reproductive organ."
icon_state = "egg_sack"
icon = 'code/citadel/icons/ovipositor.dmi'
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/ovipositor
name = "ovipositor"
name = "Ovipositor"
desc = "An egg laying reproductive organ."
icon_state = "ovi_knotted_2"
icon = 'code/citadel/icons/ovipositor.dmi'
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/penis
name = "penis"
name = "Penis"
desc = "A male reproductive organ."
icon_state = "penis"
icon = 'code/citadel/icons/penis.dmi'
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/testicles
name = "testicles"
name = "Testicles"
desc = "A male reproductive organ."
icon_state = "testicles"
icon = 'code/citadel/icons/penis.dmi'
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/vagina
name = "vagina"
name = "Vagina"
desc = "A female reproductive organ."
icon = 'code/citadel/icons/vagina.dmi'
icon_state = "vagina"
+2 -2
View File
@@ -1,5 +1,5 @@
/obj/item/organ/genital/womb
name = "womb"
name = "Womb"
desc = "A female reproductive organ."
icon = 'code/citadel/icons/vagina.dmi'
icon_state = "womb"
@@ -10,7 +10,7 @@
fluid_id = "femcum"
producing = TRUE
var/obj/item/organ/genital/vagina/linked_vag
/obj/item/organ/genital/womb/Initialize()
. = ..()
reagents.add_reagent(fluid_id, fluid_max_volume)