diff --git a/code/citadel/cit_arousal.dm b/code/citadel/cit_arousal.dm index 12245c05d5..cf47dab1da 100644 --- a/code/citadel/cit_arousal.dm +++ b/code/citadel/cit_arousal.dm @@ -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 << "Arousal is disabled. Feature is unavailable." + to_chat(M, "Arousal is disabled. Feature is unavailable.") -/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 << "You aren't aroused enough for that." + to_chat(src, "You aren't aroused enough for that.") -/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 << "You need to wait [round((mb_cd_timer - world.time)/(20))] seconds before you can do that again!" + if(!forced_climax) //Don't spam the message to the victim if forced to come too fast + to_chat(src, "You need to wait [round((mb_cd_timer - world.time)/(20))] seconds before you can do that again!") 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 << "You can't do that while restrained!" + if(stat==2) + to_chat(src, "You can't do that while dead!") return - if(stat) - src << "You must be conscious to do that!" + 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("[src] shudders, their [G.name] unable to cum.", \ + "Your [G.name] cannot cum, giving no relief.", \ + "Your [G.name] cannot cum, giving no relief.") + else + if(fluid_source) + total_cum = fluid_source.total_volume + src.visible_message("[src] looks like they're about to cum.", \ + "You feel yourself about to orgasm.", \ + "You feel yourself about to orgasm.") + 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("[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!", \ + "You're forced to cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""] with your [G].", \ + "Your [G] have been forced to climax.") + 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, "You must be conscious to do that!") + return + if(restrained()) + to_chat(src, "You can't do that while restrained!") return if(getArousalLoss() < 33)//flat number instead of percentage - src << "You aren't aroused enough for that!" + to_chat(src, "You aren't aroused enough for that!") return if(!is_groin_exposed()) - src << "You need to undress, first!" + to_chat(src, "You need to undress, first!") return - if(!arms) - src << "You need at least one arm." + if(!free_hands) + to_chat(src, "You need at least one free arm.") return for(var/helditem in held_items)//how many hands are free if(isobj(helditem)) free_hands-- if(free_hands <= 0) - src << "You need at least one free hand." + to_chat(src, "You need at least one free hand.") 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 << "Grow a pair!" + to_chat(src, "You need a pair of testicles to do this.") 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("[src] starts [pick("jerking off","stroking")] their [SG] over [SC].", \ + src.visible_message("[src] starts [pick("jerking off","stroking")] their [SG.name] over [SC].", \ "You start jerking off over [SC.name].", \ "You start masturbating.") if(do_after(src, mb_time, target = src) && in_range(src, SC)) @@ -254,16 +302,71 @@ "You cum into [SC].", \ "You have relieved yourself.") 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, "You must undress someone to climax inside them.") + 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]!", \ + "You're preparing to climax inside someone!") + 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("[src] ejaculates inside [partner][did_spill ? ", overflowing and spilling":""]!", \ + "You ejaculate inside [partner][did_spill ? ", spilling out of them":""].", \ + "You have climaxed inside someone[did_spill ? ", spilling out of them":""].") + 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("[src] ejaculates inside [partner], spilling nothing!", \ + "You ejaculate inside [partner], spilling nothing.", \ + "You have climaxed inside someone, spilling nothing.") + finished = 1 + //Don't care, not coding you fucking a unanchored girder + else //No pulling, or pulling non-living things + src.visible_message("[src] starts [pick("jerking off","stroking")] their [SG].", \ + "You start masturbating.", \ + "You start masturbating.") + 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("[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!", \ + "You cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""].", \ + "You have relieved yourself.") + finished = 1 + if(/obj/item/organ/genital/vagina) var/obj/item/organ/genital/vagina/V = SG if(!V.linked_womb) - src << "No womb!" + to_chat(src, "You need a womb to do this.") 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("[src] starts fingering their vagina over [SC].", \ + src.visible_message("[src] starts fingering their [SG.name] over [SC].", \ "You start fingering over [SC.name].", \ "You start masturbating.") if(do_after(src, mb_time, target = src) && in_range(src, SC)) @@ -272,7 +375,7 @@ "You cum into [SC].", \ "You have relieved yourself.") finished = 1 - + else//not into a container src.visible_message("[src] starts fingering their vagina.", \ "You start fingering your vagina.", \ @@ -297,10 +400,5 @@ setArousalLoss(min_arousal) else - src << "You have no genitals!" + to_chat(src, "You have no genitals!") return - -/mob/living/carbon/proc/force_orgasm(intensity) - if(canbearoused && has_dna() && (has_penis() || has_vagina())) - return 1 - return 0 diff --git a/code/citadel/cit_reagents.dm b/code/citadel/cit_reagents.dm index 2f421542ae..428729d30f 100644 --- a/code/citadel/cit_reagents.dm +++ b/code/citadel/cit_reagents.dm @@ -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 << "[aroused_message]" + to_chat(M, "[aroused_message]") ..() /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 << "[aroused_message]" + 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 << "[aroused_message]" -// 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, "[aroused_message]") + /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, "Your libido is going haywire!") + 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, "You're having a hard time thinkin about things other than sex!") + if(M.min_arousal < M.max_arousal) + M.min_arousal += 1 + to_chat(M, "You feel your libido permanently increasing.") 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, "You feel your libido returning to more normal levels.") + if(M.min_arousal > 50) M.min_arousal -= 1 + to_chat(M, "You feel like your overactive libido is calming down.") M.adjustArousalLoss(-2) ..() diff --git a/code/citadel/organs/breasts.dm b/code/citadel/organs/breasts.dm index 5e3f312199..ce45b88cfb 100644 --- a/code/citadel/organs/breasts.dm +++ b/code/citadel/organs/breasts.dm @@ -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' diff --git a/code/citadel/organs/eggsack.dm b/code/citadel/organs/eggsack.dm index 1e53240e1a..718a353b87 100644 --- a/code/citadel/organs/eggsack.dm +++ b/code/citadel/organs/eggsack.dm @@ -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' diff --git a/code/citadel/organs/ovipositor.dm b/code/citadel/organs/ovipositor.dm index 9e46cff91c..3d684ee387 100644 --- a/code/citadel/organs/ovipositor.dm +++ b/code/citadel/organs/ovipositor.dm @@ -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' diff --git a/code/citadel/organs/penis.dm b/code/citadel/organs/penis.dm index 3d99d6c939..d687b3e76a 100644 --- a/code/citadel/organs/penis.dm +++ b/code/citadel/organs/penis.dm @@ -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' diff --git a/code/citadel/organs/testicles.dm b/code/citadel/organs/testicles.dm index 71e591f930..a759aeab52 100644 --- a/code/citadel/organs/testicles.dm +++ b/code/citadel/organs/testicles.dm @@ -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' diff --git a/code/citadel/organs/vagina.dm b/code/citadel/organs/vagina.dm index c1924a3067..fa1f00bda2 100644 --- a/code/citadel/organs/vagina.dm +++ b/code/citadel/organs/vagina.dm @@ -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" diff --git a/code/citadel/organs/womb.dm b/code/citadel/organs/womb.dm index e1ea02a230..3ebe5c2f98 100644 --- a/code/citadel/organs/womb.dm +++ b/code/citadel/organs/womb.dm @@ -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)